Instruction:
Can you tell what is the following Python 3 function doing
def _2g_bin(dir_path=".", mag_file="", meas_file='measurements.txt',
            spec_file="specimens.txt", samp_file="samples.txt", site_file="sites.txt",
            loc_file="locations.txt", or_con='3', specnum=0, samp_con='2', corr='1',
            gmeths="FS-FD:SO-POM", location="unknown", inst="", user="", noave=False, input_dir="",
            lat="", lon=""):

    """
    Convert 2G binary format file to MagIC file(s)

    Parameters
    ----------
    dir_path : str
        output directory, default "."
    mag_file : str
        input file name
    meas_file : str
        output measurement file name, default "measurements.txt"
    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"
    or_con : number
        orientation convention, default '3', see info below
    specnum : int
        number of characters to designate a specimen, default 0
    samp_con : str
        sample/site naming convention, default '2', see info below
    corr: str
        default '1'
    gmeths : str
        sampling method codes, default "FS-FD:SO-POM", see info below
    location : str
        location name, default "unknown"
    inst : str
        instrument, default ""
    user : str
        user name, default ""
    noave : bool
       do not average duplicate measurements, default False (so by default, DO average)
    input_dir : str
        input file directory IF different from dir_path, default ""
    lat : float
        latitude, default ""
    lon : float
        longitude, default ""

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

    Info
    ----------
    Orientation convention:
        [1] Lab arrow azimuth= mag_azimuth; Lab arrow dip=-field_dip
            i.e., field_dip is degrees from vertical down - the hade [default]
        [2] Lab arrow azimuth = mag_azimuth-90; Lab arrow dip = -field_dip
            i.e., mag_azimuth is strike and field_dip is hade
        [3] Lab arrow azimuth = mag_azimuth; Lab arrow dip = 90-field_dip
            i.e.,  lab arrow same as field arrow, but field_dip was a hade.
        [4] lab azimuth and dip are same as mag_azimuth, field_dip
        [5] lab azimuth is same as mag_azimuth,lab arrow dip=field_dip-90
        [6] Lab arrow azimuth = mag_azimuth-90; Lab arrow dip = 90-field_dip
        [7] all others you will have to either customize your
            self or e-mail ltauxe@ucsd.edu for help.

   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

    Sampling method codes:
         FS-FD field sampling done with a drill
         FS-H field sampling done with hand samples
         FS-LOC-GPS  field location done with GPS
         FS-LOC-MAP  field location done with map
         SO-POM   a Pomeroy orientation device was used
         SO-ASC   an ASC orientation device was used
         SO-MAG   orientation with magnetic compass
         SO-SUN   orientation with sun compass

    """

    def skip(N, ind, L):
        for b in range(N):
            ind += 1
            while L[ind] == "":
                ind += 1
        ind += 1
        while L[ind] == "":
            ind += 1
        return ind

    #
    # initialize variables
    #
    bed_dip, bed_dip_dir = "", ""
    sclass, lithology, _type = "", "", ""
    DecCorr = 0.
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

    # format and fix variables
    specnum = int(specnum)
    specnum = -specnum
    input_dir_path, dir_path = pmag.fix_directories(input_dir, dir_path)

    if samp_con:
        Z = 1
        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, "option [4] must be in form 4-Z where Z is an integer"
            else:
                Z = samp_con.split("-")[1]
                samp_con = "4"
        if "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, "option [7] must be in form 7-Z where Z is an integer"
            else:
                Z = samp_con.split("-")[1]
                samp_con = "7"
        if "6" in samp_con:
            print('Naming convention option [6] not currently supported')
            return False, 'Naming convention option [6] not currently supported'
            # Z=1
            # try:
            #    SampRecs,file_type=pmag.magic_read(os.path.join(input_dir_path, 'er_samples.txt'))
            # except:
            #    print("there is no er_samples.txt file in your input directory - you can't use naming convention #6")
            #    return False, "there is no er_samples.txt file in your input directory - you can't use naming convention #6"
            # if file_type == 'bad_file':
            #    print("there is no er_samples.txt file in your input directory - you can't use naming convention #6")
            #    return False, "there is no er_samples.txt file in your input directory - you can't use naming convention #6"
        # else: Z=1

    if not mag_file:
        print("mag file is required input")
        return False, "mag file is required input"
    output_dir_path = dir_path
    mag_file = pmag.resolve_file_name(mag_file, input_dir_path)

    samplist = []
    try:
        SampRecs, file_type = pmag.magic_read(samp_file)
    except:
        SampRecs = []
    MeasRecs, SpecRecs, SiteRecs, LocRecs = [], [], [], []
    try:
        f = open(mag_file, 'br')
        input = str(f.read()).strip("b '")
        f.close()
    except Exception as ex:
        print('ex', ex)
        print("bad mag file")
        return False, "bad mag file"
    firstline, date = 1, ""
    d = input.split('\\xcd')
    for line in d:
        rec = line.split('\\x00')
        # skip nearly empty lines
        rec_not_null = [i for i in rec if i]
        if len(rec_not_null) < 5:
            continue
        if firstline == 1:
            firstline = 0
            spec, vol = "", 1
            el = 51
            #while line[el:el+1] != "\\":
            #    spec = spec+line[el]
            #    el += 1
            spec = rec[7]
            # check for bad sample name
            test = spec.split('.')
            date = ""
            if len(test) > 1:
                spec = test[0]
                kk = 24
                while line[kk] != '\\x01' and line[kk] != '\\x00':
                    kk += 1
                vcc = line[24:kk]
                el = 10
                while rec[el].strip() != '':
                    el += 1
                date, comments = rec[el+7], []
            else:
                el = 9
                while rec[el] != '\\x01':
                    el += 1
                vcc, date, comments = rec[el-3], rec[el+7], []
            specname = spec.lower()
            print('importing ', specname)
            el += 8
            while rec[el].isdigit() == False:
                comments.append(rec[el])
                el += 1
            while rec[el] == "":
                el += 1
            az = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            pl = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            bed_dip_dir = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            bed_dip = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            if rec[el] == '\\x01':
                bed_dip = 180.-bed_dip
                el += 1
                while rec[el] == "":
                    el += 1
            fold_az = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            fold_pl = rec[el]
            el += 1
            while rec[el] == "":
                el += 1
            if rec[el] != "" and rec[el] != '\\x02' and rec[el] != '\\x01':
                deccorr = float(rec[el])
                az += deccorr
                bed_dip_dir += deccorr
                fold_az += deccorr
                if bed_dip_dir >= 360:
                    bed_dip_dir = bed_dip_dir-360.
                if az >= 360.:
                    az = az-360.
                if fold_az >= 360.:
                    fold_az = fold_az-360.
            else:
                deccorr = 0
            if specnum != 0:
                sample = specname[:specnum]
            else:
                sample = specname

            methods = gmeths.split(':')
            if deccorr != "0":
                if 'SO-MAG' in methods:
                    del methods[methods.index('SO-MAG')]
                methods.append('SO-CMD-NORTH')
            meths = reduce(lambda x, y: x+':'+y, methods)
            method_codes = meths
            # parse out the site name
            site = pmag.parse_site(sample, samp_con, Z)
            SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}
            SpecRec["specimen"] = specname
            SpecRec["sample"] = sample
            if vcc.strip() != "":
                vol = float(vcc)*1e-6  # convert to m^3 from cc
            SpecRec["volume"] = '%10.3e' % (vol)
            SpecRec["geologic_classes"] = sclass
            SpecRec["lithologies"] = lithology
            SpecRec["geologic_types"] = _type
            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
                # convert to labaz, labpl
                labaz, labdip = pmag.orient(az, pl, or_con)
                SampRec["bed_dip"] = '%7.1f' % (bed_dip)
                SampRec["bed_dip_direction"] = '%7.1f' % (bed_dip_dir)
                SampRec["dip"] = '%7.1f' % (labdip)
                SampRec["azimuth"] = '%7.1f' % (labaz)
                SampRec["azimuth_dec_correction"] = '%7.1f' % (deccorr)
                SampRec["geologic_classes"] = sclass
                SampRec["lithologies"] = lithology
                SampRec["geologic_types"] = _type
                SampRec["method_codes"] = method_codes
                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
                SiteRec["geologic_classes"] = sclass
                SiteRec["lithologies"] = lithology
                SiteRec["geologic_types"] = _type
                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
                # LocRec["geologic_classes"]=sclass
                # LocRec["lithologies"]=lithology
                # LocRec["geologic_types"]=_type
                LocRecs.append(LocRec)

        else:
            MeasRec = {}
            MeasRec["treat_temp"] = '%8.3e' % (273)  # room temp in kelvin
            MeasRec["meas_temp"] = '%8.3e' % (273)  # room temp in kelvin
            MeasRec["treat_ac_field"] = '0'
            MeasRec["treat_dc_field"] = '0'
            MeasRec["treat_dc_field_phi"] = '0'
            MeasRec["treat_dc_field_theta"] = '0'
            meas_type = "LT-NO"
            MeasRec["quality"] = 'g'
            MeasRec["standard"] = 'u'
            MeasRec["treat_step_num"] = 0
            MeasRec["specimen"] = specname
            el, demag = 1, ''
            treat = rec[el]
            if treat[-1] == 'C':
                demag = 'T'
            elif treat != 'NRM':
                demag = 'AF'
            el += 1
            while rec[el] == "":
                el += 1
            MeasRec["dir_dec"] = rec[el]
            cdec = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            MeasRec["dir_inc"] = rec[el]
            cinc = float(rec[el])
            el += 1
            while rec[el] == "":
                el += 1
            gdec = rec[el]
            el += 1
            while rec[el] == "":
                el += 1
            ginc = rec[el]
            el = skip(2, el, rec)  # skip bdec,binc
