Instruction:
Write a Python 3 script for
converting TDT formatted files to measurements format files Parameters ---------- input_dir_path : str directory with one or more .tdt files experiment: str one of: ["Thellier", "ATRM 6 pos", "NLT"], default "Thellier" meas_file_name : str default "measurements.txt" spec_file_name : str default "specimens.txt" samp_file_name : str default "samples.txt" site_file_name : str default "sites.txt" loc_file_name : str default "locations.txt" user : str default "" location : str default "" lab_dec: int default: 0 lab_inc: int default 90 moment_units : str must be one of: ["mA/m", "emu", "Am^2"], default "mA/m" samp_name_con : str or int {1: "sample=specimen", 2: "no. of terminate characters", 3: "character delimited"} samp_name_chars : str or int number of characters to remove for sample name, (or delimiting character), default 0 site_name_con : str or int {1: "site=sample", 2: "no. of terminate characters", 3: "character delimited"} site_name_chars : str or int number of characters to remove for site name, (or delimiting character), default 0 volume : float volume in cc, default 12 output_dir_path : str path for file output, defaults to input_dir_path Returns --------- tuple : (True if program ran else False, measurement outfile name or error message if failed)

Response:
def tdt(input_dir_path, experiment_name="Thellier", meas_file_name="measurements.txt",
        spec_file_name="specimens.txt", samp_file_name="samples.txt",
        site_file_name="sites.txt", loc_file_name="locations.txt",
        user="", location="", lab_dec=0, lab_inc=90, moment_units="mA/m",
        samp_name_con="sample=specimen", samp_name_chars=0,
        site_name_con="site=sample", site_name_chars=0, volume=12.,
        output_dir_path=""):

    """
    converts TDT formatted files to measurements format files

    Parameters
    ----------
    input_dir_path : str
        directory with one or more .tdt files
    experiment: str
        one of: ["Thellier", "ATRM 6 pos", "NLT"], default "Thellier"
    meas_file_name : str
        default "measurements.txt"
    spec_file_name : str
        default "specimens.txt"
    samp_file_name : str
        default "samples.txt"
    site_file_name : str
        default "sites.txt"
    loc_file_name : str
        default "locations.txt"
    user : str
        default ""
    location : str
        default ""
    lab_dec: int
        default: 0
    lab_inc: int
        default 90
    moment_units : str
        must be one of: ["mA/m", "emu", "Am^2"], default "mA/m"
    samp_name_con : str or int
        {1: "sample=specimen", 2: "no. of terminate characters", 3: "character delimited"}
    samp_name_chars : str or int
        number of characters to remove for sample name, (or delimiting character), default 0
    site_name_con : str or int
        {1: "site=sample", 2: "no. of terminate characters", 3: "character delimited"}
    site_name_chars : str or int
        number of characters to remove for site name, (or delimiting character), default 0
    volume : float
        volume in cc, default 12
    output_dir_path : str
        path for file output, defaults to input_dir_path

    Returns
    ---------
    tuple : (True if program ran else False, measurement outfile name or error message if failed)
    """

    # --------------------------------------
    # Read the files
    #
    # Database structure
    # Thellier_type experiment:
    #
    # 1) Each file contains the data one specimen
    # 2) First line is the header: "Thellier-tdt"
    # 3) Second line in header inlucdes 4 fields:
    #    [Blab] ,[unknown_1] , [unknown_2] , [unknown_3] , [unknown_4]
    # 4) Body includes 5 fields
    #    [specimen_name], [treatments], [moment],[meas_dec],[meas_dec
    # Tretment: XXX.0 (zerofield)
    #           XXX.1 (infield)
    #           XXX.2 (pTRM check)
    #           XXX.3 (Tail check)
    #           XXX.4 (Additivity check; Krasa et al., 2003)
    #           XXX.5 (Original Thellier-Thellier protocol. )
    #                 (where .5 is for the second direction and .1 in the first)
    # XXX = temperature in degrees
    #
    #
    # IMPORTANT ASSUMPTION:
    # (1) lab field is always in Z direction (theta=0, phi=90)
    # (2) Thermal demagnetization - NO MICROWAVE
    # (3) if if XXX <50 then assuming that this is NRM (273K)
    #
    # -------------------------------------
    #
    #   ATRM in six positions
    #
    # Tretment: XXX.0 zerofield
    #           XXX.1 +x
    #           XXX.2 +y
    #           XXX.3 +z
    #           XXX.4 -x
    #           XXX.5 -y
    #           XXX.6 -z
    #           XXX.7 alteration check
    #   IMPORTANT REMARKS:
    #
    # (1) If the program check if the direction of the magnetization fits the coding above
    # if not, an error message will appear
    # (2) Alteration ckeck can be in any direction
    # (3) the order of the measurements is not important
    #

    def get_sample_name(specimen, sample_naming_convention):
        if sample_naming_convention[0] == "sample=specimen":
            sample = specimen
        elif sample_naming_convention[0] == "no. of terminate characters":
            n = int(sample_naming_convention[1])*-1
            sample = specimen[:n]
        elif sample_naming_convention[0] == "charceter delimited":
            d = sample_naming_convention[1]
            sample_splitted = specimen.split(d)
            if len(sample_splitted) == 1:
                sample = sample_splitted[0]
            else:
                sample = d.join(sample_splitted[:-1])
        return sample

    def get_site_name(sample, site_naming_convention):
        if site_naming_convention[0] == "site=sample":
            site = sample
        elif site_naming_convention[0] == "no. of terminate characters":
            n = int(site_naming_convention[1])*-1
            site = sample[:n]
        elif site_naming_convention[0] == "charceter delimited":
            d = site_naming_convention[1]
            site_splitted = sample.split(d)
            if len(site_splitted) == 1:
                site = site_splitted[0]
            else:
                site = d.join(site_splitted[:-1])
        return site

    ## format some variables

    # convert volume from cc to m^3
    volume = float(volume) * 1e-6
    if not output_dir_path:
        output_dir_path = input_dir_path
    samp_name_cons = {1: 'sample=specimen', 2: 'no. of terminate characters', 3: 'character delimited'}
    if not samp_name_con:
        samp_name_con = "sample=specimen"
    elif samp_name_con not in samp_name_cons.values():
        try:
            samp_name_con =  samp_name_cons.get(int(samp_name_con), 'sample=specimen')
        except ValueError:
            samp_name_con="sample=specimen"
    if samp_name_con == 'no. of terminate characters' and not samp_name_chars:
        print("-W- You have selected the sample naming convention: 'no. of terminate characters',\n    but have provided the number of characters as 0.\n    Defaulting to use 'sample=specimen' instead.")
        samp_name_con = 'sample=specimen'

    site_name_cons =  {1: 'site=sample', 2: 'no. of terminate characters', 3: 'character delimited'}
    if not site_name_con:
        site_name_con = "site=sample"
    elif site_name_con not in site_name_cons.values():
        try:
            site_name_con = site_name_cons.get(int(site_name_con), 'site=sample')
        except ValueError:
            site_name_con = "site=sample"
    if site_name_con == 'no. of terminate characters' and not site_name_chars:
        print("-W- You have selected the site naming convention: 'no. of terminate characters',\n    but have provided the number of characters as 0.\n    Defaulting to use 'site=sample' instead.")
        site_name_con = 'site=sample'

    Data = {}

    # -----------------------------------
    # First, read all files and sort data by specimen and by Experiment type
    # -----------------------------------

    for files in os.listdir(input_dir_path):
        if files.endswith(".tdt"):
            fname = os.path.join(input_dir_path, files)
            print("Open file: ", fname)
            fin = open(fname, 'r')
            header_codes = ['labfield', 'core_azimuth',
                            'core_plunge', 'bedding_dip_direction', 'bedding_dip']
            body_codes = ['specimen_name',
                          'treatment', 'moment', 'dec', 'inc']
            tmp_body = []
            tmp_header_data = {}
            line_number = 0
            continue_reading = True
            line = fin.readline()  # ignore first line
            lines = fin.readlines()
            fin.close()
            for line in lines:

                if "END" in line:
                    break

                if line.strip('\n') == "":
                    break

                this_line = line.strip('\n').split()

                if len(this_line) < 5:
                    continue

                # ---------------------------------------------------
                # fix muxworthy funky data format
                # ---------------------------------------------------
                if len(this_line) < 5 and line_number != 0:
                    new_line = []
                    for i in range(len(this_line)):
                        if i > 1 and "-" in this_line[i]:
                            tmp = this_line[i].replace("-", " -")
                            tmp1 = tmp.split()
                            for i in range(len(tmp1)):
                                new_line.append(tmp1[i])
                        else:
                            new_line.append(this_line[i])
                    this_line = list(copy(new_line))

                # -------------------------------
                # Read infromation from Header and body
                # The data is stored in a dictionary:
                # Data[specimen][Experiment_Type]['header_data']=tmp_header_data  --> a dictionary with header data
                # Data[specimen][Experiment_Type]['meas_data']=[dict1, dict2, ...] --> a list of dictionaries with measurement data
                # -------------------------------

                # ---------------------------------------------------
                # header
                # ---------------------------------------------------
                if line_number == 0:

                    for i in range(len(this_line)):
                        tmp_header_data[header_codes[i]] = this_line[i]

                    line_number += 1

                # ---------------------------------------------------
                # body
                # ---------------------------------------------------

                else:
                    tmp_data = {}
                    for i in range(min(len(this_line), len(body_codes))):
                        tmp_data[body_codes[i]] = this_line[i]
                    tmp_body.append(tmp_data)

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

                    specimen = tmp_body[0]['specimen_name']
                    line_number += 1

            if specimen not in list(Data.keys()):
                Data[specimen] = {}
            Experiment_Type = experiment_name
            if Experiment_Type not in list(Data[specimen].keys()):
                Data[specimen][Experiment_Type] = {}
            Data[specimen][Experiment_Type]['meas_data'] = tmp_body
            Data[specimen][Experiment_Type]['header_data'] = tmp_header_data
            Data[specimen][Experiment_Type]['sample_naming_convention'] = [samp_name_con, samp_name_chars]
            Data[specimen][Experiment_Type]['site_naming_convention'] = [site_name_con, site_name_chars]
            Data[specimen][Experiment_Type]['location'] = location
            Data[specimen][Experiment_Type]['user_name'] = user
            Data[specimen][Experiment_Type]['volume'] = volume
            Data[specimen][Experiment_Type]['moment_units'] = moment_units
            Data[specimen][Experiment_Type]['labfield_DI'] = [lab_dec, lab_inc]

    # -----------------------------------
    # Convert Data{} to MagIC
    # -----------------------------------
    MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
    specimens_list = list(Data.keys())
    specimens_list.sort()
    for specimen in specimens_list:
        Experiment_Types_list = list(Data[specimen].keys())
        Experiment_Types_list.sort()
        for Experiment_Type in Experiment_Types_list:
            if Experiment_Type in ["Thellier"]:

                tmp_MeasRecs = []

                # IMORTANT:
                # phi and theta of lab field are not defined
                # defaults are defined here:
                phi, theta = '0.', '90.'

                header_line = Data[specimen][Experiment_Type]['header_data']
                experiment_treatments = []
                measurement_running_number = 0
                # start to make a list of the methcodes. and later will merge it to one string
                methcodes = ["LP-PI-TRM"]

                for i in range(len(Data[specimen][Experiment_Type]['meas_data'])):
                    meas_line = Data[specimen][Experiment_Type]['meas_data'][i]

                    # ------------------
                    # check if the same treatment appears more than once. If yes, assuming that the measurements is repeated twice,
                    # ignore the first, and take only the second one
                    # ------------------

                    if i < (len(Data[specimen][Experiment_Type]['meas_data'])-2):
                        Repeating_measurements = True
                        for key in ['treatment', 'specimen_name']:
                            if Data[specimen][Experiment_Type]['meas_data'][i][key] != Data[specimen][Experiment_Type]['meas_data'][i+1][key]:
                                Repeating_measurements = False
                        if Repeating_measurements == True:
                            "Found a repeating measurement at line %i, sample %s. taking the last one" % (
                                i, specimen)
                            continue
                    # ------------------
                    # Special treatment for first line (NRM data).
                    # ------------------

                    if i == 0:
                        if "." not in meas_line['treatment']:
                            meas_line['treatment'] = "0.0"
                        # if NRM is in the form of ".0" instead of "0.0"
                        elif meas_line['treatment'].split(".")[0] == "" and meas_line['treatment'].split(".")[1] == '0':
                            meas_line['treatment'] = "0.0"
                        # if NRM is in the form of "20.0" instead of "0.0"
                        elif float(meas_line['treatment'].split(".")[0]) < 50 and float(meas_line['treatment'].split(".")[-1]) == 0:
                            meas_line['treatment'] = "0.0"

                    # ------------------
                    # fix line in format of XX instead of XX.YY
                    # ------------------
                    if "." not in meas_line['treatment']:
                        meas_line['treatment'] = meas_line['treatment']+".0"
                    if meas_line['treatment'].split(".")[1] == "":
                        meas_line['treatment'] = meas_line['treatment']+"0"

                    # ------------------
                    # init names and dictionaries
                    # ------------------

                    MeasRec, SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}, {}

                    # convert from microT to Tesla
                    labfield = float(header_line['labfield'])*1e-6
                    sample = get_sample_name(
                        specimen, Data[specimen][Experiment_Type]['sample_naming_convention'])
                    site = get_site_name(
                        sample, Data[specimen][Experiment_Type]['site_naming_convention'])
                    location = Data[specimen][Experiment_Type]['location']
                    if location == '':
                        location = 'unknown'

                    # ------------------
                    # Fill data
                    # ------------------

                    # Start with S'tables and Loc Table
                    if specimen != "" and specimen not in [x['specimen'] if 'specimen' in list(x.keys()) else "" for x in SpecRecs]:
                        SpecRec['specimen'] = specimen
                        SpecRec['sample'] = sample
                        SpecRec['volume'] = Data[specimen][Experiment_Type]['volume']
                        SpecRec['citations'] = "This study"
                        SpecRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SpecRecs.append(SpecRec)
                    if sample != "" and sample not in [x['sample'] if 'sample' in list(x.keys()) else "" for x in SampRecs]:
                        SampRec['sample'] = sample
                        SampRec['site'] = site
                        SampRec['citations'] = "This study"
                        SampRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SampRecs.append(SampRec)
                    if site != "" and site not in [x['site'] if 'site' in list(x.keys()) else "" for x in SiteRecs]:
                        SiteRec['site'] = site
                        SiteRec['location'] = location
                        SiteRec['citations'] = "This study"
                        SiteRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SiteRecs.append(SiteRec)
                    if location != "" and location not in [x['location'] if 'location' in list(x.keys()) else "" for x in LocRecs]:
                        LocRec['location'] = location
                        LocRec['citations'] = "This study"
                        LocRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        LocRecs.append(LocRec)

                    # now the measurement Rec
                    MeasRec['citations'] = "This study"
                    # experiment is set in pmag.measurements_methods3
                    # MeasRec["experiments"]=""
                    MeasRec["specimen"] = specimen
                    MeasRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                    MeasRec["quality"] = 'g'
                    MeasRec["standard"] = 'u'
                    MeasRec["treat_step_num"] = "%i" % measurement_running_number
                    MeasRec["dir_dec"] = meas_line['dec']
                    MeasRec["dir_inc"] = meas_line['inc']
                    if Data[specimen][Experiment_Type]['moment_units'] == 'mA/m':
                        MeasRec["magn_moment"] = "%5e" % (float(meas_line['moment'])*1e-3*float(
                            Data[specimen][Experiment_Type]['volume']))  # converted to Am^2
                    if Data[specimen][Experiment_Type]['moment_units'] == 'emu':
                        MeasRec["magn_moment"] = "%5e" % (
                            float(meas_line['moment'])*1e-3)  # converted to Am^2
                    if Data[specimen][Experiment_Type]['moment_units'] == 'Am^2':
                        MeasRec["magn_moment"] = "%5e" % (
                            float(meas_line['moment']))  # converted to Am^2
                    MeasRec["meas_temp"] = '273.'  # room temp in kelvin

                    # Date and time
