docs: def utrecht(mag_file, dir_path=".",  input_dir_path="", meas_file="measurements.txt",
              spec_file="specimens.txt", samp_file="samples.txt", site_file="sites.txt",
              loc_file="locations.txt", location="unknown", lat="", lon="", dmy_flag=False,
              noave=False, meas_n_orient=8, meth_code="LP-NO", specnum=1, samp_con='2',
              labfield=0, phi=0, theta=0):
      """
      Converts Utrecht magnetometer data files to MagIC files
  
      Parameters
      ----------
      mag_file : str
          input file name
      dir_path : str
          working directory, default "."
      input_dir_path : str
          input file directory IF different from dir_path, default ""
      spec_file : str
          output specimen file name, default "specimens.txt"
      samp_file: str
          output sample file name, default "samples.txt"
      site_file : str
          output site file name, default "sites.txt"
      loc_file : str
          output location file name, default "locations.txt"
      append : bool
          append output files to existing files instead of overwrite, default False
      location : str
          location name, default "unknown"
      lat : float
          latitude, default ""
      lon : float
          longitude, default ""
      dmy_flag : bool
          default False
      noave : bool
         do not average duplicate measurements, default False (so by default, DO average)
      meas_n_orient : int
          Number of different orientations in measurement (default : 8)
      meth_code : str
          sample method codes, default "LP-NO"
          e.g. [SO-MAG, SO-SUN, SO-SIGHT, ...]
      specnum : int
          number of characters to designate a specimen, default 0
      samp_con : str
          sample/site naming convention, default '2', see info below
      labfield : float
          DC_FIELD in microTesla (default : 0)
      phi : float
          DC_PHI in degrees (default : 0)
      theta : float
          DC_THETA in degrees (default : 0)
  
      Returns
      ----------
      type - Tuple : (True or False indicating if conversion was sucessful, meas_file name written)
  
      Info
      ---------
      Sample naming convention:
          [1] XXXXY: where XXXX is an arbitrary length site designation and Y
              is the single character sample designation.  e.g., TG001a is the
              first sample from site TG001.    [default]
          [2] XXXX-YY: YY sample from site XXXX (XXX, YY of arbitary length)
          [3] XXXX.YY: YY sample from site XXXX (XXX, YY of arbitary length)
          [4-Z] XXXX[YYY]:  YYY is sample designation with Z characters from site XXX
          [5] site name = sample name
          [6] site name entered in site_name column in the orient.txt format input file  -- NOT CURRENTLY SUPPORTED
          [7-Z] [XXX]YYY:  XXX is site designation with Z characters from samples  XXXYYY
  
  
      """
      # initialize some stuff
      version_num = pmag.get_version()
      MeasRecs, SpecRecs, SampRecs, SiteRecs, LocRecs = [], [], [], [], []
      input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, dir_path)
      specnum = -int(specnum)
      if "4" in samp_con:
          if "-" not in samp_con:
              print("option [4] must be in form 4-Z where Z is an integer")
              return False, "naming convention option [4] must be in form 4-Z where Z is an integer"
          else:
              site_num = samp_con.split("-")[1]
              samp_con = "4"
      elif "7" in samp_con:
          if "-" not in samp_con:
              print("option [7] must be in form 7-Z where Z is an integer")
              return False, "naming convention option [7] must be in form 7-Z where Z is an integer"
          else:
              site_num = samp_con.split("-")[1]
              samp_con = "7"
      else:
          site_num = 1
      try:
          DC_FIELD = float(labfield)*1e-6
          DC_PHI = float(phi)
          DC_THETA = float(theta)
      except ValueError:
          raise ValueError(
              'problem with your dc parameters. please provide a labfield in microTesla and a phi and theta in degrees.')
  
      # format variables
      if not mag_file:
          return False, 'You must provide a Utrecht format file'
      mag_file = pmag.resolve_file_name(mag_file, input_dir_path)
      # need to add these
      meas_file = pmag.resolve_file_name(meas_file, output_dir_path)
      spec_file = pmag.resolve_file_name(spec_file, output_dir_path)
      samp_file = pmag.resolve_file_name(samp_file, output_dir_path)
      site_file = pmag.resolve_file_name(site_file, output_dir_path)
      loc_file = pmag.resolve_file_name(loc_file, output_dir_path)
  
  
      # parse data
  
      # Open up the Utrecht file and read the header information
      AF_or_T = mag_file.split('.')[-1]
      data = open(mag_file, 'r')
      line = data.readline()
      line_items = line.split(',')
      operator = line_items[0]
      operator = operator.replace("\"", "")
      machine = line_items[1]
      machine = machine.replace("\"", "")
      machine = machine.rstrip('\n')
  #    print("operator=", operator)
  #    print("machine=", machine)
  
      # read in measurement data
      line = data.readline()
      while line != "END" and line != '"END"':
          SpecRec, SampRec, SiteRec, LocRec = {}, {}, {}, {}
          line_items = line.split(',')
          spec_name = line_items[0]
          spec_name = spec_name.replace("\"", "")
  #        print("spec_name=", spec_name)
          free_string = line_items[1]
          free_string = free_string.replace("\"", "")
  #        print("free_string=", free_string)
          dec = line_items[2]
  #        print("dec=", dec)
          inc = line_items[3]
  #        print("inc=", inc)
          volume = float(line_items[4])
          volume = volume * 1e-6  # enter volume in cm^3, convert to m^3
  #        print("volume=", volume)
          bed_plane = line_items[5]
  #        print("bed_plane=", bed_plane)
          bed_dip = line_items[6]
  #        print("bed_dip=", bed_dip)
  
          # Configure et er_ tables
          if specnum == 0:
              sample_name = spec_name
          else:
              sample_name = spec_name[:specnum]
          site = pmag.parse_site(sample_name, samp_con, site_num)
          SpecRec['specimen'] = spec_name
          SpecRec['sample'] = sample_name
          if volume != 0:
              SpecRec['volume'] = volume
          SpecRecs.append(SpecRec)
          if sample_name != "" and sample_name not in [x['sample'] if 'sample' in list(x.keys()) else "" for x in SampRecs]:
              SampRec['sample'] = sample_name
              SampRec['azimuth'] = dec
              SampRec['dip'] = str(float(inc)-90)
              SampRec['bed_dip_direction'] = bed_plane
              SampRec['bed_dip'] = bed_dip
              SampRec['method_codes'] = meth_code
              SampRec['site'] = site
              SampRecs.append(SampRec)
          if site != "" and site not in [x['site'] if 'site' in list(x.keys()) else "" for x in SiteRecs]:
              SiteRec['site'] = site
              SiteRec['location'] = location
              SiteRec['lat'] = lat
              SiteRec['lon'] = lon
              SiteRecs.append(SiteRec)
          if location != "" and location not in [x['location'] if 'location' in list(x.keys()) else "" for x in LocRecs]:
              LocRec['location'] = location
              LocRec['lat_n'] = lat
              LocRec['lon_e'] = lon
              LocRec['lat_s'] = lat
              LocRec['lon_w'] = lon
              LocRecs.append(LocRec)
  
          # measurement data
          line = data.readline()
          line = line.rstrip("\n")
          items = line.split(",")
          while line != '9999':
              step = items[0]
              step = step.split('.')
              step_value = step[0]
              step_type = ""
              if len(step) == 2:
                  step_type = step[1]
              if step_type == '5':
                  step_value = items[0]
              A = float(items[1])
              B = float(items[2])
              C = float(items[3])
  #  convert to MagIC coordinates
              Z = -A
              X = -B
              Y = C
              cart = np.array([X, Y, Z]).transpose()
              direction = pmag.cart2dir(cart).transpose()
              measurement_dec = direction[0]
              measurement_inc = direction[1]
              # the data are in pico-Am^2 - this converts to Am^2
              magn_moment = direction[2] * 1.0e-12
              if volume != 0:
                  # data volume normalized - converted to A/m
                  magn_volume = direction[2] * 1.0e-12 / volume
  #            print("magn_moment=", magn_moment)
  #            print("magn_volume=", magn_volume)
              error = items[4]
              date = items[5]
              date = date.strip('"').replace(' ', '')
              if date.count("-") > 0:
                  date = date.split("-")
              elif date.count("/") > 0:
                  date = date.split("/")
              else:
                  print("date format seperator cannot be identified")
  #            print(date)
              time = items[6]
              time = time.strip('"').replace(' ', '')
              time = time.split(":")
  #            print(time)
              dt = date[0] + ":" + date[1] + ":" + date[2] + \
                  ":" + time[0] + ":" + time[1] + ":" + "0"
              local = pytz.timezone("Europe/Amsterdam")
              try:
                  if dmy_flag:
                      naive = datetime.datetime.strptime(dt, "%d:%m:%Y:%H:%M:%S")
                  else:
                      naive = datetime.datetime.strptime(dt, "%m:%d:%Y:%H:%M:%S")
              except ValueError:
                  try:
                      naive = datetime.datetime.strptime(dt, "%Y:%m:%d:%H:%M:%S")
                  except ValueError:
                      print('-W- Could not parse date format')
                      return False, 'Could not parse date format'
              local_dt = local.localize(naive, is_dst=None)
              utc_dt = local_dt.astimezone(pytz.utc)
              timestamp = utc_dt.strftime("%Y-%m-%dT%H:%M:%S")+"Z"
  #            print(timestamp)
  
              MeasRec = {}
              MeasRec["timestamp"] = timestamp
              MeasRec["analysts"] = operator
              MeasRec["instrument_codes"] = "Utrecht_" + machine
              MeasRec["description"] = "free string = " + free_string
              MeasRec["citations"] = "This study"
              MeasRec['software_packages'] = version_num
              MeasRec["meas_temp"] = '%8.3e' % (273)  # room temp in kelvin
              MeasRec["quality"] = 'g'
              MeasRec["standard"] = 'u'
              # will be overwritten by measurements_methods3
              MeasRec["experiment"] = location + site + spec_name
              MeasRec["treat_step_num"] = location + site + spec_name + items[0]
              MeasRec["specimen"] = spec_name
              # MeasRec["treat_ac_field"] = '0'
              if AF_or_T.lower() == "th":
                  MeasRec["treat_temp"] = '%8.3e' % (
                      float(step_value)+273.)  # temp in kelvin
                  MeasRec['treat_ac_field'] = '0'
                  lab_treat_type = "T"
              else:
                  MeasRec['treat_temp'] = '273'
                  MeasRec['treat_ac_field'] = '%10.3e' % (float(step_value)*1e-3)
                  lab_treat_type = "AF"
              MeasRec['treat_dc_field'] = '0'
              if step_value == '0':
                  meas_type = "LT-NO"
  #            print("step_type=", step_type)
              if step_type == '0' or step_type == '00':
                  meas_type = "LT-%s-Z" % lab_treat_type
              elif step_type == '1' or step_type == '11':
                  meas_type = "LT-%s-I" % lab_treat_type
                  MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
              elif step_type == '2' or step_type == '12':
                  meas_type = "LT-PTRM-I"
                  MeasRec['treat_dc_field'] = '%1.2e' % DC_FIELD
              elif step_type == '3' or step_type == '13':
                  meas_type = "LT-PTRM-Z"
  #            print("meas_type=", meas_type)
              MeasRec['treat_dc_field_phi'] = '%1.2f' % DC_PHI
              MeasRec['treat_dc_field_theta'] = '%1.2f' % DC_THETA
              MeasRec['method_codes'] = meas_type
              MeasRec["magn_moment"] = magn_moment
              if volume != 0:
                  MeasRec["magn_volume"] = magn_volume
              MeasRec["dir_dec"] = measurement_dec
              MeasRec["dir_inc"] = measurement_inc
              MeasRec['dir_csd'] = error
              MeasRec['meas_n_orient'] = meas_n_orient
  #            print(MeasRec)
              MeasRecs.append(MeasRec)
  
              line = data.readline()
              line = line.rstrip("\n")
              items = line.split(",")
          line = data.readline()
          line = line.rstrip("\n")
          items = line.split(",")
  
      data.close()
  
      con = cb.Contribution(output_dir_path, read_tables=[])
  
      con.add_magic_table_from_data(dtype='specimens', data=SpecRecs)
      con.add_magic_table_from_data(dtype='samples', data=SampRecs)
      con.add_magic_table_from_data(dtype='sites', data=SiteRecs)
      con.add_magic_table_from_data(dtype='locations', data=LocRecs)
      # figures out method codes for measuremet data
      MeasOuts = pmag.measurements_methods3(MeasRecs, noave)
      con.add_magic_table_from_data(dtype='measurements', data=MeasOuts)
  
      con.tables['specimens'].write_magic_file(custom_name=spec_file)
      con.tables['samples'].write_magic_file(custom_name=samp_file)
      con.tables['sites'].write_magic_file(custom_name=site_file)
      con.tables['locations'].write_magic_file(custom_name=loc_file)
      con.tables['measurements'].write_magic_file(custom_name=meas_file)
  
      return True, meas_file