#                el=skip(4,el,rec) # skip gdec,ginc,bdec,binc
#                print 'moment emu: ',rec[el]
            MeasRec["magn_moment"] = '%10.3e' % (
                float(rec[el])*1e-3)  # moment in Am^2 (from emu)
            MeasRec["magn_volume"] = '%10.3e' % (
                float(rec[el])*1e-3/vol)  # magnetization in A/m
            el = skip(2, el, rec)  # skip to xsig
            MeasRec["magn_x_sigma"] = '%10.3e' % (
                float(rec[el])*1e-3)  # convert from emu
            el = skip(3, el, rec)  # skip to ysig
            MeasRec["magn_y_sigma"] = '%10.3e' % (
                float(rec[el])*1e-3)  # convert from emu
            el = skip(3, el, rec)  # skip to zsig
            MeasRec["magn_z_sigma"] = '%10.3e' % (
                float(rec[el])*1e-3)  # convert from emu
            el += 1  # skip to positions
            MeasRec["meas_n_orient"] = rec[el]
#                    el=skip(5,el,rec) # skip to date
#                    mm=str(months.index(date[0]))
#                    if len(mm)==1:
#                        mm='0'+str(mm)
#                    else:
#                        mm=str(mm)
#                    dstring=date[2]+':'+mm+':'+date[1]+":"+date[3]
#                    MeasRec['measurement_date']=dstring
            MeasRec["instrument_codes"] = inst
            MeasRec["analysts"] = user
            MeasRec["citations"] = "This study"
            MeasRec["method_codes"] = meas_type
            if demag == "AF":
                MeasRec["treat_ac_field"] = '%8.3e' % (
                    float(treat[:-2])*1e-3)  # peak field in tesla
                meas_type = "LT-AF-Z"
                MeasRec["treat_dc_field"] = '0'
            elif demag == "T":
                MeasRec["treat_temp"] = '%8.3e' % (
                    float(treat[:-1])+273.)  # temp in kelvin
                meas_type = "LT-T-Z"
            MeasRec['method_codes'] = meas_type
            MeasRecs.append(MeasRec)

    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)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)

    con.write_table_to_file('specimens', custom_name=spec_file)
    con.write_table_to_file('samples', custom_name=samp_file)
    con.write_table_to_file('sites', custom_name=site_file)
    con.write_table_to_file('locations', custom_name=loc_file)
    con.write_table_to_file('measurements', custom_name=meas_file)
    return True, meas_file

Response: Convert 2G binary format file to MagIC file


Instruction:
Write a Python 3 function for
converting AGM format file to MagIC file