##                                    date=meas_line['Measurement Date'].strip("\"").split('-')
# yyyy=date[2];dd=date[1];mm=date[0]
##                                    hour=meas_line['Measurement Time'].strip("\"")
# MeasRec["measurement_date"]=yyyy+':'+mm+":"+dd+":"+hour

                    # lab field data: distinguish between PI experiments to AF/Thermal
                    treatments = meas_line['treatment'].split(".")
                    if float(treatments[1]) == 0:
                        MeasRec["treat_dc_field"] = '0'
                        MeasRec["treat_dc_field_phi"] = '0'
                        MeasRec["treat_dc_field_theta"] = '0'
                    else:
                        MeasRec["treat_dc_field"] = '%8.3e' % (labfield)
                        MeasRec["treat_dc_field_phi"] = Data[specimen][Experiment_Type]['labfield_DI'][0]
                        MeasRec["treat_dc_field_theta"] = Data[specimen][Experiment_Type]['labfield_DI'][1]

                    # ------------------
                    # Lab Treatments
                    # ------------------

                    # NRM
                    if float(treatments[0]) == 0 and float(treatments[1]) == 0:
                        MeasRec["method_codes"] = "LT-NO"
                        experiment_treatments.append('0')
                        MeasRec["treat_temp"] = '273.'
                        IZorZI = ""

                    # Zerofield step
                    elif float(treatments[1]) == 0:
                        MeasRec["method_codes"] = "LT-T-Z"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin

                        #  check if this is ZI or IZ:
                        for j in range(0, i):
                            previous_lines = Data[specimen][Experiment_Type]['meas_data'][j]
                            if previous_lines['treatment'].split(".")[0] == meas_line['treatment'].split(".")[0]:
                                if float(previous_lines['treatment'].split(".")[1]) == 1 or float(previous_lines['treatment'].split(".")[1]) == 10:
                                    if "LP-PI-TRM-IZ" not in methcodes:
                                        methcodes.append("LP-PI-TRM-IZ")
                                    IZorZI = ""
                                else:
                                    IZorZI = "Z"

                    # Infield step
                    elif float(treatments[1]) == 1 or float(treatments[1]) == 10:
                        MeasRec["method_codes"] = "LT-T-I"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin

                        # check if this is ZI,IZ:
                        for j in range(0, i):
                            previous_lines = Data[specimen][Experiment_Type]['meas_data'][j]
                            if previous_lines['treatment'].split(".")[0] == meas_line['treatment'].split(".")[0]:
                                if float(previous_lines['treatment'].split(".")[1]) == 0:
                                    if "LP-PI-TRM-ZI" not in methcodes:
                                        methcodes.append("LP-PI-TRM-ZI")
                                        IZorZI = ""
                                else:
                                    IZorZI = "I"
                    # pTRM check step
                    elif float(treatments[1]) == 2 or float(treatments[1]) == 20:
                        MeasRec["method_codes"] = "LT-PTRM-I"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin
                        if "LP-PI-ALT" not in methcodes:
                            methcodes.append("LP-PI-ALT")

                    # Tail check step
                    elif float(treatments[1]) == 3 or float(treatments[1]) == 30:
                        MeasRec["method_codes"] = "LT-PTRM-MD"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin
                        if "LP-PI-BT-MD" not in methcodes:
                            methcodes.append("LP-PI-BT-MD")
                            MeasRec["treat_dc_field"] = "0"
                            MeasRec["treat_dc_field_phi"] = "0"
                            MeasRec["treat_dc_field_theta"] = "0"

                    # Additivity check step
                    elif float(treatments[1]) == 4 or float(treatments[1]) == 40:
                        MeasRec["method_codes"] = "LT-PTRM-AC"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin
                        if "LP-PI-BT" not in methcodes:
                            methcodes.append("LP-PI-BT")

                    # Thellier Thellier protocol (1 for one direction and 5 for the antiparallel)
                    # Lab field direction of 1 is as put in the GUI dialog box
                    # Lab field direction of 5 is the anti-parallel direction of 1

                    elif float(treatments[1]) == 5 or float(treatments[1]) == 50:
                        MeasRec["method_codes"] = "LT-T-I"
                        MeasRec["treat_temp"] = '%8.3e' % (
                            float(treatments[0])+273.)  # temp in kelvin
                        MeasRec["treat_dc_field_phi"] = "%.2f" % (
                            (float(Data[specimen][Experiment_Type]['labfield_DI'][0])+180.) % 360.)
                        MeasRec["treat_dc_field_theta"] = "%.2f" % (
                            float(Data[specimen][Experiment_Type]['labfield_DI'][1])*-1.)
                        if "LP-PI-II" not in methcodes:
                            methcodes.append("LP-PI-II")

                    else:
                        print("-E- ERROR in file %s" % Experiment_Type)
                        print("-E- ERROR in treatment ",
                              meas_line['treatment'])
                        print("... exiting until you fix the problem")

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

                    # MeasRec["method_codes"]=lab_treatment+":"+lab_protocols_string
                    # MeasRec["experiments"]=specimen+":"+lab_protocols_string

                    tmp_MeasRecs.append(MeasRec)
                    measurement_running_number += 1

                # arrange method_codes and experiments:
                method_codes = "LP-PI-TRM"
                # Coe mothod
                if "LP-PI-TRM-ZI" in methcodes and "LP-PI-TRM-IZ" not in methcodes and "LP-PI-II" not in methcodes:
                    method_codes = method_codes+":LP-PI-TRM-ZI"
                if "LP-PI-TRM-ZI" not in methcodes and "LP-PI-TRM-IZ" in methcodes and "LP-PI-II" not in methcodes:
                    method_codes = method_codes+":LP-PI-TRM-IZ"
                if "LP-PI-TRM-ZI" in methcodes and "LP-PI-TRM-IZ" in methcodes and "LP-PI-II" not in methcodes:
                    method_codes = method_codes+":LP-PI-BT-IZZI"
                if "LP-PI-II" in methcodes:
                    method_codes = method_codes+":LP-PI-II"
                if "LP-PI-ALT" in methcodes:
                    method_codes = method_codes+":LP-PI-ALT"
                if "LP-PI-BT-MD" in methcodes:
                    method_codes = method_codes+":LP-PI-BT-MD"
                if "LP-PI-BT" in methcodes:
                    method_codes = method_codes+":LP-PI-BT"
                for i in range(len(tmp_MeasRecs)):
                    STRING = ":".join(
                        [tmp_MeasRecs[i]["method_codes"], method_codes])
                    tmp_MeasRecs[i]["method_codes"] = STRING
                    # experiment is set in pmag.measurements_methods3
                    # STRING=":".join([tmp_MeasRecs[i]["specimen"],method_codes])
                    # tmp_MeasRecs[i]["experiments"]=STRING
                    MeasRecs.append(tmp_MeasRecs[i])

            elif Experiment_Type in ["ATRM 6 positions"]:

                tmp_MeasRecs = []

                header_line = Data[specimen][Experiment_Type]['header_data']
                experiment_treatments = []
                measurement_running_number = 0
                # start to make a list of the methcodes. and later will merge it to one string
                methcodes = ["LP-AN-TRM"]

                for i in range(len(Data[specimen][Experiment_Type]['meas_data'])):
                    meas_line = Data[specimen][Experiment_Type]['meas_data'][i]

                    # ------------------
                    # check if the same treatment appears more than once. If yes, assuming that the measurements is repeated twice,
                    # ignore the first, and take only the second one
                    # ------------------

                    if i < (len(Data[specimen][Experiment_Type]['meas_data'])-2):
                        Repeating_measurements = True
                        for key in ['treatment', 'specimen_name']:
                            if Data[specimen][Experiment_Type]['meas_data'][i][key] != Data[specimen][Experiment_Type]['meas_data'][i+1][key]:
                                Repeating_measurements = False
                        if Repeating_measurements == True:
                            "Found a repeating measurement at line %i, sample %s. taking the last one" % (
                                i, specimen)
                            continue

                    # ------------------
                    # fix line in format of XX instead of XX.0
                    # ------------------
                    if "." not in meas_line['treatment']:
                        meas_line['treatment'] = meas_line['treatment']+".0"
                    if meas_line['treatment'].split(".")[1] == "":
                        meas_line['treatment'] = meas_line['treatment']+"0"

                    # ------------------
                    # init names and dictionaries
                    # ------------------

                    MeasRec, SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}, {}

                    # convert from microT to Tesla
                    labfield = float(header_line['labfield'])*1e-6
                    sample = get_sample_name(
                        specimen, Data[specimen][Experiment_Type]['sample_naming_convention'])
                    site = get_site_name(
                        sample, Data[specimen][Experiment_Type]['site_naming_convention'])
                    location = Data[specimen][Experiment_Type]['location']

                    # ------------------
                    # Fill data
                    # ------------------

                    # Start with S'tables and Loc Table
                    if specimen != "" and specimen not in [x['specimen'] if 'specimen' in list(x.keys()) else "" for x in SpecRecs]:
                        SpecRec['specimen'] = specimen
                        SpecRec['sample'] = sample
                        SpecRec['volume'] = Data[specimen][Experiment_Type]['volume']
                        SpecRec['citations'] = "This study"
                        SpecRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SpecRecs.append(SpecRec)
                    if sample != "" and sample not in [x['sample'] if 'sample' in list(x.keys()) else "" for x in SampRecs]:
                        SampRec['sample'] = sample
                        SampRec['site'] = site
                        SampRec['citations'] = "This study"
                        SampRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SampRecs.append(SampRec)
                    if site != "" and site not in [x['site'] if 'site' in list(x.keys()) else "" for x in SiteRecs]:
                        SiteRec['site'] = site
                        SiteRec['location'] = location
                        SiteRec['citations'] = "This study"
                        SiteRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        SiteRecs.append(SiteRec)
                    if location != "" and location not in [x['location'] if 'location' in list(x.keys()) else "" for x in LocRecs]:
                        LocRec['location'] = location
                        LocRec['citations'] = "This study"
                        LocRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                        LocRecs.append(LocRec)

                    # Meas data now
                    MeasRec["specimen"] = specimen
                    MeasRec['analysts'] = Data[specimen][Experiment_Type]['user_name']
                    MeasRec['citations'] = "This study"
                    MeasRec["quality"] = 'g'
                    MeasRec["standard"] = 'u'
                    MeasRec["treat_step_num"] = "%i" % measurement_running_number
                    MeasRec["dir_dec"] = meas_line['dec']
                    MeasRec["dir_inc"] = meas_line['inc']
                    MeasRec["magn_moment"] = "%5e" % (float(meas_line['moment'])*1e-3*float(
                        Data[specimen][Experiment_Type]['volume']))  # converted to Am^2
                    MeasRec["meas_temp"] = '273.'  # room temp in kelvin

                    treatments = meas_line['treatment'].split(".")
                    if len(treatments[1]) > 1:
                        treatments[1] = treatments[1][0]

                    MeasRec["treat_temp"] = '%8.3e' % (
                        float(treatments[0])+273.)  # temp in kelvin

                    # labfield direction
                    if float(treatments[1]) == 0:
                        MeasRec["treat_dc_field"] = '0'
                        MeasRec["treat_dc_field_phi"] = '0'
                        MeasRec["treat_dc_field_theta"] = '0'
                        MeasRec["method_codes"] = "LT-T-Z:LP-AN-TRM"
                    else:

                        MeasRec["treat_dc_field"] = '%8.3e' % (labfield)

                        # alteration check as final measurement
                        if float(treatments[1]) == 7 or float(treatments[1]) == 70:
                            MeasRec["method_codes"] = "LT-PTRM-I:LP-AN-TRM"
                        else:
                            MeasRec["method_codes"] = "LT-T-I:LP-AN-TRM"

                        # find the direction of the lab field in two ways:
                        # (1) using the treatment coding (XX.1=+x, XX.2=+y, XX.3=+z, XX.4=-x, XX.5=-y, XX.6=-z)
                        # atrm declination/inlclination order
                        tdec = [0, 90, 0, 180, 270, 0, 0, 90, 0]
                        # atrm declination/inlclination order
                        tinc = [0, 0, 90, 0, 0, -90, 0, 0, 90]

                        ipos_code = int(treatments[1])-1
                        # (2) using the magnetization
                        DEC = float(MeasRec["dir_dec"])
                        INC = float(MeasRec["dir_inc"])
                        if INC < 45 and INC > -45:
                            if DEC > 315 or DEC < 45:
                                ipos_guess = 0
                            if DEC > 45 and DEC < 135:
                                ipos_guess = 1
                            if DEC > 135 and DEC < 225:
                                ipos_guess = 3
                            if DEC > 225 and DEC < 315:
                                ipos_guess = 4
                        else:
                            if INC > 45:
                                ipos_guess = 2
                            if INC < -45:
                                ipos_guess = 5
                        # prefer the guess over the code
                        ipos = ipos_guess
                        MeasRec["treat_dc_field_phi"] = '%7.1f' % (
                            tdec[ipos])
                        MeasRec["treat_dc_field_theta"] = '%7.1f' % (
                            tinc[ipos])
                        # check it
                        if ipos_guess != ipos_code and treatments[1] != '7':
                            print("-E- ERROR: check specimen %s step %s, ATRM measurements, coding does not match the direction of the lab field!" % (
                                MeasRec["specimen"], ".".join(list(treatments))))

                    MeasRecs.append(MeasRec)
                    measurement_running_number += 1

            else:
                print(
                    "-E- ERROR. sorry, file format %s is not supported yet. Please contact rshaar@ucsd.edu" % Experiment_Type)

    # -------------------------------------------
    #  measurements.txt
    # -------------------------------------------

    con = cb.Contribution(output_dir_path, read_tables=[])

    con.add_magic_table_from_data(dtype='specimens', data=SpecRecs)
    con.add_magic_table_from_data(dtype='samples', data=SampRecs)
    con.add_magic_table_from_data(dtype='sites', data=SiteRecs)
    con.add_magic_table_from_data(dtype='locations', data=LocRecs)
    MeasOuts = pmag.measurements_methods3(MeasRecs, noave=False)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)
    con.write_table_to_file('specimens', spec_file_name)
    con.write_table_to_file('samples', samp_file_name)
    con.write_table_to_file('sites', site_file_name)
    con.write_table_to_file('locations', loc_file_name)
    meas_file = con.write_table_to_file('measurements', meas_file_name)
    return True, meas_file