Response:
def agm(agm_file, dir_path=".", input_dir_path="",
        meas_outfile="", spec_outfile="", samp_outfile="",
        site_outfile="", loc_outfile="", spec_infile="",
        samp_infile="", site_infile="",
        specimen="", specnum=0, samp_con="1", location="unknown",
        instrument="", institution="", bak=False, syn=False, syntype="",
        units="cgs", fmt='new', user=''):
    """
    Convert AGM format file to MagIC file(s)

    Parameters
    ----------
    agm_file : str
        input file name
    dir_path : str
        working directory, default "."
    input_dir_path : str
        input file directory IF different from dir_path, default ""
    meas_outfile : str
        output measurement file name, default ""
        (default output is SPECNAME.magic)
    spec_outfile : str
        output specimen file name, default ""
        (default output is SPEC_specimens.txt)
    samp_outfile: str
        output sample file name, default ""
        (default output is SPEC_samples.txt)
    site_outfile : str
        output site file name, default ""
        (default output is SPEC_sites.txt)
    loc_outfile : str
        output location file name, default ""
        (default output is SPEC_locations.txt)
    samp_infile : str
        existing sample infile (not required), default ""
    site_infile : str
        existing site infile (not required), default ""
    specimen : str
        specimen name, default ""
        (default is to take base of input file name, e.g. SPEC.agm)
    specnum : int
        number of characters to designate a specimen, default 0
    samp_con : str
        sample/site naming convention, default '1', see info below
    location : str
        location name, default "unknown"
    instrument : str
        instrument name, default ""
    institution : str
        institution name, default ""
    bak : bool
       IRM backfield curve, default False
    syn : bool
       synthetic, default False
    syntype : str
       synthetic type, default ""
    units : str
       units, default "cgs"
    fmt: str
        input format, options: ('new', 'old', 'xy', default 'new')
    user : user name

    Returns
    ---------
    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
    citations = 'This study'
    meth = "LP-HYS"
    version_num = pmag.get_version()
    Samps, Sites = [], []
    #noave = 1

    # get args
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, dir_path)
    specnum = - int(specnum)
    if not specimen:
        # grab the specimen name from the input file name
        specimen = agm_file.split('.')[0]
    if not meas_outfile:
        meas_outfile = specimen + '.magic'
    if not spec_outfile:
        spec_outfile = specimen + '_specimens.txt'
    if not samp_outfile:
        samp_file = specimen + '_samples.txt'
    if not site_outfile:
        site_file = specimen + '_sites.txt'
    if not loc_outfile:
        loc_outfile = specimen + '_locations.txt'
    if bak:
        meth = "LP-IRM-DCD"
        output = output_dir_path + "/irm.magic"
    if "4" == samp_con[0]:
        if "-" not in samp_con:
            print(
                "naming convention option [4] must be in form 4-Z where Z is an integer")
            print('---------------')
            return False, "naming convention option [4] must be in form 4-Z where Z is an integer"
        else:
            Z = samp_con.split("-")[1]
            samp_con = "4"
    if "7" == samp_con[0]:
        if "-" not in samp_con:
            print("option [7] must be in form 7-Z where Z is an integer")
            return False, "option [7] must be in form 7-Z where Z is an integer"
        else:
            Z = samp_con.split("-")[1]
            samp_con = "7"
    else:
        Z = 0

    # read stuff in
    if site_infile:
        Sites, file_type = pmag.magic_read(site_infile)
    if samp_infile:
        Samps, file_type = pmag.magic_read(samp_infile)
    if spec_infile:
        Specs, file_type = pmag.magic_read(spec_infile)
    if agm_file:
        agm_file = pmag.resolve_file_name(agm_file, input_dir_path)
        Data = pmag.open_file(agm_file)
        if not Data:
            print("you must provide a valid agm_file")
            return False, "you must provide a valid agm_file"
    if not agm_file:
        print(__doc__)
        print("agm_file field is required option")
        return False, "agm_file field is required option"
    if "ASCII" not in Data[0] and fmt != 'xy':
        fmt = 'new'
    measnum, start, end = 1, 0, 0
    if fmt == 'new':  # new Micromag formatted file
        end = 2
        for skip in range(len(Data)):
            line = Data[skip]
            rec = line.strip('\n').strip('\r').split()
            if 'Units' in line:
                units = rec[-1]
            if "Raw" in rec:
                start = skip + 2
            if ("Field" in rec) and ("Moment" in rec) and (not start):
                start = skip + 2
                break
    elif fmt == 'old':
        start = 2
        end = 1

    MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
    version_num = pmag.get_version()

    ##################################
    # parse data
    stop = len(Data) - end
    for line in Data[start:stop]:  # skip header stuff
        MeasRec, SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}, {}
        # take care of some paper work
        if not syn:
            MeasRec["specimen"] = specimen
            if specnum != 0:
                sample = specimen[:specnum]
            else:
                sample = specimen
            if samp_infile and Samps:  # if samp_infile was provided AND yielded sample data
                samp = pmag.get_dictitem(Samps, 'sample', sample, 'T')
                if len(samp) > 0:
                    site = samp[0]["site"]
                else:
                    site = ''
            if site_infile and Sites:  # if samp_infile was provided AND yielded sample data
                sites = pmag.get_dictitem(Sites, 'sample', sample, 'T')
                if len(sites) > 0:
                    site = sites[0]["site"]
                else:
                    site = ''
            else:
                site = pmag.parse_site(sample, samp_con, Z)
            if location != '' and location not in [x['location'] if 'location' in list(x.keys()) else '' for x in LocRecs]:
                LocRec['location'] = location
                LocRecs.append(LocRec)
            if site != '' and site not in [x['site'] if 'site' in list(x.keys()) else '' for x in SiteRecs]:
                SiteRec['location'] = location
                SiteRec['site'] = site
                SiteRecs.append(SiteRec)
            if sample != '' and sample not in [x['sample'] if 'sample' in list(x.keys()) else '' for x in SampRecs]:
                SampRec['site'] = site
                SampRec['sample'] = sample
                SampRecs.append(SampRec)
            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
                SpecRecs.append(SpecRec)
        else:
            SampRec["material_type"] = syntype
            MeasRec["specimen"] = specimen
            MeasRec["user"] = user
            if specnum != 0:
                sample = specimen[:specnum]
            else:
                sample = specimen
            site = pmag.parse_site(sample, samp_con, Z)
            if location != '' and location not in [x['location'] if 'location' in list(x.keys()) else '' for x in LocRecs]:
                LocRec['location'] = location
                LocRecs.append(LocRec)
            if site != '' and site not in [x['site'] if 'site' in list(x.keys()) else '' for x in SiteRecs]:
                SiteRec['location'] = location
                SiteRec['site'] = site
                SiteRecs.append(SiteRec)
            if sample != '' and sample not in [x['sample'] if 'sample' in list(x.keys()) else '' for x in SampRecs]:
                SampRec['site'] = site
                SampRec['sample'] = sample
                SampRecs.append(SampRec)
            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
                SpecRecs.append(SpecRec)
        MeasRec['instrument_codes'] = instrument
        MeasRec['institution'] = institution
        MeasRec['method_codes'] = meth
        MeasRec['experiment'] = specimen + ':' + meth
        if fmt == 'xy':
            rec = list(line.strip('\n').split())
        else:
            rec = list(line.strip('\n').strip('\r').split(','))
        #print (rec)
        if rec[0] != "":
            if units == 'cgs':
                field = float(rec[0]) * 1e-4  # convert from oe to tesla
            else:
                field = float(rec[0])  # field in tesla
            if meth == "LP-HYS":
                MeasRec['meas_field_dc'] = '%10.3e' % (field)
                MeasRec['treat_dc_field'] = '0'
            else:
                MeasRec['meas_field_dc'] = '0'
                MeasRec['treat_dc_field'] = '%10.3e' % (field)
            if units == 'cgs':
                MeasRec['magn_moment'] = '%10.3e' % (
                    float(rec[1]) * 1e-3)  # convert from emu to Am^2
            else:
                MeasRec['magn_moment'] = '%10.3e' % (float(rec[1]))  # Am^2
            MeasRec['treat_temp'] = '273'  # temp in kelvin
            MeasRec['meas_temp'] = '273'  # temp in kelvin
            MeasRec['quality'] = 'g'
            MeasRec['standard'] = 'u'
            MeasRec['treat_step_num'] = '%i' % (measnum)
            MeasRec['measurement'] = specimen + ":" + meth + '%i' % (measnum)
            measnum += 1
            MeasRec['software_packages'] = version_num
            MeasRec['description'] = ""
            MeasRecs.append(MeasRec)
    # we have to relabel LP-HYS method codes.  initial loop is LP-IMT, minor
    # loops are LP-M  - do this in measurements_methods function
    if meth == 'LP-HYS':
        recnum = 0
        while float(MeasRecs[recnum]['meas_field_dc']) < float(MeasRecs[recnum + 1]['meas_field_dc']) and recnum + 1 < len(MeasRecs):  # this is LP-IMAG
            MeasRecs[recnum]['method_codes'] = 'LP-IMAG'
            MeasRecs[recnum]['experiment'] = MeasRecs[recnum]['specimen'] + \
                ":" + 'LP-IMAG'
            recnum += 1
#
    con = cb.Contribution(output_dir_path, read_tables=[])

    # create MagIC 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)
    con.add_magic_table_from_data(dtype='measurements', data=MeasRecs)
    # write MagIC tables to file
    con.write_table_to_file('specimens', custom_name=spec_outfile)
    con.write_table_to_file('samples', custom_name=samp_outfile)
    con.write_table_to_file('sites', custom_name=site_outfile)
    con.write_table_to_file('locations', custom_name=loc_outfile)
    con.write_table_to_file('measurements', custom_name=meas_outfile)

    return True, meas_outfile


Instruction:
Implement a function in Python 3 to
convert BGC format file to MagIC file

Response:
def bgc(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', append=False,
        location="unknown", site="", samp_con='1', specnum=0,
        meth_code="LP-NO", volume=12, user="", timezone='US/Pacific', noave=False):

    """
    Convert BGC format file to MagIC file(s)

    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 ""
    meas_file : str
        output measurement file name, default "measurements.txt"
    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"
    site : str
        site name, default ""
    samp_con : str
        sample/site naming convention, default '1', see info below
    specnum : int
        number of characters to designate a specimen, default 0
    meth_code : str
        orientation method codes, default "LP-NO"
        e.g. [SO-MAG, SO-SUN, SO-SIGHT, ...]
    volume : float
        volume in ccs, default 12.
    user : str
        user name, default ""
    timezone : str
        timezone in pytz library format, default "US/Pacific"
        list of timezones can be found at http://pytz.sourceforge.net/
    noave : bool
       do not average duplicate measurements, default False (so by default, DO average)

    Returns
    ---------
    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 same as sample
        [6] site is entered under a separate column -- NOT CURRENTLY SUPPORTED
        [7-Z] [XXXX]YYY:  XXXX is site designation with Z characters with sample name XXXXYYYY

    """

    version_num = pmag.get_version()
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, dir_path)
    samp_con = str(samp_con)
    specnum = - int(specnum)
    volume *= 1e-6  # convert cc to m^3

    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, "option [4] must be in form 4-Z where Z is an integer"
        else:
            Z = int(samp_con.split("-")[1])
            samp_con = "4"
    if "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, "option [7] must be in form 7-Z where Z is an integer"
        else:
            Z = int(samp_con.split("-")[1])
            samp_con = "7"
    else:
        Z = 1

    # format variables
    mag_file = os.path.join(input_dir_path, mag_file)
    if not os.path.isfile(mag_file):
        print("%s is not a BGC file" % mag_file)
        return False, 'You must provide a BCG format file'

    # Open up the BGC file and read the header information
    print('mag_file in bgc_magic', mag_file)
    pre_data = open(mag_file, 'r')
    line = pre_data.readline()
    line_items = line.split(' ')
    specimen = line_items[2]
    specimen = specimen.replace('\n', '')
    line = pre_data.readline()
    line = pre_data.readline()
    line_items = line.split('\t')
    azimuth = float(line_items[1])
    dip = float(line_items[2])
    bed_dip = line_items[3]
    sample_bed_azimuth = line_items[4]
    lon = line_items[5]
    lat = line_items[6]
    tmp_volume = line_items[7]
    if tmp_volume != 0.0:
        volume = float(tmp_volume) * 1e-6
    pre_data.close()

    data = pd.read_csv(mag_file, sep='\t', header=3, index_col=False)

    cart = np.array([data['X'], data['Y'], data['Z']]).transpose()
    direction = pmag.cart2dir(cart).transpose()

    data['dir_dec'] = direction[0]
    data['dir_inc'] = direction[1]
    # the data are in EMU - this converts to Am^2
    data['magn_moment'] = direction[2] / 1000
    data['magn_volume'] = (direction[2] / 1000) / \
        volume  # EMU  - data converted to A/m

    # Configure the magic_measurements table
    MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
    for rowNum, row in data.iterrows():
        MeasRec, SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}, {}

        if specnum != 0:
            sample = specimen[:specnum]
        else:
            sample = specimen
        if site == '':
            site = pmag.parse_site(sample, samp_con, Z)

        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'] = volume
            SpecRec['analysts'] = user
            SpecRec['citations'] = 'This study'
            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['azimuth'] = azimuth
            SampRec['dip'] = dip
            SampRec['bed_dip_direction'] = sample_bed_azimuth
            SampRec['bed_dip'] = bed_dip
            SampRec['method_codes'] = meth_code
            SampRec['analysts'] = user
            SampRec['citations'] = 'This study'
            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
            SiteRec['analysts'] = user
            SiteRec['citations'] = 'This study'
            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['analysts'] = user
            LocRec['citations'] = 'This study'
            LocRec['lat_n'] = lat
            LocRec['lon_e'] = lon
            LocRec['lat_s'] = lat
            LocRec['lon_w'] = lon
            LocRecs.append(LocRec)

        MeasRec['description'] = 'Date: ' + \
            str(row['Date']) + ' Time: ' + str(row['Time'])
        if '.' in row['Date']:
            datelist = row['Date'].split('.')
        elif '/' in row['Date']:
            datelist = row['Date'].split('/')
        elif '-' in row['Date']:
            datelist = row['Date'].split('-')
        else:
            print(
                "unrecogized date formating on one of the measurement entries for specimen %s" % specimen)
            datelist = ['', '', '']
        if ':' in row['Time']:
            timelist = row['Time'].split(':')
        else:
            print(
                "unrecogized time formating on one of the measurement entries for specimen %s" % specimen)
            timelist = ['', '', '']
        datelist[2] = '19' + \
            datelist[2] if len(datelist[2]) <= 2 else datelist[2]
        dt = ":".join([datelist[1], datelist[0], datelist[2],
                       timelist[0], timelist[1], timelist[2]])
        local = pytz.timezone(timezone)
        naive = datetime.datetime.strptime(dt, "%m:%d:%Y:%H:%M:%S")
        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"
        MeasRec["timestamp"] = timestamp
        MeasRec["citations"] = "This study"
        MeasRec['software_packages'] = version_num
        MeasRec["treat_temp"] = '%8.3e' % (273)  # room temp in kelvin
        MeasRec["meas_temp"] = '%8.3e' % (273)  # room temp in kelvin
        MeasRec["quality"] = 'g'
        MeasRec["standard"] = 'u'
        MeasRec["treat_step_num"] = rowNum
        MeasRec["specimen"] = specimen
        MeasRec["treat_ac_field"] = '0'
        if row['DM Val'] == '0':
            meas_type = "LT-NO"
        elif int(row['DM Type']) > 0.0:
            meas_type = "LT-AF-Z"
            treat = float(row['DM Val'])
            MeasRec["treat_ac_field"] = '%8.3e' % (
                treat*1e-3)  # convert from mT to tesla
        elif int(row['DM Type']) == -1:
            meas_type = "LT-T-Z"
            treat = float(row['DM Val'])
            MeasRec["treat_temp"] = '%8.3e' % (treat+273.)  # temp in kelvin
        else:
            print("measurement type unknown:",
                  row['DM Type'], " in row ", rowNum)
        MeasRec["magn_moment"] = str(row['magn_moment'])
        MeasRec["magn_volume"] = str(row['magn_volume'])
        MeasRec["dir_dec"] = str(row['dir_dec'])
        MeasRec["dir_inc"] = str(row['dir_inc'])
        MeasRec['method_codes'] = meas_type
        MeasRec['dir_csd'] = '0.0'  # added due to magic.write error
        MeasRec['meas_n_orient'] = '1'  # added due to magic.write error
        MeasRecs.append(MeasRec.copy())

    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)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)

    con.write_table_to_file('specimens', custom_name=spec_file, append=append)
    con.write_table_to_file('samples', custom_name=samp_file, append=append)
    con.write_table_to_file('sites', custom_name=site_file, append=append)
    con.write_table_to_file('locations', custom_name=loc_file, append=append)
    meas_file = con.write_table_to_file(
        'measurements', custom_name=meas_file, append=append)

    return True, meas_file


Instruction:
Can you generate a brief explanation for the following Python 3 code
def cit(dir_path=".", input_dir_path="", magfile="", user="", meas_file="measurements.txt",
        spec_file="specimens.txt", samp_file="samples.txt",
        site_file="sites.txt", loc_file="locations.txt", locname="unknown",
        sitename="", methods=['SO-MAG'], specnum=0, samp_con='3',
        norm='cc', oersted=False, noave=False, meas_n_orient='8',
        labfield=0, phi=0, theta=0):
    """
    Converts CIT formated Magnetometer data into MagIC format for Analysis and contribution to the MagIC database

    Parameters
    -----------
    dir_path : directory to output files to (default : current directory)
    input_dir_path : directory to input files (only needed if different from dir_path!)
    magfile : magnetometer file (.sam) to convert to MagIC (required)
    user : colon delimited list of analysts (default : "")
    meas_file : measurement file name to output (default : measurements.txt)
    spec_file : specimen file name to output (default : specimens.txt)
    samp_file : sample file name to output (default : samples.txt)
    site_file : site file name to output (default : site.txt)
    loc_file : location file name to output (default : locations.txt)
    locname : location name
    sitename : site name set by user instead of using samp_con
    methods : colon delimited list of sample method codes. full list here (https://www2.earthref.org/MagIC/method-codes) (default : SO-MAG)
    specnum : number of terminal characters that identify a specimen
    norm : is volume or mass normalization using cgs or si units (options : cc,m3,g,kg) (default : cc)
    oersted : demag step values are in Oersted
    noave : average measurement data or not. False is average, True is don't average. (default : False)
    samp_con : sample naming convention options as follows:
        [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 sitename 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
    meas_n_orient : Number of different orientations in measurement (default : 8)
    labfield : DC_FIELD in microTesla (default : 0)
    phi : DC_PHI in degrees (default : 0)
    theta : DC_THETA in degrees (default : 0)

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

    def get_dc_params(FIRST_GET_DC, specimen, treat_type, yn):
        """
        Prompts user for DC field data if not provided, just an encapsulation function for the above program and should not be used elsewhere.

        Parameters
        -----------
        FIRST_GET_DC : is this the first time you are asking for DC data?
        specimen : what specimen do you want DC data for?
        treat_type : what kind of step was it? PTM, Tail, in field, zero field?
        yn : is DC field constant or varrying? (y = constant, n = varrying)

        Returns
        -----------
        GET_DC_PARAMS : weather or not to rerun this function
        FIRST_GET_DC : same as above
        yn : same as above
        DC_FIELD : field strength in Tesla
        DC_PHI : field azimuth
        DC_THETA : field polar angle
        """
        if FIRST_GET_DC:
            yn = input(
                "Is the DC field used in this IZZI study constant or does it varry between specimen or step? (y=const) [y/N]: ")
            FIRST_GET_DC = False
        if "y" == yn:
            DC_FIELD, DC_PHI, DC_THETA = list(map(float, eval(input(
                "What DC field, Phi, and Theta was used for all steps? (float (in microTesla),float,float): "))))
            GET_DC_PARAMS = False
        else:
            DC_FIELD, DC_PHI, DC_THETA = list(map(float, eval(input(
                "What DC field, Phi, and Theta was used for specimen %s and step %s? (float (in microTesla),float,float): " % (str(specimen), str(treat_type))))))
        return GET_DC_PARAMS, FIRST_GET_DC, yn, DC_FIELD*1e-6, DC_PHI, DC_THETA

    specnum = - int(specnum)
    input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, dir_path)
    DC_FIELD = float(labfield) * 1e-6
    DC_PHI = float(phi)
    DC_THETA = float(theta)
    #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.')
#    yn = ''
#    if DC_FIELD == 0 and DC_PHI == 0 and DC_THETA == 0:
#        print('-I- Required values for labfield, phi, and theta not provided!  Will try to get these interactively')
#        GET_DC_PARAMS = True
#    else:
#        GET_DC_PARAMS = False

# With the above commented out GET_DC_PARAMS does not get set and this function fail below so setting it here. NAJ
    GET_DC_PARAMS = False
    if locname == '' or locname == None:
        locname = 'unknown'
    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:
            Z = 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:
            Z = samp_con.split("-")[1]
            samp_con = "7"
    else:
        Z = 1

    # get file names and open magfile to start reading data
    magfile = pmag.resolve_file_name(magfile, input_dir_path)
    input_dir_path = os.path.split(magfile)[0]
    FIRST_GET_DC = True
    try:
        file_input = open(magfile, 'r')
    except IOError as ex:
        print(ex)
        print(("bad sam file name: ", magfile))
        return False, "bad sam file name"
    File = file_input.readlines()
    file_input.close()
    if len(File) == 1:
        File = File[0].split('\r')
        File = [x+"\r\n" for x in File]

    # define initial variables
    SpecRecs, SampRecs, SiteRecs, LocRecs, MeasRecs = [], [], [], [], []
    sids, ln, format, citations = [], 0, 'CIT', "This study"
    formats = ['CIT', '2G', 'APP', 'JRA']

    if File[ln].strip() == 'CIT':
        ln += 1
    LocRec = {}
    LocRec["location"] = locname
    LocRec["citations"] = citations
    LocRec['analysts'] = user
    comment = File[ln]
    if comment == 'CIT':
        format = comment
        ln += 1
    comment = File[ln]
    print(comment)
    ln += 1
    specimens, samples, sites = [], [], []
    if format == 'CIT':
        line = File[ln].split()
        site_lat = line[0]
        site_lon = line[1]
        LocRec["lat_n"] = site_lat
        LocRec["lon_e"] = site_lon
        LocRec["lat_s"] = site_lat
        LocRec["lon_w"] = site_lon
        LocRecs.append(LocRec)
        Cdec = float(line[2])
        for k in range(ln+1, len(File)):
            line = File[k]
            rec = line.split()
            if rec == []:
                continue
            specimen = rec[0]
            specimens.append(specimen)
    for specimen in specimens:
        SpecRec, SampRec, SiteRec = {}, {}, {}
        if specnum != 0:
            sample = specimen[:specnum]
        else:
            sample = specimen
        if sitename:
            site = sitename
        else:
            site = pmag.parse_site(sample, samp_con, Z)
        SpecRec['specimen'] = specimen
        SpecRec['sample'] = sample
        SpecRec['citations'] = citations
        SpecRec['analysts'] = user
        SampRec['sample'] = sample
        SampRec['site'] = site
        SampRec['citations'] = citations
        SampRec['method_codes'] = methods
        SampRec['azimuth_dec_correction'] = '%7.1f' % (Cdec)
        SampRec['analysts'] = user
        SiteRec['site'] = site
        SiteRec['location'] = locname
        SiteRec['citations'] = citations
        SiteRec['lat'] = site_lat
        SiteRec['lon'] = site_lon
        SiteRec['analysts'] = user
        f = open(os.path.join(input_dir_path, specimen), 'r')
        Lines = f.readlines()
        f.close()
        comment = ""
        line = Lines[0].split()
        if len(line) > 2:
            comment = line[2]
        info = Lines[1].split()
        volmass = float(info[-1])
        if volmass == 1.0:
            print('Warning: Specimen volume set to 1.0.')
            print('Warning: If volume/mass really is 1.0, set volume/mass to 1.001')
            print('Warning: specimen method code LP-NOMAG set.')
            SpecRec['weight'] = ""
            SpecRec['volume'] = ""
            SpecRec['method_codes'] = 'LP-NOMAG'
        elif norm == "gm":
            SpecRec['volume'] = ''
            SpecRec['weight'] = '%10.3e' % volmass*1e-3
        elif norm == "kg":
            SpecRec['volume'] = ''
            SpecRec['weight'] = '%10.3e'*volmass
        elif norm == "cc":
            SpecRec['weight'] = ""
            SpecRec['volume'] = '%10.3e' % (volmass*1e-6)
        elif norm == "m3":
            SpecRec['weight'] = ""
            SpecRec['volume'] = '%10.3e' % (volmass)
        else:
            print('Warning: Unknown normalization unit ',
                  norm, '. Using default of cc')
            SpecRec['weight'] = ""
            SpecRec['volume'] = '%10.3e' % (volmass*1e-6)
        dip = float(info[-2])
        dip_direction = float(info[-3])+Cdec+90.
        sample_dip = -float(info[-4])
        sample_azimuth = float(info[-5])+Cdec-90.
        if len(info) > 5:
            SampRec['height'] = info[-6]
        else:
            SampRec['height'] = '0'
        SampRec['azimuth'] = '%7.1f' % (sample_azimuth)
        SampRec['dip'] = '%7.1f' % (sample_dip)
        SampRec['bed_dip'] = '%7.1f' % (dip)
        SampRec['bed_dip_direction'] = '%7.1f' % (dip_direction)
        SampRec['geologic_classes'] = ''
        SampRec['geologic_types'] = ''
        SampRec['lithologies'] = ''
        if Cdec != 0 or Cdec != "":
            SampRec['method_codes'] = 'SO-CMD-NORTH'
        else:
            SampRec['method_codes'] = 'SO-MAG'
        for line in Lines[2:len(Lines)]:
            if line == '\n':
                continue
            MeasRec = SpecRec.copy()
            MeasRec.pop('sample')
            MeasRec['analysts'] = user
#           Remove volume and weight as they do not exits in the magic_measurement table
            del MeasRec["volume"]
            del MeasRec["weight"]
            # USGS files have blank for an AF demag value when measurement is the NRM. njarboe
            if line[0:6] == 'AF    ':
                line = 'NRM' + line[3:]
            treat_type = line[0:3]
            if treat_type[1] == '.':
                treat_type = 'NRM'
            treat = line[2:6]
            try:
                float(treat)
            except ValueError:
                treat = line[3:6]
                if treat.split() == '':
                    treat = '0'
                try:
                    float(treat)
                except ValueError:
                    treat = line.split()[1]
            if treat_type.startswith('NRM'):
                MeasRec['method_codes'] = 'LT-NO'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = '273'
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif treat_type.startswith('LT') or treat_type.upper().startswith('LN2'):
                MeasRec['method_codes'] = 'LT-LT-Z'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = '77'
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif treat_type.startswith('AF') or treat_type.startswith('MAF'):
                MeasRec['method_codes'] = 'LT-AF-Z'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = '273'
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                if treat.strip() == '':
                    MeasRec['treat_ac_field'] = '0'
                else:
                    try:
                        MeasRec['treat_ac_field'] = '%10.3e' % (
                            float(treat)*1e-3)
                    except ValueError as e:
                        print(os.path.join(input_dir_path, specimen))
                        raise e
                if MeasRec['treat_ac_field'] != '0':
                    MeasRec['treat_ac_field'] = '%10.3e' % (
                        float(MeasRec['treat_ac_field'])/10)
            elif treat_type.startswith('ARM'):
                MeasRec['method_codes'] = "LP-ARM"
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = '273'
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                if treat.strip() == '':
                    MeasRec['treat_ac_field'] = '0'
                else:
                    MeasRec['method_codes'] = "LP-ARM-AFD"
                    MeasRec['treat_ac_field'] = '%10.3e' % (float(treat)*1e-3)
            elif treat_type.startswith('IRM'):
                if GET_DC_PARAMS:
                    GET_DC_PARAMS, FIRST_GET_DC, yn, DC_FIELD, DC_PHI, DC_THETA = get_dc_params(
                        FIRST_GET_DC, specimen, treat_type, yn)
                MeasRec['method_codes'] = "LT-IRM"
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = '273'
                MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif treat_type.startswith('TT'):
                MeasRec['method_codes'] = 'LT-T-Z'
                MeasRec['meas_temp'] = '273'
                if treat.strip() == '':
                    MeasRec['treat_temp'] = '273'
                else:
                    MeasRec['treat_temp'] = '%7.1f' % (float(treat)+273)
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif line[4] == '0':  # assume decimal IZZI format 0 field thus can hardcode the dc fields
                MeasRec['method_codes'] = 'LT-T-Z'
                MeasRec['meas_temp'] = '273'
                try:
                    MeasRec['treat_temp'] = str(int(treat_type) + 273)
                except ValueError as e:
                    print(specimen)
                    raise e
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif line[4] == '1':  # assume decimal IZZI format in constant field
                if GET_DC_PARAMS:
                    GET_DC_PARAMS, FIRST_GET_DC, yn, DC_FIELD, DC_PHI, DC_THETA = get_dc_params(
                        FIRST_GET_DC, specimen, treat_type, yn)
                MeasRec['method_codes'] = 'LT-T-I'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = str(int(treat_type) + 273)
                MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif line[4] == '2':  # assume decimal IZZI format PTRM step
                if GET_DC_PARAMS:
                    GET_DC_PARAMS, FIRST_GET_DC, yn, DC_FIELD, DC_PHI, DC_THETA = get_dc_params(
                        FIRST_GET_DC, specimen, treat_type, yn)
                MeasRec['method_codes'] = 'LT-PTRM-I'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = str(int(treat_type) + 273)
                MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            elif line[4] == '3':  # assume decimal IZZI format PTRM tail check
                if GET_DC_PARAMS:
                    GET_DC_PARAMS, FIRST_GET_DC, yn, DC_FIELD, DC_PHI, DC_THETA = get_dc_params(
                        FIRST_GET_DC, specimen, treat_type, yn)
                MeasRec['method_codes'] = 'LT-PTRM-Z'
                MeasRec['meas_temp'] = '273'
                MeasRec['treat_temp'] = str(int(treat_type) + 273)
                MeasRec['treat_dc_field'] = '0'
                MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
                MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
                MeasRec['treat_ac_field'] = '0'
            else:
                print("trouble with your treatment steps")
            MeasRec['dir_dec'] = line[46:51]
            MeasRec['dir_inc'] = line[52:58]
#           Some MIT files have and extra digit in the exponent of the magnetude.
#           That makes those files not compliant with the cit measurement file spec.
#           Not sure if we should just print an error message and exit. For now we accept the file and fix it.
#           The first digit of the exponent, which should always be zero, is cut out of the line if column 39 is not ' '
            if line[39] != ' ':
                line = line[0:37] + line[38:]
            M = '%8.2e' % (float(line[31:39])*volmass*1e-3)  # convert to Am2
            MeasRec['magn_moment'] = M
            MeasRec['dir_csd'] = '%7.1f' % (eval(line[41:46]))
            MeasRec["meas_n_orient"] = meas_n_orient
            MeasRec['standard'] = 'u'
            if len(line) > 60:
                MeasRec['instrument_codes'] = line[85:].strip('\n \r \t "')
                MeasRec['magn_x_sigma'] = '%8.2e' % (
                    float(line[58:67])*1e-8)  # (convert e-5emu to Am2)
                MeasRec['magn_y_sigma'] = '%8.2e' % (float(line[67:76])*1e-8)
                MeasRec['magn_z_sigma'] = '%8.2e' % (float(line[76:85])*1e-8)
            MeasRecs.append(MeasRec)
        SpecRecs.append(SpecRec)
        if sample not in samples:
            samples.append(sample)
            SampRecs.append(SampRec)
        if site not in sites:
            sites.append(site)
            SiteRecs.append(SiteRec)

    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)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)

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

    return True, meas_file