Instruction:
Make a summary of the following Python 3 code
def utrecht(mag_file, dir_path=".",  input_dir_path="", meas_file="measurements.txt",
            spec_file="specimens.txt", samp_file="samples.txt", site_file="sites.txt",
            loc_file="locations.txt", location="unknown", lat="", lon="", dmy_flag=False,
            noave=False, meas_n_orient=8, meth_code="LP-NO", specnum=1, samp_con='2',
            labfield=0, phi=0, theta=0):
    """
    Converts Utrecht magnetometer data files to MagIC files

    Parameters
    ----------
    mag_file : str
        input file name
    dir_path : str
        working directory, default "."
    input_dir_path : str
        input file directory IF different from dir_path, default ""
    spec_file : str
        output specimen file name, default "specimens.txt"
    samp_file: str
        output sample file name, default "samples.txt"
    site_file : str
        output site file name, default "sites.txt"
    loc_file : str
        output location file name, default "locations.txt"
    append : bool
        append output files to existing files instead of overwrite, default False
    location : str
        location name, default "unknown"
    lat : float
        latitude, default ""
    lon : float
        longitude, default ""
    dmy_flag : bool
        default False
    noave : bool
       do not average duplicate measurements, default False (so by default, DO average)
    meas_n_orient : int
        Number of different orientations in measurement (default : 8)
    meth_code : str
        sample method codes, default "LP-NO"
        e.g. [SO-MAG, SO-SUN, SO-SIGHT, ...]
    specnum : int
        number of characters to designate a specimen, default 0
    samp_con : str
        sample/site naming convention, default '2', see info below
    labfield : float
        DC_FIELD in microTesla (default : 0)
    phi : float
        DC_PHI in degrees (default : 0)
    theta : float
        DC_THETA in degrees (default : 0)

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

    Info
    ---------
    Sample naming convention:
        [1] XXXXY: where XXXX is an arbitrary length site designation and Y
            is the single character sample designation.  e.g., TG001a is the
            first sample from site TG001.    [default]
        [2] XXXX-YY: YY sample from site XXXX (XXX, YY of arbitary length)
        [3] XXXX.YY: YY sample from site XXXX (XXX, YY of arbitary length)
        [4-Z] XXXX[YYY]:  YYY is sample designation with Z characters from site XXX
        [5] site name = sample name
        [6] site name entered in site_name column in the orient.txt format input file  -- NOT CURRENTLY SUPPORTED
        [7-Z] [XXX]YYY:  XXX is site designation with Z characters from samples  XXXYYY

    """
    # initialize some stuff
    version_num = pmag.get_version()
    MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, dir_path)
    specnum = -int(specnum)
    if "4" in samp_con:
        if "-" not in samp_con:
            print("option [4] must be in form 4-Z where Z is an integer")
            return False, "naming convention option [4] must be in form 4-Z where Z is an integer"
        else:
            site_num = samp_con.split("-")[1]
            samp_con = "4"
    elif "7" in samp_con:
        if "-" not in samp_con:
            print("option [7] must be in form 7-Z where Z is an integer")
            return False, "naming convention option [7] must be in form 7-Z where Z is an integer"
        else:
            site_num = samp_con.split("-")[1]
            samp_con = "7"
    else:
        site_num = 1
    try:
        DC_FIELD = float(labfield)*1e-6
        DC_PHI = float(phi)
        DC_THETA = float(theta)
    except ValueError:
        raise ValueError(
            'problem with your dc parameters. please provide a labfield in microTesla and a phi and theta in degrees.')

    # format variables
    if not mag_file:
        return False, 'You must provide a Utrecht format file'
    mag_file = pmag.resolve_file_name(mag_file, input_dir_path)
    # need to add these
    meas_file = pmag.resolve_file_name(meas_file, output_dir_path)
    spec_file = pmag.resolve_file_name(spec_file, output_dir_path)
    samp_file = pmag.resolve_file_name(samp_file, output_dir_path)
    site_file = pmag.resolve_file_name(site_file, output_dir_path)
    loc_file = pmag.resolve_file_name(loc_file, output_dir_path)

    # parse data

    # Open up the Utrecht file and read the header information
    AF_or_T = mag_file.split('.')[-1]
    data = open(mag_file, 'r')
    line = data.readline()
    line_items = line.split(',')
    operator = line_items[0]
    operator = operator.replace("\"", "")
    machine = line_items[1]
    machine = machine.replace("\"", "")
    machine = machine.rstrip('\n')
#    print("operator=", operator)
#    print("machine=", machine)

    # read in measurement data
    line = data.readline()
    while line != "END" and line != '"END"':
        SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}
        line_items = line.split(',')
        spec_name = line_items[0]
        spec_name = spec_name.replace("\"", "")
#        print("spec_name=", spec_name)
        free_string = line_items[1]
        free_string = free_string.replace("\"", "")
#        print("free_string=", free_string)
        dec = line_items[2]
#        print("dec=", dec)
        inc = line_items[3]
#        print("inc=", inc)
        volume = float(line_items[4])
        volume = volume * 1e-6  # enter volume in cm^3, convert to m^3
#        print("volume=", volume)
        bed_plane = line_items[5]
#        print("bed_plane=", bed_plane)
        bed_dip = line_items[6]
#        print("bed_dip=", bed_dip)

        # Configure et er_ tables
        if specnum == 0:
            sample_name = spec_name
        else:
            sample_name = spec_name[:specnum]
        site = pmag.parse_site(sample_name, samp_con, site_num)
        SpecRec['specimen'] = spec_name
        SpecRec['sample'] = sample_name
        if volume != 0:
            SpecRec['volume'] = volume
        SpecRecs.append(SpecRec)
        if sample_name != "" and sample_name not in [x['sample'] if 'sample' in list(x.keys()) else "" for x in SampRecs]:
            SampRec['sample'] = sample_name
            SampRec['azimuth'] = dec
            SampRec['dip'] = str(float(inc)-90)
            SampRec['bed_dip_direction'] = bed_plane
            SampRec['bed_dip'] = bed_dip
            SampRec['method_codes'] = meth_code
            SampRec['site'] = site
            SampRecs.append(SampRec)
        if site != "" and site not in [x['site'] if 'site' in list(x.keys()) else "" for x in SiteRecs]:
            SiteRec['site'] = site
            SiteRec['location'] = location
            SiteRec['lat'] = lat
            SiteRec['lon'] = lon
            SiteRecs.append(SiteRec)
        if location != "" and location not in [x['location'] if 'location' in list(x.keys()) else "" for x in LocRecs]:
            LocRec['location'] = location
            LocRec['lat_n'] = lat
            LocRec['lon_e'] = lon
            LocRec['lat_s'] = lat
            LocRec['lon_w'] = lon
            LocRecs.append(LocRec)

        # measurement data
        line = data.readline()
        line = line.rstrip("\n")
        items = line.split(",")
        while line != '9999':
            step = items[0]
            step = step.split('.')
            step_value = step[0]
            step_type = ""
            if len(step) == 2:
                step_type = step[1]
            if step_type == '5':
                step_value = items[0]
            A = float(items[1])
            B = float(items[2])
            C = float(items[3])
#  convert to MagIC coordinates
            Z = -A
            X = -B
            Y = C
            cart = np.array([X, Y, Z]).transpose()
            direction = pmag.cart2dir(cart).transpose()
            measurement_dec = direction[0]
            measurement_inc = direction[1]
            # the data are in pico-Am^2 - this converts to Am^2
            magn_moment = direction[2] * 1.0e-12
            if volume != 0:
                # data volume normalized - converted to A/m
                magn_volume = direction[2] * 1.0e-12 / volume
#            print("magn_moment=", magn_moment)
#            print("magn_volume=", magn_volume)
            error = items[4]
            date = items[5]
            date = date.strip('"').replace(' ', '')
            if date.count("-") > 0:
                date = date.split("-")
            elif date.count("/") > 0:
                date = date.split("/")
            else:
                print("date format seperator cannot be identified")
#            print(date)
            time = items[6]
            time = time.strip('"').replace(' ', '')
            time = time.split(":")
#            print(time)
            dt = date[0] + ":" + date[1] + ":" + date[2] + \
                ":" + time[0] + ":" + time[1] + ":" + "0"
            local = pytz.timezone("Europe/Amsterdam")
            try:
                if dmy_flag:
                    naive = datetime.datetime.strptime(dt, "%d:%m:%Y:%H:%M:%S")
                else:
                    naive = datetime.datetime.strptime(dt, "%m:%d:%Y:%H:%M:%S")
            except ValueError:
                try:
                    naive = datetime.datetime.strptime(dt, "%Y:%m:%d:%H:%M:%S")
                except ValueError:
                    print('-W- Could not parse date format')
                    return False, 'Could not parse date format'
            local_dt = local.localize(naive, is_dst=None)
            utc_dt = local_dt.astimezone(pytz.utc)
            timestamp = utc_dt.strftime("%Y-%m-%dT%H:%M:%S")+"Z"
#            print(timestamp)

            MeasRec = {}
            MeasRec["timestamp"] = timestamp
            MeasRec["analysts"] = operator
            MeasRec["instrument_codes"] = "Utrecht_" + machine
            MeasRec["description"] = "free string = " + free_string
            MeasRec["citations"] = "This study"
            MeasRec['software_packages'] = version_num
            MeasRec["meas_temp"] = '%8.3e' % (273)  # room temp in kelvin
            MeasRec["quality"] = 'g'
            MeasRec["standard"] = 'u'
            # will be overwritten by measurements_methods3
            MeasRec["experiment"] = location + site + spec_name
            MeasRec["treat_step_num"] = location + site + spec_name + items[0]
            MeasRec["specimen"] = spec_name
            # MeasRec["treat_ac_field"] = '0'
            if AF_or_T.lower() == "th":
                MeasRec["treat_temp"] = '%8.3e' % (
                    float(step_value)+273.)  # temp in kelvin
                MeasRec['treat_ac_field'] = '0'
                lab_treat_type = "T"
            else:
                MeasRec['treat_temp'] = '273'
                MeasRec['treat_ac_field'] = '%10.3e' % (float(step_value)*1e-3)
                lab_treat_type = "AF"
            MeasRec['treat_dc_field'] = '0'
            if step_value == '0':
                meas_type = "LT-NO"
#            print("step_type=", step_type)
            if step_type == '0' or step_type == '00':
                meas_type = "LT-%s-Z" % lab_treat_type
            elif step_type == '1' or step_type == '11':
                meas_type = "LT-%s-I" % lab_treat_type
                MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
            elif step_type == '2' or step_type == '12':
                meas_type = "LT-PTRM-I"
                MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
            elif step_type == '3' or step_type == '13':
                meas_type = "LT-PTRM-Z"
#            print("meas_type=", meas_type)
            MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
            MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
            MeasRec['method_codes'] = meas_type
            MeasRec["magn_moment"] = magn_moment
            if volume != 0:
                MeasRec["magn_volume"] = magn_volume
            MeasRec["dir_dec"] = measurement_dec
            MeasRec["dir_inc"] = measurement_inc
            MeasRec['dir_csd'] = error
            MeasRec['meas_n_orient'] = meas_n_orient
#            print(MeasRec)
            MeasRecs.append(MeasRec)

            line = data.readline()
            line = line.rstrip("\n")
            items = line.split(",")
        line = data.readline()
        line = line.rstrip("\n")
        items = line.split(",")

    data.close()

    con = cb.Contribution(output_dir_path, read_tables=[])

    con.add_magic_table_from_data(dtype='specimens', data=SpecRecs)
    con.add_magic_table_from_data(dtype='samples', data=SampRecs)
    con.add_magic_table_from_data(dtype='sites', data=SiteRecs)
    con.add_magic_table_from_data(dtype='locations', data=LocRecs)
    # figures out method codes for measuremet data
    MeasOuts = pmag.measurements_methods3(MeasRecs, noave)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)

    con.tables['specimens'].write_magic_file(custom_name=spec_file)
    con.tables['samples'].write_magic_file(custom_name=samp_file)
    con.tables['sites'].write_magic_file(custom_name=site_file)
    con.tables['locations'].write_magic_file(custom_name=loc_file)
    con.tables['measurements'].write_magic_file(custom_name=meas_file)

    return True, meas_file