Response: This function converts CIT formated Magnetometer data into MagIC format for Analysis and contribution to the MagIC database.


Instruction:
Write a Python 3 function that can
convert generic file to MagIC file

Response:
def generic(magfile="", dir_path=".", meas_file="measurements.txt",
            spec_file="specimens.txt", samp_file="samples.txt", site_file="sites.txt",
            loc_file="locations.txt", user="", labfield=0, labfield_phi=0, labfield_theta=0,
            experiment="", cooling_times_list=[], sample_nc=[1, 0], site_nc=[1, 0],
            location="unknown", lat="", lon="", noave=False, input_dir_path=""):

    """
    Convert generic file to MagIC file(s)

    Parameters
    ----------
    mag_file : str
        input file name
    dir_path : str
        output directory, default "."
    meas_file : str
        output measurement file name, default "measurements.txt"
    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"
    user : str
        user name, default ""
    labfield : float
        dc lab field (in micro tesla)
    labfield_phi : float
        declination 0-360
    labfield_theta : float
        inclination -90 - 90
    experiment : str
        experiment type, see info below
    cooling_times_list : list
        cooling times in [K/minutes] seperated by comma,
        ordered at the same order as XXX.10,XXX.20 ...XX.70
    sample_nc : list
        sample naming convention, default [1, 0], see info below
    site_nc : list
        site naming convention, default [1, 0], see info below
    location : str
        location name, default "unknown"
    lat : float
        latitude, default ""
    lon : float
        longitude, default ""
    noave : bool
       do not average duplicate measurements, default False (so by default, DO average)
    input_dir_path : str
        input file directory IF different from dir_path, default ""

    Info
    --------
    Experiment type:
        Demag:
            AF and/or Thermal
        PI:
            paleointenisty thermal experiment (ZI/IZ/IZZI)
        ATRM n:

            ATRM in n positions (n=6)

        AARM n:
            AARM in n positions
        CR:
            cooling rate experiment
            The treatment coding of the measurement file should be: XXX.00,XXX.10, XXX.20 ...XX.70 etc. (XXX.00 is optional)
            where XXX in the temperature and .10,.20... are running numbers of the cooling rates steps.
            XXX.00 is optional zerofield baseline. XXX.70 is alteration check.
            if using this type, you must also provide cooling rates in [K/minutes] in cooling_times_list
            seperated by comma, ordered at the same order as XXX.10,XXX.20 ...XX.70

            No need to specify the cooling rate for the zerofield
            But users need to make sure that there are no duplicate meaurements in the file

        NLT:
            non-linear-TRM experiment

    Specimen-sample naming convention:
        X determines which kind of convention (initial characters, terminal characters, or delimiter
        Y determines how many characters to remove to go from specimen --> sample OR which delimiter to use
        X=0 Y=n: specimen is distinguished from sample by n initial characters.
                 (example: generic(samp_nc=[0, 4], ...)
                  if n=4 then and specimen = mgf13a then sample = mgf13)
        X=1 Y=n: specimen is distiguished from sample by n terminate characters.
                 (example: generic(samp_nc=[1, 1], ...))
                  if n=1 then and specimen = mgf13a then sample = mgf13)
        X=2 Y=c: specimen is distinguishing from sample by a delimiter.
                 (example: generic([2, "-"]))
                  if c=- then and specimen = mgf13-a then sample = mgf13)
        default: sample is the same as specimen name

    Sample-site naming convention:
        X determines which kind of convention (initial characters, terminal characters, or delimiter
        Y determines how many characters to remove to go from sample --> site OR which delimiter to use
        X=0 Y=n: sample is distiguished from site by n initial characters.
                 (example: generic(site_nc=[0, 3]))
                  if n=3 then and sample = mgf13 then sample = mgf)
        X=1 Y=n: sample is distiguished from site by n terminate characters.
                 (example: generic(site_nc=[1, 2]))
                  if n=2 and sample = mgf13 then site = mgf)
        X=2 Y=c: specimen is distiguishing from sample by a delimiter.
                 (example: generic(site_nc=[2, "-"]))
                  if c='-' and sample = 'mgf-13' then site = mgf)
        default: site name is the same as sample name

    """

    # --------------------------------------
    # functions
    # --------------------------------------

    def sort_magic_file(path, ignore_lines_n, sort_by_this_name):
        '''
        reads a file with headers. Each line is stored as a dictionary following the headers.
        Lines are sorted in DATA by the sort_by_this_name header
        DATA[sort_by_this_name]=[dictionary1,dictionary2,...]
        '''
        DATA = {}
        fin = open(path, 'r')
        # ignore first lines
        for i in range(ignore_lines_n):
            fin.readline()
        # header
        line = fin.readline()
        header = line.strip('\n').split('\t')
        # print header
        for line in fin.readlines():
            if line[0] == "#":
                continue
            tmp_data = {}
            tmp_line = line.strip('\n').split('\t')
            # print tmp_line
            for i in range(len(tmp_line)):
                if i >= len(header):
                    continue
                tmp_data[header[i]] = tmp_line[i]
            DATA[tmp_data[sort_by_this_name]] = tmp_data
        fin.close()
        return(DATA)

    def read_generic_file(path, average_replicates):
        '''
        reads a generic file format. If average_replicates==True average replicate measurements.
        Rrturns a Data dictionary with measurements line sorted by specimen
        Data[specimen_name][dict1,dict2,...]
        '''
        Data = {}
        Fin = open(path, 'r')
        header = Fin.readline().strip('\n').split('\t')
        duplicates = []
        for line in Fin.readlines():
            tmp_data = {}
            # found_duplicate=False
            l = line.strip('\n').split('\t')
            for i in range(min(len(header), len(l))):
                tmp_data[header[i]] = l[i]
            specimen = tmp_data['specimen']
            if specimen not in list(Data.keys()):
                Data[specimen] = []
            Data[specimen].append(tmp_data)
        Fin.close()
        # search from duplicates
        for specimen in list(Data.keys()):
            x = len(Data[specimen])-1
            new_data = []
            duplicates = []
            for i in range(1, x):
                while i < len(Data[specimen]) and Data[specimen][i]['treatment'] == Data[specimen][i-1]['treatment'] and Data[specimen][i]['treatment_type'] == Data[specimen][i-1]['treatment_type']:
                    duplicates.append(Data[specimen][i])
                    del(Data[specimen][i])
                if len(duplicates) > 0:
                    if average_replicates:
                        duplicates.append(Data[specimen][i-1])
                        Data[specimen][i-1] = average_duplicates(duplicates)
                        print("-W- WARNING: averaging %i duplicates for specimen %s treatmant %s" %
                              (len(duplicates), specimen, duplicates[-1]['treatment']))
                        duplicates = []
                    else:
                        Data[specimen][i-1] = duplicates[-1]
                        print("-W- WARNING: found %i duplicates for specimen %s treatmant %s. Taking the last measurement only" %
                              (len(duplicates), specimen, duplicates[-1]['treatment']))
                        duplicates = []

                if i == len(Data[specimen])-1:
                    break

        return(Data)

    def average_duplicates(duplicates):
        '''
        avarage replicate measurements.
        '''
        carts_s, carts_g, carts_t = [], [], []
        for rec in duplicates:
            moment = float(rec['moment'])
            if 'dec_s' in list(rec.keys()) and 'inc_s' in list(rec.keys()):
                if rec['dec_s'] != "" and rec['inc_s'] != "":
                    dec_s = float(rec['dec_s'])
                    inc_s = float(rec['inc_s'])
                    cart_s = pmag.dir2cart([dec_s, inc_s, moment])
                    carts_s.append(cart_s)
            if 'dec_g' in list(rec.keys()) and 'inc_g' in list(rec.keys()):
                if rec['dec_g'] != "" and rec['inc_g'] != "":
                    dec_g = float(rec['dec_g'])
                    inc_g = float(rec['inc_g'])
                    cart_g = pmag.dir2cart([dec_g, inc_g, moment])
                    carts_g.append(cart_g)
            if 'dec_t' in list(rec.keys()) and 'inc_t' in list(rec.keys()):
                if rec['dec_t'] != "" and rec['inc_t'] != "":
                    dec_t = float(rec['dec_t'])
                    inc_t = float(rec['inc_t'])
                    cart_t = pmag.dir2cart([dec_t, inc_t, moment])
                    carts_t.append(cart_t)
        if len(carts_s) > 0:
            carts = scipy.array(carts_s)
            x_mean = scipy.mean(carts[:, 0])
            y_mean = scipy.mean(carts[:, 1])
            z_mean = scipy.mean(carts[:, 2])
            mean_dir = pmag.cart2dir([x_mean, y_mean, z_mean])
            mean_dec_s = "%.2f" % mean_dir[0]
            mean_inc_s = "%.2f" % mean_dir[1]
            mean_moment = "%10.3e" % mean_dir[2]
        else:
            mean_dec_s, mean_inc_s = "", ""
        if len(carts_g) > 0:
            carts = scipy.array(carts_g)
            x_mean = scipy.mean(carts[:, 0])
            y_mean = scipy.mean(carts[:, 1])
            z_mean = scipy.mean(carts[:, 2])
            mean_dir = pmag.cart2dir([x_mean, y_mean, z_mean])
            mean_dec_g = "%.2f" % mean_dir[0]
            mean_inc_g = "%.2f" % mean_dir[1]
            mean_moment = "%10.3e" % mean_dir[2]
        else:
            mean_dec_g, mean_inc_g = "", ""

        if len(carts_t) > 0:
            carts = scipy.array(carts_t)
            x_mean = scipy.mean(carts[:, 0])
            y_mean = scipy.mean(carts[:, 1])
            z_mean = scipy.mean(carts[:, 2])
            mean_dir = pmag.cart2dir([x_mean, y_mean, z_mean])
            mean_dec_t = "%.2f" % mean_dir[0]
            mean_inc_t = "%.2f" % mean_dir[1]
            mean_moment = "%10.3e" % mean_dir[2]
        else:
            mean_dec_t, mean_inc_t = "", ""

        meanrec = {}
        for key in list(duplicates[0].keys()):
            if key in ['dec_s', 'inc_s', 'dec_g', 'inc_g', 'dec_t', 'inc_t', 'moment']:
                continue
            else:
                meanrec[key] = duplicates[0][key]
        meanrec['dec_s'] = mean_dec_s
        meanrec['dec_g'] = mean_dec_g
        meanrec['dec_t'] = mean_dec_t
        meanrec['inc_s'] = mean_inc_s
        meanrec['inc_g'] = mean_inc_g
        meanrec['inc_t'] = mean_inc_t
        meanrec['moment'] = mean_moment
        return meanrec

    def get_upper_level_name(name, nc):
        '''
        get sample/site name from specimen/sample using naming convention
        '''
        if float(nc[0]) == 0:
            if float(nc[1]) != 0:
                number_of_char = int(nc[1])
                high_name = name[:number_of_char]
            else:
                high_name = name
        elif float(nc[0]) == 1:
            if float(nc[1]) != 0:
                number_of_char = int(nc[1])*-1
                high_name = name[:number_of_char]
            else:
                high_name = name
        elif float(nc[0]) == 2:
            d = str(nc[1])
            name_splitted = name.split(d)
            if len(name_splitted) == 1:
                high_name = name_splitted[0]
            else:
                high_name = d.join(name_splitted[:-1])
        else:
            high_name = name
        return high_name

    def merge_pmag_recs(old_recs):
        recs = {}
        recs = copy.deepcopy(old_recs)
        headers = []
        for rec in recs:
            for key in list(rec.keys()):
                if key not in headers:
                    headers.append(key)
        for rec in recs:
            for header in headers:
                if header not in list(rec.keys()):
                    rec[header] = ""
        return recs

    # --------------------------------------
    # start conversion from generic
    # --------------------------------------

    # format and validate variables

    input_dir_path, dir_path = pmag.fix_directories(input_dir_path, dir_path)
    labfield = float(labfield)
    labfield_phi = float(labfield_phi)
    labfield_theta = float(labfield_theta)

    if magfile:
        magfile = pmag.resolve_file_name(magfile, input_dir_path)
        try:
            input = open(magfile, 'r')
        except:
            print("bad mag file:", magfile)
            return False, "bad mag file"
    else:
        print("mag_file field is required option")
        return False, "mag_file field is required option"

    if not experiment:
        print("-E- Must provide experiment. Please provide experiment type of: Demag, PI, ATRM n (n of positions), CR (see below for format), NLT")
        return False, "Must provide experiment. Please provide experiment type of: Demag, PI, ATRM n (n of positions), CR (see help for format), NLT"

    if 'ATRM' in experiment:
        try:
            experiment, atrm_n_pos = experiment.split()
            atrm_n_pos = int(atrm_n_pos)
        except:
            experiment = 'ATRM'
            atrm_n_pos = 6
    if 'AARM' in experiment:
        try:
            experiment, aarm_n_pos = experiment.split()
            aarm_n_pos = int(aarm_n_pos)
        except:
            experiment = 'AARM'
            aarm_n_pos = 6

    if experiment == 'CR':
        if command_line:
            ind = sys.argv.index("CR")
            cooling_times = sys.argv[ind+1]
            cooling_times_list = cooling_times.split(',')
        noave = True
        # if not command line, cooling_times_list is already set

    # --------------------------------------
    # read data from generic file
    # --------------------------------------

    mag_data = read_generic_file(magfile, not noave)

    # --------------------------------------
    # for each specimen get the data, and translate it to MagIC format
    # --------------------------------------

    MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
    specimens_list = sorted(mag_data.keys())
    for specimen in specimens_list:
        measurement_running_number = 0
        this_specimen_treatments = []  # a list of all treatments
        MeasRecs_this_specimen = []
        LP_this_specimen = []  # a list of all lab protocols
        IZ, ZI = 0, 0  # counter for IZ and ZI steps

        for meas_line in mag_data[specimen]:

            # ------------------
            # trivial MeasRec data
            # ------------------

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

            specimen = meas_line['specimen']
            sample = get_upper_level_name(specimen, sample_nc)
            site = get_upper_level_name(sample, site_nc)
            sample_method_codes = ""
            azimuth, dip, DipDir, Dip = "", "", "", ""

            MeasRec['citations'] = "This study"
            MeasRec["specimen"] = specimen
            MeasRec['analysts'] = user
            MeasRec["instrument_codes"] = ""
            MeasRec["quality"] = 'g'
            MeasRec["treat_step_num"] = "%i" % measurement_running_number
            MeasRec["magn_moment"] = '%10.3e' % (
                float(meas_line["moment"])*1e-3)  # in Am^2
            MeasRec["meas_temp"] = '273.'  # room temp in kelvin

            # ------------------
            #  decode treatments from treatment column in the generic file
            # ------------------

            treatment = []
            treatment_code = str(meas_line['treatment']).split(".")
            treatment.append(float(treatment_code[0]))
            if len(treatment_code) == 1:
                treatment.append(0)
            else:
                treatment.append(float(treatment_code[1]))

            # ------------------
            #  lab field direction
            # ------------------

            if experiment in ['PI', 'NLT', 'CR']:
                if float(treatment[1]) in [0., 3.]:  # zerofield step or tail check
                    MeasRec["treat_dc_field"] = "0"
                    MeasRec["treat_dc_field_phi"] = "0"
                    MeasRec["treat_dc_field_theta"] = "0"
                elif not labfield:
                    print(
                        "-W- WARNING: labfield (-dc) is a required argument for this experiment type")
                    return False, "labfield (-dc) is a required argument for this experiment type"
                else:
                    MeasRec["treat_dc_field"] = '%8.3e' % (float(labfield))
                    MeasRec["treat_dc_field_phi"] = "%.2f" % (
                        float(labfield_phi))
                    MeasRec["treat_dc_field_theta"] = "%.2f" % (
                        float(labfield_theta))
            else:
                MeasRec["treat_dc_field"] = ""
                MeasRec["treat_dc_field_phi"] = ""
                MeasRec["treat_dc_field_theta"] = ""

            # ------------------
            # treatment temperature/peak field
            # ------------------

            if experiment == 'Demag':
                if meas_line['treatment_type'] == 'A':
                    MeasRec['treat_temp'] = "273."
                    MeasRec["treat_ac_field"] = "%.3e" % (treatment[0]*1e-3)
                elif meas_line['treatment_type'] == 'N':
                    MeasRec['treat_temp'] = "273."
                    MeasRec["treat_ac_field"] = ""
                else:
                    MeasRec['treat_temp'] = "%.2f" % (treatment[0]+273.)
                    MeasRec["treat_ac_field"] = ""
            else:
                MeasRec['treat_temp'] = "%.2f" % (treatment[0]+273.)
                MeasRec["treat_ac_field"] = ""

            # ---------------------
            # Lab treatment
            # Lab protocol
            # ---------------------

            # ---------------------
            # Lab treatment and lab protocoal for NRM:
            # ---------------------

            if float(meas_line['treatment']) == 0:
                LT = "LT-NO"
                LP = ""  # will be filled later after finishing reading all measurements line

            # ---------------------
            # Lab treatment and lab protocoal for paleointensity experiment
            # ---------------------

            elif experiment == 'PI':
                LP = "LP-PI-TRM"
                if treatment[1] == 0:
                    LT = "LT-T-Z"
                elif treatment[1] == 1 or treatment[1] == 10:  # infield
                    LT = "LT-T-I"
                elif treatment[1] == 2 or treatment[1] == 20:  # pTRM check
                    LT = "LT-PTRM-I"
                    LP = LP+":"+"LP-PI-ALT-PTRM"
                elif treatment[1] == 3 or treatment[1] == 30:  # Tail check
                    LT = "LT-PTRM-MD"
                    LP = LP+":"+"LP-PI-BT-MD"
                elif treatment[1] == 4 or treatment[1] == 40:  # Additivity check
                    LT = "LT-PTRM-AC"
                    LP = LP+":"+"LP-PI-BT-MD"
                else:
                    print("-E- unknown measurement code specimen %s treatmemt %s" %
                          (meas_line['specimen'], meas_line['treatment']))
                    MeasRec = {}
                    continue
                # save all treatment in a list
                # we will use this later to distinguidh between ZI / IZ / and IZZI

                this_specimen_treatments.append(float(meas_line['treatment']))
                if LT == "LT-T-Z":
                    if float(treatment[0]+0.1) in this_specimen_treatments:
                        LP = LP+":"+"LP-PI-IZ"
                if LT == "LT-T-I":
                    if float(treatment[0]+0.0) in this_specimen_treatments:
                        LP = LP+":"+"LP-PI-ZI"
            # ---------------------
            # Lab treatment and lab protocoal for demag experiment
            # ---------------------

            elif "Demag" in experiment:
                if meas_line['treatment_type'] == 'A':
                    LT = "LT-AF-Z"
                    LP = "LP-DIR-AF"
                else:
                    LT = "LT-T-Z"
                    LP = "LP-DIR-T"

            # ---------------------
            # Lab treatment and lab protocoal for ATRM experiment
            # ---------------------

            elif experiment in ['ATRM', 'AARM']:

                if experiment == 'ATRM':
                    LP = "LP-AN-TRM"
                    n_pos = atrm_n_pos
                    if n_pos != 6:
                        print(
                            "the program does not support ATRM in %i position." % n_pos)
                        continue

                if experiment == 'AARM':
                    LP = "LP-AN-ARM"
                    n_pos = aarm_n_pos
                    if n_pos != 6:
                        print(
                            "the program does not support AARM in %i position." % n_pos)
                        continue

                if treatment[1] == 0:
                    if experiment == 'ATRM':
                        LT = "LT-T-Z"
                        MeasRec['treat_temp'] = "%.2f" % (treatment[0]+273.)
                        MeasRec["treat_ac_field"] = ""

                    else:
                        LT = "LT-AF-Z"
                        MeasRec['treat_temp'] = "273."
                        MeasRec["treat_ac_field"] = "%.3e" % (
                            treatment[0]*1e-3)
                    MeasRec["treat_dc_field"] = '0'
                    MeasRec["treat_dc_field_phi"] = '0'
                    MeasRec["treat_dc_field_theta"] = '0'
                else:
                    if experiment == 'ATRM':
                        # alteration check as final measurement
                        if float(treatment[1]) == 70 or float(treatment[1]) == 7:
                            LT = "LT-PTRM-I"
                        else:
                            LT = "LT-T-I"
                    else:
                        LT = "LT-AF-I"
                    MeasRec["treat_dc_field"] = '%8.3e' % (float(labfield))

                    # 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)
                    tdec = [0, 90, 0, 180, 270, 0, 0, 90, 0]
                    tinc = [0, 0, 90, 0, 0, -90, 0, 0, 90]
                    if treatment[1] < 10:
                        ipos_code = int(treatment[1]) - 1
                    else:
                        ipos_code = int(treatment[1] / 10) - 1

                    # (2) using the magnetization
                    if meas_line["dec_s"] != "":
                        DEC = float(meas_line["dec_s"])
                        INC = float(meas_line["inc_s"])
                    elif meas_line["dec_g"] != "":
                        DEC = float(meas_line["dec_g"])
                        INC = float(meas_line["inc_g"])
                    elif meas_line["dec_t"] != "":
                        DEC = float(meas_line["dec_t"])
                        INC = float(meas_line["inc_t"])
                    if DEC < 0 and DEC > -359:
                        DEC = 360.+DEC

                    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
                    # check it
                    if treatment[1] != 7 and treatment[1] != 70:
                        if ipos_guess != ipos_code:
                            print("-W- WARNING: check specimen %s step %s, anistropy measurements, coding does not match the direction of the lab field" % (
                                specimen, meas_line['treatment']))
                    MeasRec["treat_dc_field_phi"] = '%7.1f' % (tdec[ipos])
                    MeasRec["treat_dc_field_theta"] = '%7.1f' % (tinc[ipos])

            # ---------------------
            # Lab treatment and lab protocoal for cooling rate experiment
            # ---------------------

            elif experiment == "CR":

                cooling_times_list
                LP = "LP-CR-TRM"
                MeasRec["treat_temp"] = '%8.3e' % (
                    float(treatment[0])+273.)  # temp in kelvin

                if treatment[1] == 0:
                    LT = "LT-T-Z"
                    MeasRec["treat_dc_field"] = "0"
                    MeasRec["treat_dc_field_phi"] = '0'
                    MeasRec["treat_dc_field_theta"] = '0'
                else:
                    if treatment[1] == 7:  # alteration check as final measurement
                        LT = "LT-PTRM-I"
                    else:
                        LT = "LT-T-I"
                    MeasRec["treat_dc_field"] = '%8.3e' % (labfield)
                    MeasRec["treat_dc_field_phi"] = '%7.1f' % (
                        labfield_phi)  # labfield phi
                    MeasRec["treat_dc_field_theta"] = '%7.1f' % (
                        labfield_theta)  # labfield theta

                    indx = int(treatment[1])-1
                    # alteration check matjed as 0.7 in the measurement file
                    if indx == 6:
                        cooling_time = cooling_times_list[-1]
                    else:
                        cooling_time = cooling_times_list[indx]
                    MeasRec["measurement_description"] = "cooling_rate" + \
                        ":"+cooling_time+":"+"K/min"

            # ---------------------
            # Lab treatment and lab protocoal for NLT experiment
            # ---------------------

            elif 'NLT' in experiment:
                print(
                    "Dont support yet NLT rate experiment file. Contact rshaar@ucsd.edu")

            # ---------------------
            # method_codes for this measurement only
            # LP will be fixed after all measurement lines are read
            # ---------------------

            MeasRec["method_codes"] = LT+":"+LP

            # --------------------
            # deal with specimen orientation and different coordinate system
            # --------------------

            found_s, found_geo, found_tilt = False, False, False
            if "dec_s" in list(meas_line.keys()) and "inc_s" in list(meas_line.keys()):
                if meas_line["dec_s"] != "" and meas_line["inc_s"] != "":
                    found_s = True
                MeasRec["dir_dec"] = meas_line["dec_s"]
                MeasRec["dir_inc"] = meas_line["inc_s"]
            if "dec_g" in list(meas_line.keys()) and "inc_g" in list(meas_line.keys()):
                if meas_line["dec_g"] != "" and meas_line["inc_g"] != "":
                    found_geo = True
            if "dec_t" in list(meas_line.keys()) and "inc_t" in list(meas_line.keys()):
                if meas_line["dec_t"] != "" and meas_line["inc_t"] != "":
                    found_tilt = True

            # -----------------------------
            # specimen coordinates: no
            # geographic coordinates: yes
            # -----------------------------

            if found_geo and not found_s:
                MeasRec["dir_dec"] = meas_line["dec_g"]
                MeasRec["dir_inc"] = meas_line["inc_g"]
                azimuth = "0"
                dip = "0"

            # -----------------------------
            # specimen coordinates: no
            # geographic coordinates: no
            # -----------------------------
            if not found_geo and not found_s:
                print("-E- ERROR: sample %s does not have dec_s/inc_s or dec_g/inc_g. Ignore specimen %s " %
                      (sample, specimen))
                break

            # -----------------------------
            # specimen coordinates: yes
            # geographic coordinates: yes
            #
            # commant: Ron, this need to be tested !!
            # -----------------------------
            if found_geo and found_s:
                cdec, cinc = float(meas_line["dec_s"]), float(
                    meas_line["inc_s"])
                gdec, ginc = float(meas_line["dec_g"]), float(
                    meas_line["inc_g"])
                az, pl = pmag.get_azpl(cdec, cinc, gdec, ginc)
                azimuth = "%.1f" % az
                dip = "%.1f" % pl

            # -----------------------------
            # specimen coordinates: yes
            # geographic coordinates: no
            # -----------------------------
            if not found_geo and found_s and "Demag" in experiment:
                print("-W- WARNING: missing dip or azimuth for sample %s" % sample)

            # -----------------------------
            # tilt-corrected coordinates: yes
            # geographic coordinates: no
            # -----------------------------
            if found_tilt and not found_geo:
                print(
                    "-E- ERROR: missing geographic data for sample %s. Ignoring tilt-corrected data " % sample)

            # -----------------------------
            # tilt-corrected coordinates: yes
            # geographic coordinates: yes
            # -----------------------------
            if found_tilt and found_geo:
                dec_geo, inc_geo = float(
                    meas_line["dec_g"]), float(meas_line["inc_g"])
                dec_tilt, inc_tilt = float(
                    meas_line["dec_t"]), float(meas_line["inc_t"])
                if dec_geo == dec_tilt and inc_geo == inc_tilt:
                    DipDir, Dip = 0., 0.
                else:
                    DipDir, Dip = pmag.get_tilt(
                        dec_geo, inc_geo, dec_tilt, inc_tilt)

            # -----------------------------
            # samples method codes
            # geographic coordinates: no
            # -----------------------------
            if found_tilt or found_geo:
                sample_method_codes = "SO-NO"

            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['citations'] = "This study"
                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['azimuth'] = azimuth
                SampRec['dip'] = dip
                SampRec['bed_dip_direction'] = DipDir
                SampRec['bed_dip'] = Dip
                SampRec['method_codes'] = sample_method_codes
                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['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['citations'] = "This study"
                LocRec['lat_n'] = lat
                LocRec['lon_e'] = lon
                LocRec['lat_s'] = lat
                LocRec['lon_w'] = lon
                LocRecs.append(LocRec)

            MeasRecs_this_specimen.append(MeasRec)
            measurement_running_number += 1
            # -------

        # -------
        # after reading all the measurements lines for this specimen
        # 1) add experiments
        # 2) fix method_codes with the correct lab protocol
        # -------
        LP_this_specimen = []
        for MeasRec in MeasRecs_this_specimen:
            method_codes = MeasRec["method_codes"].split(":")
            for code in method_codes:
                if "LP" in code and code not in LP_this_specimen:
                    LP_this_specimen.append(code)
        # check IZ/ZI/IZZI
        if "LP-PI-ZI" in LP_this_specimen and "LP-PI-IZ" in LP_this_specimen:
            LP_this_specimen.remove("LP-PI-ZI")
            LP_this_specimen.remove("LP-PI-IZ")
            LP_this_specimen.append("LP-PI-BT-IZZI")

        # add the right LP codes and fix experiment name
        for MeasRec in MeasRecs_this_specimen:
            # MeasRec["experiment"]=MeasRec["specimen"]+":"+":".join(LP_this_specimen)
            method_codes = MeasRec["method_codes"].split(":")
            LT = ""
            for code in method_codes:
                if code[:3] == "LT-":
                    LT = code
                    break
            MeasRec["method_codes"] = LT+":"+":".join(LP_this_specimen)
            MeasRec["method_codes"] = MeasRec["method_codes"].strip(":")
            MeasRecs.append(MeasRec)

    # --
    # write tables to file
    # --

    con = cb.Contribution(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)
    con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)

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

    return True, meas_file