Response: This function converts Utrecht magnetometer data files to MagIC files.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def make_thing():
    cwd = os.getcwd()
    main_dir = cwd + '/SPD'
    try:
        import new_lj_thellier_gui_spd as tgs
        gui = tgs.Arai_GUI('/magic_measurements.txt', main_dir)
        specimens = list(gui.Data.keys())
        thing = PintPars(gui.Data, '0238x6011044', 473., 623.)
        thing.calculate_all_statistics()
        #new_thing = PintPars(gui.Data, '0238x5721062', 100. + 273., 525. + 273.)
        #new_thing.calculate_all_statistics()
        gui2 = tgs.Arai_GUI('/magic_measurements.txt', '/Users/nebula/Desktop/MagIC_experiments/ODP-SBG_1')
        thing2 = PintPars(gui2.Data, '0335x1031411', 273., 743.)
        return thing, thing2
    except Exception as ex:
        print('could not make standard specimen objects')
        print(ex)

Response: make example PintPars object


Instruction:
Write a Python 3 function for
getting the dec and inc from the PTRMS table

Response:
def get_ptrm_dec_and_inc(self):
        """not included in spd."""
        PTRMS = self.PTRMS[1:]
        CART_pTRMS_orig = numpy.array([lib_direct.dir2cart(row[1:4]) for row in PTRMS])
        #B_lab_dir = [self.B_lab_dir[0], self.B_lab_dir[1], 1.] # dir
        tmin, tmax = self.t_Arai[0], self.t_Arai[-1]
        ptrms_dec_Free, ptrms_inc_Free, ptrm_best_fit_vector_Free, ptrm_tau_Free, ptrm_v_Free, ptrm_mass_center_Free, ptrm_PCA_sigma_Free = lib_direct.get_dec_and_inc(CART_pTRMS_orig, self.t_Arai, tmin, tmax, anchored=False)
        ptrms_angle = lib_direct.get_ptrms_angle(ptrm_best_fit_vector_Free, self.B_lab_cart)
        self.pars['ptrms_dec_Free'], self.pars['ptrms_inc_Free'] = ptrms_dec_Free, ptrms_inc_Free
        self.pars['ptrms_tau_Free'] = ptrm_tau_Free
        self.pars['ptrms_angle_Free'] = ptrms_angle


Instruction:
Can you generate a brief explanation for the following Python 3 code
def main():

#
# parse command line options
#

    if '-h' in sys.argv:
        print(main.__doc__)
        sys.exit()
    dir_path = pmag.get_named_arg("-WD", default_val=".")
    input_dir_path = pmag.get_named_arg('-ID', "")
    input_dir_path, dir_path = pmag.fix_directories(input_dir_path, dir_path)
    meas_file = pmag.get_named_arg(
        "-f", default_val="measurements.txt")
    #spec_file = pmag.get_named_arg(
    #    "-fsp", default_val="specimens.txt")
    #crit_file = pmag.get_named_arg("-fcr", default_val="criteria.txt")
    #spec_file = os.path.join(dir_path, spec_file)
    #crit_file = os.path.join(dir_path, crit_file)
    meas_file = pmag.resolve_file_name(meas_file, input_dir_path)
    fmt = pmag.get_named_arg("-fmt", "svg")
    save_plots = False
    interactive = True
    if '-sav' in sys.argv:
        save_plots = True
        interactive=False
    spec = pmag.get_named_arg("-spc", default_val="")
    n_specs = pmag.get_named_arg("-n", default_val="all")
    try:
        n_specs = int(n_specs)
    except ValueError:
        pass
    ipmag.thellier_magic(meas_file, dir_path, input_dir_path,
                         spec, n_specs, save_plots, fmt, interactive)

Response: This function is the main function of the Thellier - Thellier - Thellier - Magic script. It is used to generate the interpretations for a specific specimen in version 3. 0.


Instruction:
Write a Python 3 function for
trying to download the data model from Earthref and return the corresponding object. If that fails return the online data model.

Response:
def get_data_model(self):
        """
        Try to download the data model from Earthref.
        If that fails, grab the cached data model.
        """
        if len(DM):
            self.dm = DM
            self.crit_map = CRIT_MAP
            return
        if not set_env.OFFLINE:
            dm = self.get_dm_online()
            if dm:
                print('-I- Using online data model')
                #self.cache_data_model(dm)
                return self.parse_response(dm)
        # if online is not available, get cached dm
        dm = self.get_dm_offline()
        print('-I- Using cached data model')
        return self.parse_cache(dm)


Instruction:
Can you implement a function in Python 3 that
grabs the 3. 0 data model from the PmagPy directory Returns --------- DataFrame full

Response:
def get_dm_offline(self):
        """
        Grab the 3.0 data model from the PmagPy/pmagpy directory

        Returns
        ---------
        full : DataFrame
            cached data model json in DataFrame format
        """
        model_file = self.find_cached_dm()
        try:
            f = open(model_file, 'r', encoding='utf-8-sig')
        except TypeError:
            f = open(model_file, 'r')
        string = '\n'.join(f.readlines())
        f.close()
        raw = json.loads(string)
        full = pd.DataFrame(raw)
        return full


Instruction:
Create a Python 3 function for
getting data model from Earthref.

Response:
def get_dm_online(self):
        """
        Use requests module to get data model from Earthref.
        If this fails or times out, return false.

        Returns
        ---------
        result : requests.models.Response, False if unsuccessful
        """
        if not requests:
            return False
        try:
            req = requests.get("https://earthref.org/MagIC/data-models/3.0.json", timeout=3)
            if not req.ok:
                return False
            return req
        except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError,
                requests.exceptions.ReadTimeout):
            return False


Instruction:
Make a summary of the following Python 3 code
def parse_cache(self, full_df):
        data_model = {}
        levels = ['specimens', 'samples', 'sites', 'locations',
                  'ages', 'measurements', 'criteria', 'contribution',
                  'images']
        criteria_map = pd.DataFrame(full_df['criteria_map'])
        for level in levels:
            df = pd.DataFrame(full_df['tables'][level]['columns'])
            data_model[level] = df.transpose()
        # replace np.nan with None
        data_model[level] = data_model[level].where((pd.notnull(data_model[level])), None)
        return data_model, criteria_map

Response:
Format the cached data model into a dictionary of DataFrames
        and a criteria map DataFrame.


Instruction:
Make a summary of the following Python 3 code
def parse(self, data_model, crit):
        # data model
        tables = pd.DataFrame(data_model)
        data_model = {}
        for table_name in tables.columns:
            data_model[table_name] = pd.DataFrame(tables[table_name]['columns']).T
            # replace np.nan with None
            data_model[table_name] = data_model[table_name].where((pd.notnull(data_model[table_name])), None)
        # criteria map
        zipped = list(zip(crit.keys(), crit.values()))
        crit_map = pd.DataFrame(zipped)
        crit_map.index = crit_map[0]
        crit_map.drop(0, axis='columns', inplace=True)
        crit_map.rename({1: 'criteria_map'}, axis='columns', inplace=True)
        crit_map.index.rename("", inplace=True)
        for table_name in ['measurements', 'specimens', 'samples', 'sites', 'locations',
                           'contribution', 'criteria', 'images', 'ages']:
            crit_map.loc[table_name] = np.nan

        return data_model, crit_map

Response:
Take the relevant pieces of the data model json
        and parse into data model and criteria map.


Instruction:
Can you generate the documentation for the following Python 3 function
def parse_response(self, raw):

        tables = raw.json()['tables']
        crit = raw.json()['criteria_map']
        return self.parse(tables, crit)

Response:
Parse the response from the Earthref API into a dictionary of DataFrames
        and a criteria map DataFrame.


Instruction:
Write a Python 3 script for
finding filename where cached data model json is stored.

Response:
def find_cached_dm(self):
        """
        Find filename where cached data model json is stored.

        Returns
        ---------
        model_file : str
            data model json file location
        """
        pmag_dir = find_pmag_dir.get_pmag_dir()
        if pmag_dir is None:
            pmag_dir = '.'
        model_file = os.path.join(pmag_dir, 'pmagpy',
                                  'data_model', 'data_model.json')
        # for py2app:
        if not os.path.isfile(model_file):
            model_file = os.path.join(pmag_dir, 'data_model',
                                      'data_model.json')
        if not os.path.isfile(model_file):
            model_file = os.path.join(os.path.split(os.path.dirname(__file__))[0],'pmagpy', 'data_model','data_model.json')
        if not os.path.isfile(model_file):
            model_file = os.path.join(os.path.split(os.path.dirname(__file__))[0], 'data_model','data_model.json')
        return model_file


Instruction:
How would you code a function in Python 3 to
cache the data model json.

Response:
def cache_data_model(self, raw):
        """
        Cache the data model json.
        Take data returned by a requests.get call to Earthref.

        Parameters
        ----------
        raw: requests.models.Response

        """
        output_json = json.loads(raw.content)
        output_file = self.find_cached_dm()
        json.dump(output_json, open(output_file, 'w+'))


Instruction:
Create a Python 3 function for
returning list of all groups for a particular data type

Response:
def get_groups(self, table_name):
        """
        Return list of all groups for a particular data type
        """
        df = self.dm[table_name]
        return list(df['group'].unique())


Instruction:
How would you implement a function in Python 3 that
returns a list of all headers for a given group

Response:
def get_group_headers(self, table_name, group_name):
        """
        Return a list of all headers for a given group
        """
        # get all headers of a particular group
        df = self.dm[table_name]
        cond = df['group'] == group_name
        return df[cond].index


Instruction:
Explain what the following Python 3 code does
def get_reqd_headers(self, table_name):
        df = self.dm[table_name]
        cond = df['validations'].map(lambda x: 'required()' in str(x))
        return df[cond].index

Response: Return a list of all required headers for a particular table


Instruction:
Create a Python 3 function for
checking data model to find group name for a given column header

Response:
def get_group_for_col(self, table_name, col_name):
        """
        Check data model to find group name for a given column header

        Parameters
        ----------
        table_name: str
        col_name: str

        Returns
        ---------
        group_name: str
        """
        df = self.dm[table_name]
        try:
            group_name = df.loc[col_name, 'group']
        except KeyError:
            return ''
        return group_name


Instruction:
How would you code a function in Python 3 to
name fisher. py AttributeNames fisher. py AttributeNames is the main function for the fisher - distribution.

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

    DESCRIPTION
        generates set of Fisher distribed data from specified distribution

    INPUT (COMMAND LINE ENTRY)
    OUTPUT
        dec,  inc

    SYNTAX
        fisher.py [-h] [-i] [command line options]

    OPTIONS
        -h prints help message and quits
        -i for interactive  entry
        -k specify kappa as next argument, default is 20
        -n specify N as next argument, default is 100
        where:
            kappa:  fisher distribution concentration parameter
            N:  number of directions desired

    """
    N,kappa=100,20
    if '-h' in sys.argv:
        print(main.__doc__)
        sys.exit()
    elif '-i' in sys.argv:
        ans=input('    Kappa: ')
        kappa=float(ans)
        ans=input('    N: ')
        N=int(ans)
    else:
        if '-k' in sys.argv:
            ind=sys.argv.index('-k')
            kappa=float(sys.argv[ind+1])
        if '-n' in sys.argv:
            ind=sys.argv.index('-n')
            N=int(sys.argv[ind+1])
    for k in range(N): spitout(kappa)


Instruction:
Write a Python 3 function that can
name pmm_redo. py - h prints help message and quits prints help message and quits prints help message and quits prints help message and quits prints help message and quits prints usage message and exits

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

    DESCRIPTION
        converts the UCSC PMM files format to PmagPy redo file

    SYNTAX
        pmm_redo.py [-h] [command line options]

    OPTIONS
        -h: prints help message and quits
        -f FILE: specify input file
        -F FILE: specify output file, default is 'zeq_redo'
    """
    dir_path='.'
    if '-WD' in sys.argv:
        ind=sys.argv.index('-WD')
        dir_path=sys.argv[ind+1]
    zfile=dir_path+'/zeq_redo'
    if '-h' in sys.argv:
        print(main.__doc__)
        sys.exit()
    if '-f' in sys.argv:
        ind=sys.argv.index('-f')
        inspec=dir_path+'/'+sys.argv[ind+1]
    if '-F' in sys.argv:
        ind=sys.argv.index('-F')
        zfile=dir_path+'/'+sys.argv[ind+1]
    zredo=open(zfile,"w")
#
# read in PMM file
#
    specs=[]
    prior_spec_data=open(inspec,'r').readlines()
    for line in prior_spec_data:
      rec=line.split(',')
      if rec[0][0]!='"' and rec[0]!="ID" and len(rec)>2: # skip all the header stuff
            spec=rec[0]
            specs.append(spec)
            comp_name=string.uppercase[specs.count(spec)-1] # assign component names
            calculation_type="DE-FM"
            if rec[1].strip()=='DirPCA': calculation_type="DE-BFL" # assume default calculation type is best-fit line
            if rec[1].strip()=='DirOPCA': calculation_type="DE-BFL-A" # anchored best-fit line
            if rec[1].strip()=='GCPCA' or rec[1]=='GCnPCA' : calculation_type="DE-BFP" # best-fit plane
            steps=rec[2].strip().split('-')
            min,max=steps[0],steps[1]
            beg,end="",""
            if min=="NRM":
               beg=0
            elif min[0]=='M' or min[0]=='H':
                beg=float(min[1:])*1e-3 # convert to T from mT
            elif min[-1]=='M':
                beg=float(min[:-1])*1e-3 # convert to T from mT
            elif min[0]=='T':
                beg=float(min[1:])+273 # convert to C to kelvin
            if max[0]=='M' or max[0]=='H':
                end=float(max[1:])*1e-3 # convert to T from mT
            elif max[0]=='T':
                end=float(max[1:])+273 # convert to C to kelvin
            elif max[-1]=='M':
                end=float(max[1:])*1e-3 # convert to T from mT
            if beg==0:beg=273
            outstring='%s %s %s %s %s \n'%(spec,calculation_type,beg,end,comp_name)
            zredo.write(outstring)


Instruction:
Create a Python 3 function for
naming nac_util. py VIRTUAL is the main function of nac_util. py

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

    DESCRIPTION
       makes qq plot from dec,inc input data

    INPUT FORMAT
       takes dec/inc pairs in space delimited file

    SYNTAX
       fishqq.py [command line options]

    OPTIONS
        -h help message
        -f FILE, specify file on command line
        -F FILE, specify output file for statistics
        -sav save and quit [saves as input file name plus fmt extension]
        -fmt specify format for output [png, eps, svg, pdf]

    OUTPUT:
        Dec Inc N Mu Mu_crit Me Me_crit Y/N
     where direction is the principal component and Y/N is Fisherian or not
     separate lines for each mode with N >=10 (N and R)
    """
    fmt,plot='svg',0
    outfile=""
    if '-h' in sys.argv: # check if help is needed
        print(main.__doc__)
        sys.exit() # graceful quit
    elif '-f' in sys.argv: # ask for filename
        ind=sys.argv.index('-f')
        file=sys.argv[ind+1]
        f=open(file,'r')
        data=f.readlines()
    if '-F' in sys.argv:
        ind=sys.argv.index('-F')
        outfile=open(sys.argv[ind+1],'w') # open output file
    if '-sav' in sys.argv: plot=1
    if '-fmt' in sys.argv:
        ind=sys.argv.index('-fmt')
        fmt=sys.argv[ind+1]
    DIs,nDIs,rDIs= [],[],[] # set up list for data
    for line in data:   # read in the data from standard input
        if '\t' in line:
            rec=line.split('\t') # split each line on space to get records
        else:
            rec=line.split() # split each line on space to get records
        DIs.append([float(rec[0]),float(rec[1])]) # append data to Inc
# split into two modes
    ppars=pmag.doprinc(DIs) # get principal directions
    for rec in DIs:
        angle=pmag.angle([rec[0],rec[1]],[ppars['dec'],ppars['inc']])
        if angle>90.:
            rDIs.append(rec)
        else:
            nDIs.append(rec)

#
    if len(rDIs) >=10 or len(nDIs) >=10:
        D1,I1=[],[]
        QQ={'unf1':1,'exp1':2}
        pmagplotlib.plot_init(QQ['unf1'],5,5)
        pmagplotlib.plot_init(QQ['exp1'],5,5)
        if len(nDIs) < 10:
            ppars=pmag.doprinc(rDIs) # get principal directions
            Drbar,Irbar=ppars['dec']-180.,-ppars['inc']
            Nr=len(rDIs)
            for di in rDIs:
                d,irot=pmag.dotilt(di[0],di[1],Drbar-180.,90.-Irbar) # rotate to mean
                drot=d-180.
                if drot<0:drot=drot+360.
                D1.append(drot)
                I1.append(irot)
                Dtit='Mode 2 Declinations'
                Itit='Mode 2 Inclinations'
        else:
            ppars=pmag.doprinc(nDIs) # get principal directions
            Dnbar,Inbar=ppars['dec'],ppars['inc']
            Nn=len(nDIs)
            for di in nDIs:
                d,irot=pmag.dotilt(di[0],di[1],Dnbar-180.,90.-Inbar) # rotate to mean
                drot=d-180.
                if drot<0:drot=drot+360.
                D1.append(drot)
                I1.append(irot)
                Dtit='Mode 1 Declinations'
                Itit='Mode 1 Inclinations'
        Mu_n,Mu_ncr=pmagplotlib.plot_qq_unf(QQ['unf1'],D1,Dtit) # make plot
        Me_n,Me_ncr=pmagplotlib.plot_qq_exp(QQ['exp1'],I1,Itit) # make plot
        #print Mu_n,Mu_ncr,Me_n, Me_ncr
        if outfile!="":
#        Dec Inc N Mu Mu_crit Me Me_crit Y/N
            if Mu_n<=Mu_ncr and Me_n<=Me_ncr:
               F='Y'
            else:
               F='N'
            outstring='%7.1f %7.1f %i %5.3f %5.3f %5.3f %5.3f %s \n'%(Dnbar,Inbar,Nn,Mu_n,Mu_ncr,Me_n,Me_ncr,F)
            outfile.write(outstring)
    else:
        print('you need N> 10 for at least one mode')
        sys.exit()
    if len(rDIs)>10 and len(nDIs)>10:
        D2,I2=[],[]
        QQ['unf2']=3
        QQ['exp2']=4
        pmagplotlib.plot_init(QQ['unf2'],5,5)
        pmagplotlib.plot_init(QQ['exp2'],5,5)
        ppars=pmag.doprinc(rDIs) # get principal directions
        Drbar,Irbar=ppars['dec']-180.,-ppars['inc']
        Nr=len(rDIs)
        for di in rDIs:
            d,irot=pmag.dotilt(di[0],di[1],Drbar-180.,90.-Irbar) # rotate to mean
            drot=d-180.
            if drot<0:drot=drot+360.
            D2.append(drot)
            I2.append(irot)
            Dtit='Mode 2 Declinations'
            Itit='Mode 2 Inclinations'
        Mu_r,Mu_rcr=pmagplotlib.plot_qq_unf(QQ['unf2'],D2,Dtit) # make plot
        Me_r,Me_rcr=pmagplotlib.plot_qq_exp(QQ['exp2'],I2,Itit) # make plot
        if outfile!="":
#        Dec Inc N Mu Mu_crit Me Me_crit Y/N
            if Mu_r<=Mu_rcr and Me_r<=Me_rcr:
               F='Y'
            else:
               F='N'
            outstring='%7.1f %7.1f %i %5.3f %5.3f %5.3f %5.3f %s \n'%(Drbar,Irbar,Nr,Mu_r,Mu_rcr,Me_r,Me_rcr,F)
            outfile.write(outstring)
    files={}
    for key in list(QQ.keys()):
        files[key]=file+'_'+key+'.'+fmt
    if pmagplotlib.isServer:
        black     = '#000000'
        purple    = '#800080'
        titles={}
        titles['eq']='Equal Area Plot'
        EQ = pmagplotlib.add_borders(EQ,titles,black,purple)
        pmagplotlib.save_plots(QQ,files)
    elif plot==1:
        pmagplotlib.save_plots(QQ,files)
    else:
        pmagplotlib.draw_figs(QQ)
        ans=input(" S[a]ve to save plot, [q]uit without saving:  ")
        if ans=="a": pmagplotlib.save_plots(QQ,files)


Instruction:
How would you implement a function in Python 3 that
names n_lines n_planes K alpha95 dec inc

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

    DESCRIPTION
       makes equal area projections site by site
         from specimen formatted file with
         Fisher confidence ellipse using McFadden and McElhinny (1988)
         technique for combining lines and planes

    SYNTAX
        lnp_magic [command line options]

    INPUT
       takes magic formatted specimens file

    OUPUT
        prints site_name n_lines n_planes K alpha95 dec inc R

    OPTIONS
        -h prints help message and quits
        -f FILE: specify input file, default is 'specimens.txt', ('pmag_specimens.txt' for legacy data model 2)
        -fsa FILE: specify samples file, required to plot by site for data model 3 (otherwise will plot by sample)
                default is 'samples.txt'
        -crd [s,g,t]: specify coordinate system, [s]pecimen, [g]eographic, [t]ilt adjusted
                default is specimen
        -fmt [svg,png,jpg] format for plots, default is svg
        -sav save plots and quit
        -P: do not plot
        -F FILE, specify output file of dec, inc, alpha95 data for plotting with plotdi_a and plotdi_e
        -exc use criteria in criteria table # NOT IMPLEMENTED
        -DM NUMBER MagIC data model (2 or 3, default 3)
    """
    if '-h' in sys.argv:
        print(main.__doc__)
        sys.exit()
    dir_path = pmag.get_named_arg("-WD", ".")
    data_model = int(float(pmag.get_named_arg("-DM", 3)))
    fmt = pmag.get_named_arg("-fmt", 'svg')
    if data_model == 2:
        in_file = pmag.get_named_arg('-f', 'pmag_specimens.txt')
        crit_file = "pmag_criteria.txt"
    else:
        in_file = pmag.get_named_arg('-f', 'specimens.txt')
        samp_file = pmag.get_named_arg('-fsa', 'samples.txt')
        crit_file = "criteria.txt"
    in_file = pmag.resolve_file_name(in_file, dir_path)
    dir_path = os.path.split(in_file)[0]
    if data_model == 3:
        samp_file = pmag.resolve_file_name(samp_file, dir_path)
    if '-crd' in sys.argv:
        ind = sys.argv.index("-crd")
        crd = sys.argv[ind+1]
        if crd == 's':
            coord = "-1"
        if crd == 'g':
            coord = "0"
        if crd == 't':
            coord = "100"
    else:
        coord = "-1"

    out_file = pmag.get_named_arg('-F', '')
    if out_file:
        out = open(dir_path+'/'+out_file, 'w')
    if '-P' in sys.argv:
        make_plots = 0  # do not plot
    else:
        make_plots = 1  # do plot
    if '-sav' in sys.argv:
        plot = 1  # save plots and quit
    else:
        plot = 0 # show plots intereactively (if make_plots)
#

    if data_model == 2:
        Specs, file_type = pmag.magic_read(in_file)
        if 'specimens' not in file_type:
            print('Error opening ', in_file, file_type)
            sys.exit()
    else:
        fnames = {'specimens': in_file, 'samples': samp_file}
        con = cb.Contribution(dir_path, read_tables=['samples', 'specimens'],
                              custom_filenames=fnames)
        con.propagate_name_down('site', 'specimens')
        if 'site' in con.tables['specimens'].df.columns:
            site_col = 'site'
        else:
            site_col = 'sample'
        tilt_corr_col = "dir_tilt_correction"
        mad_col = "dir_mad_free"
        alpha95_col = "dir_alpha95"
        site_alpha95_col = "dir_alpha95"
        dec_col = "dir_dec"
        inc_col = "dir_inc"
        num_meas_col = "dir_n_measurements"
        k_col = "dir_k"
        cols = [site_col, tilt_corr_col, mad_col, alpha95_col, dec_col, inc_col]
        con.tables['specimens'].front_and_backfill(cols)
        con.tables['specimens'].df = con.tables['specimens'].df.where(con.tables['specimens'].df.notnull(), "")
        Specs = con.tables['specimens'].convert_to_pmag_data_list()

    ## using criteria file was never fully implemented
    #if '-exc' in sys.argv:
    #    Crits, file_type = pmag.magic_read(pmag.resolve_file_name(crit_file, dir_path))
    #    for crit in Crits:
    #        if mad_col in crit:
    #            M = float(crit['specimen_mad'])
    #        if num_meas_col in crit:
    #            N = float(crit['specimen_n'])
    #        if site_alpha95_col in crit and 'site' in crit:
    #            acutoff = float(crit['site_alpha95'])
    #        if k_col in crit:
    #            kcutoff = float(crit['site_k'])
    #else:
    #    Crits = ""

    sitelist = []

    # initialize some variables
    FIG = {}  # plot dictionary
    FIG['eqarea'] = 1  # eqarea is figure 1
    M, N, acutoff, kcutoff = 180., 1, 180., 0.

    if data_model == 2:
        site_col = 'er_site_name'
        tilt_corr_col = "specimen_tilt_correction"
        mad_col = "specimen_mad"
        alpha95_col = 'specimen_alpha95'
        dec_col = "specimen_dec"
        inc_col = "specimen_inc"
        num_meas_col = "specimen_n"
        site_alpha95_col = "site_alpha95"
    else: # data model 3
        pass

    for rec in Specs:
        if rec[site_col] not in sitelist:
            sitelist.append(rec[site_col])
    sitelist.sort()
    if make_plots == 1:
        EQ = {}
        EQ['eqarea'] = 1
    for site in sitelist:
        pmagplotlib.plot_init(EQ['eqarea'], 4, 4)
        print(site)
        data = []
        for spec in Specs:
            if tilt_corr_col not in list(spec.keys()):
                spec[tilt_corr_col] = '-1'  # assume unoriented
            if spec[site_col] == site:
                if mad_col not in list(spec.keys()) or spec[mad_col] == "":
                    if alpha95_col in list(spec.keys()) and spec[alpha95_col] != "":
                        spec[mad_col] = spec[alpha95_col]
                    else:
                        spec[mad_col] = '180'
                if not spec[num_meas_col]:
                    continue
                if (float(spec[tilt_corr_col]) == float(coord)) and (float(spec[mad_col]) <= M) and (float(spec[num_meas_col]) >= N):
                    rec = {}
                    for key in list(spec.keys()):
                        rec[key] = spec[key]
                    rec["dec"] = float(spec[dec_col])
                    rec["inc"] = float(spec[inc_col])
                    rec["tilt_correction"] = spec[tilt_corr_col]
                    data.append(rec)
        if len(data) > 2:
            fpars = pmag.dolnp(data, 'specimen_direction_type')
            print("Site lines planes  kappa   a95   dec   inc")
            print(site, fpars["n_lines"], fpars["n_planes"], fpars["K"],
                  fpars["alpha95"], fpars["dec"], fpars["inc"], fpars["R"])
            if out_file != "":
                if float(fpars["alpha95"]) <= acutoff and float(fpars["K"]) >= kcutoff:
                    out.write('%s %s %s\n' %
                              (fpars["dec"], fpars['inc'], fpars['alpha95']))
            print('% tilt correction: ', coord)
            if make_plots == 1:
                files = {}
                files['eqarea'] = site+'_'+crd+'_'+'eqarea'+'.'+fmt
                pmagplotlib.plot_lnp(EQ['eqarea'], site,
                                    data, fpars, 'specimen_direction_type')
                if plot == 0:
                    pmagplotlib.draw_figs(EQ)
                    ans = input(
                        "s[a]ve plot, [q]uit, <return> to continue:\n ")
                    if ans == "a":
                        pmagplotlib.save_plots(EQ, files)
                    if ans == "q":
                        sys.exit()
                else:
                    pmagplotlib.save_plots(EQ, files)
        else:
            print('skipping site - not enough data with specified coordinate system')


Instruction:
Can you generate the documentation for the following Python 3 function
def get_item_string(items_list):
    if not items_list:
        return ''
    string_list = []
    for item in items_list:
        try:
            name = item.name
            string_list.append(name)
        except AttributeError:
            pass
    return ":".join(string_list)

Response:
take in a list of pmag_objects
    return a colon - delimited list of the findable names


Instruction:
Can you generate the documentation for the following Python 3 function
def combine_dicts(new_dict, old_dict):
    old_data_keys = list(old_dict.keys())
    new_data_keys = list(new_dict.keys())
    all_keys = set(old_data_keys).union(new_data_keys)
    combined_data_dict = {}
    for k in all_keys:
        try:
            combined_data_dict[k] = new_dict[k]
        except KeyError:
            combined_data_dict[k] = old_dict[k]
    return combined_data_dict

Response: Combine two dictionaries with all key value pairs from new_dict.


Instruction:
Given the following Python 3 function, write the documentation
def find_by_name(self, item_name, items_list, name_list=None):
        if not name_list:
            names = [item.name for item in items_list if item]
        else:
            names = name_list
        if item_name in names:
            ind = names.index(item_name)
            return items_list[ind]
        return False

Response: Find a item in items_list with the given name.


Instruction:
Explain what the following Python 3 code does
def find_or_create_by_name(self, item_name, items_list, item_type):
        item = self.find_by_name(item_name, items_list)
        if not item:
            item = self.data_lists[item_type][2](item_name, None)
        return item

Response: Find or create an item by name


Instruction:
Make a summary of the following Python 3 code
def init_default_headers(self):
        if not self.data_model:
            self.data_model = validate_upload.get_data_model()
            if not self.data_model:
                print("Can't access MagIC-data-model at the moment.\nIf you are working offline, make sure MagIC-data-model.txt is in your PmagPy directory (or download it from https://github.com/ltauxe/PmagPy and put it in your PmagPy directory).\nOtherwise, check your internet connection")
                return False

        # actual is at position 0, reqd is at position 1, optional at position 2
        self.headers['measurement']['er'][1], self.headers['measurement']['er'][2] = self.get_headers('magic_measurements')
        self.headers['specimen']['er'][1], self.headers['specimen']['er'][2] = self.get_headers('er_specimens')
        self.headers['sample']['er'][1], self.headers['sample']['er'][2] = self.get_headers('er_samples')
        self.headers['site']['er'][1], self.headers['site']['er'][2] = self.get_headers('er_sites')
        self.headers['location']['er'][1], self.headers['location']['er'][2] = self.get_headers('er_locations')
        self.headers['age']['er'][1], self.headers['age']['er'][2] = self.get_headers('er_ages')

        self.headers['result']['pmag'][1], self.headers['result']['pmag'][2] = self.get_headers('pmag_results')
        self.headers['specimen']['pmag'][1], self.headers['specimen']['pmag'][2] = self.get_headers('pmag_specimens')
        self.headers['sample']['pmag'][1], self.headers['sample']['pmag'][2] = self.get_headers('pmag_samples')
        self.headers['site']['pmag'][1], self.headers['site']['pmag'][2] = self.get_headers('pmag_sites')

Response: initialize default required headers.


Instruction:
Write a Python 3 function that can
add a new measurement to the data object.

Response:
def add_measurement(self, exp_name, meas_num, spec_name=None, er_data=None, pmag_data=None):
        """
        Find actual data object for specimen.
        Then create a measurement belonging to that specimen and add it to the data object
        """
        specimen = self.find_by_name(spec_name, self.specimens)
        measurement = Measurement(exp_name, meas_num, specimen, er_data)
        self.measurements.append(measurement)
        return measurement


Instruction:
Here you have a function in Python 3, explain what it does
def change_specimen(self, old_spec_name, new_spec_name,
                        new_sample_name=None, new_er_data=None, new_pmag_data=None,
                        replace_data=False):
        """
        Find actual data objects for specimen and sample.
        Then call Specimen class change method to update specimen name and data.
        """
        specimen = self.find_by_name(old_spec_name, self.specimens)
        if not specimen:
            print('-W- {} is not a currently existing specimen, so cannot be updated'.format(old_spec_name))
            return False
        if new_sample_name:
            new_sample = self.find_by_name(new_sample_name, self.samples)
            if not new_sample:
                print("""-W- {} is not a currently existing sample.
Creating a new sample named: {} """.format(new_sample_name, new_sample_name))
                new_sample = self.add_sample(new_sample_name)
        else:
            new_sample = None
        specimen.change_specimen(new_spec_name, new_sample, new_er_data, new_pmag_data, replace_data)
        return specimen

Response: Change the specimen name and data.


Instruction:
Can you tell what is the following Python 3 function doing
def delete_specimen(self, spec_name):
        specimen = self.find_by_name(spec_name, self.specimens)
        if not specimen:
            return False
        sample = specimen.sample
        if sample:
            sample.specimens.remove(specimen)
        self.specimens.remove(specimen)
        del specimen
        return []

Response: Delete a specimen from the specimen list.


Instruction:
Create a Python 3 function for
adding a new specimen to the internal list of specimen objects.

Response:
def add_specimen(self, spec_name, samp_name=None, er_data=None, pmag_data=None):
        """
        Create a Specimen object and add it to self.specimens.
        If a sample name is provided, add the specimen to sample.specimens as well.
        """
        if samp_name:
            sample = self.find_by_name(samp_name, self.samples)
            if not sample:
                print("""-W- {} is not a currently existing sample.
Creating a new sample named: {} """.format(samp_name, samp_name))
                sample = self.add_sample(samp_name)
        else:
            sample = None

        specimen = Specimen(spec_name, sample, self.data_model, er_data, pmag_data)

        self.specimens.append(specimen)
        if sample:
            sample.specimens.append(specimen)
        return specimen


Instruction:
Can you generate the documentation for the following Python 3 function
def change_sample(self, old_samp_name, new_samp_name, new_site_name=None,
                      new_er_data=None, new_pmag_data=None, replace_data=False):
        """
        Find actual data objects for sample and site.
        Then call Sample class change method to update sample name and data..
        """
        sample = self.find_by_name(old_samp_name, self.samples)
        if not sample:
            print('-W- {} is not a currently existing sample, so it cannot be updated'.format(old_samp_name))
            return False
        if new_site_name:
            new_site = self.find_by_name(new_site_name, self.sites)
            if not new_site:
                print("""-W- {} is not a currently existing site.
Adding site named: {}""".format(new_site_name, new_site_name))#sample.site or '*empty*', sample)
                new_site = self.add_site(new_site_name)
        else:
            new_site = None
        sample.change_sample(new_samp_name, new_site, new_er_data, new_pmag_data, replace_data)
        return sample

Response: Change the name of a sample and site.


Instruction:
Write a Python 3 script for
adding a sample to the internal list of samples.

Response:
def add_sample(self, samp_name, site_name=None, er_data=None, pmag_data=None):
        """
        Create a Sample object and add it to self.samples.
        If a site name is provided, add the sample to site.samples as well.
        """
        if site_name:
            site = self.find_by_name(site_name, self.sites)
            if not site:
                print("""-W- {} is not a currently existing site.
Creating a new site named: {} """.format(site_name, site_name))
                site = self.add_site(site_name)
        else:
            site = None
        sample = Sample(samp_name, site, self.data_model, er_data, pmag_data)
        self.samples.append(sample)
        if site:
            site.samples.append(sample)
        return sample


Instruction:
Here you have a function in Python 3, explain what it does
def delete_sample(self, sample_name, replacement_samp=None):
        sample = self.find_by_name(sample_name, self.samples)
        if not sample:
            return False
        specimens = sample.specimens
        site = sample.site
        if site:
            site.samples.remove(sample)
        self.samples.remove(sample)
        for spec in specimens:
            spec.sample = ""
        return specimens

Response: Removes a sample from the list of samples.


Instruction:
Can you create a Python 3 function that
changes the site name and data.

Response:
def change_site(self, old_site_name, new_site_name, new_location_name=None,
                    new_er_data=None, new_pmag_data=None, replace_data=False):
        """
        Find actual data objects for site and location.
        Then call the Site class change method to update site name and data.
        """
        site = self.find_by_name(old_site_name, self.sites)
        if not site:
            print('-W- {} is not a currently existing site, so it cannot be updated.'.format(old_site_name))
            return False
        if new_location_name:
            if site.location:
                old_location = self.find_by_name(site.location.name, self.locations)
                if old_location:
                    old_location.sites.remove(site)
            new_location = self.find_by_name(new_location_name, self.locations)
            if not new_location:
                print("""-W- {} is not a currently existing location.
Adding location with name: {}""".format(new_location_name, new_location_name))
                new_location = self.add_location(new_location_name)
            new_location.sites.append(site)
        else:
            new_location = None
        ## check all declinations/azimuths/longitudes in range 0=>360.
        #for key, value in new_er_data.items():
        #    new_er_data[key] = pmag.adjust_to_360(value, key)
        site.change_site(new_site_name, new_location, new_er_data, new_pmag_data, replace_data)
        return site


Instruction:
Make a summary of the following Python 3 code
def add_site(self, site_name, location_name=None, er_data=None, pmag_data=None):
        if location_name:
            location = self.find_by_name(location_name, self.locations)
            if not location:
                location = self.add_location(location_name)
        else:
            location = None

        ## check all declinations/azimuths/longitudes in range 0=>360.
        #for key, value in er_data.items():
        #    er_data[key] = pmag.adjust_to_360(value, key)

        new_site = Site(site_name, location, self.data_model, er_data, pmag_data)
        self.sites.append(new_site)
        if location:
            location.sites.append(new_site)
        return new_site

Response: Add a site to the list of sites and add it to self. sites.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def delete_site(self, site_name, replacement_site=None):
        site = self.find_by_name(site_name, self.sites)
        if not site:
            return False
        self.sites.remove(site)
        if site.location:
            site.location.sites.remove(site)
        samples = site.samples
        for samp in samples:
            samp.site = ''
        del site
        return samples

Response: Removes a site from the list of sites and returns a list of samples.


Instruction:
Can you write a function in Python 3 where it
changes location name and data.

Response:
def change_location(self, old_location_name, new_location_name, new_parent_name=None,
                        new_er_data=None, new_pmag_data=None, replace_data=False):
        """
        Find actual data object for location with old_location_name.
        Then call Location class change method to update location name and data.
        """
        location = self.find_by_name(old_location_name, self.locations)
        if not location:
            print('-W- {} is not a currently existing location, so it cannot be updated.'.format(old_location_name))
            return False
        location.change_location(new_location_name, new_er_data, new_pmag_data, replace_data)
        return location


Instruction:
How would you implement a function in Python 3 that
adds a Location object to the list of locations.

Response:
def add_location(self, location_name, parent_name=None, er_data=None, pmag_data=None):
        """
        Create a Location object and add it to self.locations.
        """
        if not location_name:
            return False
        location = Location(location_name, data_model=self.data_model, er_data=er_data, pmag_data=pmag_data)
        self.locations.append(location)
        return location


Instruction:
Explain what the following Python 3 code does
def delete_location(self, location_name):
        location = self.find_by_name(location_name, self.locations)
        if not location:
            return False
        sites = location.sites
        self.locations.remove(location)
        for site in sites:
            if site:
                site.location = ''
        del location
        return sites

Response: Delete a location from the set of available locations.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def change_result(self, old_result_name, new_result_name, new_er_data=None,
                      new_pmag_data=None, spec_names=None, samp_names=None,
                      site_names=None, loc_names=None, replace_data=False):
        """
        Find actual data object for result with old_result_name.
        Then call Result class change method to update result name and data.
        """
        result = self.find_by_name(old_result_name, self.results)
        if not result:
            msg = '-W- {} is not a currently existing result, so it cannot be updated.'.format(old_result_name)
            print(msg)
            return False
        else:
            specimens, samples, sites, locations = None, None, None, None
            if spec_names:
                specimens = [self.find_or_create_by_name(spec, self.specimens, 'specimen') for spec in spec_names]
            if samp_names:
                samples = [self.find_or_create_by_name(samp, self.samples, 'sample') for samp in samp_names]
            if site_names:
                sites = [self.find_or_create_by_name(site, self.sites, 'site') for site in site_names]
            if loc_names:
                locations = [self.find_or_create_by_name(loc, self.locations, 'location') for loc in loc_names]

            result.change_result(new_result_name, new_pmag_data, specimens, samples,
                                 sites, locations, replace_data)
            return result

Response: Change the result name and data of a currently existing result.


Instruction:
Create a Python 3 function for
reading the magic_measurements. txt file and return a dictionary of data

Response:
def get_data(self):
        """
        attempt to read measurements file in working directory.
        """
        meas_file = os.path.join(self.WD, 'magic_measurements.txt')
        if not os.path.isfile(meas_file):
            print("-I- No magic_measurements.txt file")
            return {}
        try:
            meas_data, file_type = pmag.magic_read(meas_file)
        except IOError:
            print("-I- No magic_measurements.txt file")
            return {}
        if file_type == 'bad_file':
            print("-E- ERROR: Can't read magic_measurements.txt file. File is corrupted.")

        old_specimen_name = ''
        #start_time = time.time()
        meas_name_list = [measurement.name for measurement in self.measurements]

        for rec in meas_data:
            # get citation information
            citation = rec.get('er_citation_names', 'This study')
            if 'This study' not in citation:
                citation = citation.strip() + ':This study'
            er_data = {'er_citation_names': citation}
            pmag_data = {'er_citation_names': 'This study'}
            specimen_name = rec["er_specimen_name"]
            # ignore measurement if there is no specimen
            if specimen_name == "" or specimen_name == " ":
                continue
            # if we've moved onto a new specimen, make sure a sample/site/location
            # exists for that specimen
            if specimen_name != old_specimen_name:
                sample_name = rec["er_sample_name"]
                site_name = rec["er_site_name"]
                location_name = rec["er_location_name"]

                # add items and parents
                location = self.find_by_name(location_name, self.locations)
                if location_name and not location:
                    location = self.add_location(location_name, er_data=er_data,
                                                 pmag_data=pmag_data)
                site = self.find_by_name(site_name, self.sites)
                if site_name and not site:
                    site = self.add_site(site_name, location_name,
                                         er_data, pmag_data)
                sample = self.find_by_name(sample_name, self.samples)
                if sample_name and not sample:
                    sample = self.add_sample(sample_name, site_name,
                                             er_data, pmag_data)
                specimen = self.find_by_name(specimen_name, self.specimens)
                if specimen_name and not specimen:
                    specimen = self.add_specimen(specimen_name, sample_name,
                                                 er_data, pmag_data)

                # add child_items
                if sample and not self.find_by_name(specimen_name, sample.specimens):
                    sample.specimens.append(specimen)
                if site and not self.find_by_name(sample_name, site.samples):
                    site.samples.append(sample)
                if location and not self.find_by_name(site_name, location.sites):
                    location.sites.append(site)

            exp_name = rec['magic_experiment_name']
            meas_num = rec['measurement_number']

            meas_name = exp_name + '_' + str(meas_num)
            measurement = self.find_by_name(meas_name, self.measurements, meas_name_list)
            if not measurement:
                self.add_measurement(exp_name, meas_num, specimen.name, rec)
                meas_name_list.append(meas_name)

            old_specimen_name = specimen_name