docs: def atrm_magic(meas_file, dir_path=".", input_dir_path="",
                 input_spec_file='specimens.txt', output_spec_file='specimens.txt',
                 data_model_num=3):
      """
      Converts ATRM  data to best-fit tensor (6 elements plus sigma)
  
      Parameters
      ----------
      meas_file : str
          input measurement file
      dir_path : str
          output directory, default "."
      input_dir_path : str
          input file directory IF different from dir_path, default ""
      input_spec_file : str
          input specimen file name, default "specimens.txt"
      output_spec_file : str
          output specimen file name, default "specimens.txt"
      data_model_num : number
          MagIC data model [2, 3], default 3
  
      Returns
      ---------
      Tuple : (True or False indicating if conversion was sucessful, output file name written)
  
      """
      # fix up file names
      input_dir_path, dir_path = pmag.fix_directories(input_dir_path, dir_path)
      meas_file = pmag.resolve_file_name(meas_file, input_dir_path)
      rmag_anis = os.path.join(dir_path, 'rmag_anisotropy.txt')
      rmag_res = os.path.join(dir_path, 'rmag_results.txt')
      input_spec_file = pmag.resolve_file_name(input_spec_file, input_dir_path)
      output_spec_file = pmag.resolve_file_name(output_spec_file, dir_path)
  
      # read in data
      if data_model_num == 3:
          meas_data = []
          meas_data3, file_type = pmag.magic_read(meas_file)
          if file_type != 'measurements':
              print(
                  "-E- {} is not a valid measurements file, {}".format(meas_file, file_type))
              return False
          # convert meas_data to 2.5
          for rec in meas_data3:
              meas_map = map_magic.meas_magic3_2_magic2_map
              meas_data.append(map_magic.mapping(rec, meas_map))
          old_spec_recs, file_type = pmag.magic_read(input_spec_file)
          if file_type != 'specimens':
              print("-W- {} is not a valid specimens file ".format(input_spec_file))
              old_spec_recs = []
          spec_recs = []
          for rec in old_spec_recs:
              spec_map = map_magic.spec_magic3_2_magic2_map
              spec_recs.append(map_magic.mapping(rec, spec_map))
  
      else:
          meas_data, file_type = pmag.magic_read(meas_file)
          if file_type != 'magic_measurements':
              print("-E- {} is is not a valid magic_measurements file ".format(file_type))
              return False, "{} is not a valid magic_measurements file, {}".format(meas_file, file_type)
  
      meas_data = pmag.get_dictitem(
          meas_data, 'magic_method_codes', 'LP-AN-TRM', 'has')
      if not len(meas_data):
          print("-E- No measurement records found with code LP-AN-TRM")
          return False, "No measurement records found with code LP-AN-TRM"
      #
      #
      # get sorted list of unique specimen names
      ssort = []
      for rec in meas_data:
          spec = rec["er_specimen_name"]
          if spec not in ssort:
              ssort.append(spec)
      sids = sorted(ssort)
      #
      #
      # work on each specimen
      #
      specimen, npos = 0, 6
      RmagSpecRecs, RmagResRecs = [], []
      SpecRecs, SpecRecs3 = [], []
      while specimen < len(sids):
          nmeas = 0
          s = sids[specimen]
          RmagSpecRec = {}
          RmagResRec = {}
          # get old specrec here if applicable
          if data_model_num == 3:
              if spec_recs:
                  try:
                      RmagResRec = pmag.get_dictitem(
                          spec_recs, 'er_specimen_name', s, 'T')[0]
                      RmagSpecRec = pmag.get_dictitem(
                          spec_recs, 'er_specimen_name', s, 'T')[0]
                  except IndexError:
                      pass
  
          BX, X = [], []
          method_codes = []
          Spec0 = ""
      #
      # find the data from the meas_data file for this sample
          # and get dec, inc, int and convert to x,y,z
          #
          # fish out data for this specimen name
          data = pmag.get_dictitem(meas_data, 'er_specimen_name', s, 'T')
          if len(data) > 5:
              RmagSpecRec["rmag_anisotropy_name"] = data[0]["er_specimen_name"]
              RmagSpecRec["er_location_name"] = data[0].get(
                  "er_location_name", "")
              RmagSpecRec["er_specimen_name"] = data[0]["er_specimen_name"]
              if not "er_sample_name" in RmagSpecRec:
                  RmagSpecRec["er_sample_name"] = data[0].get(
                      "er_sample_name", "")
              RmagSpecRec["er_site_name"] = data[0].get("er_site_name", "")
              RmagSpecRec["magic_experiment_names"] = RmagSpecRec["rmag_anisotropy_name"] + ":ATRM"
              RmagSpecRec["er_citation_names"] = "This study"
              RmagResRec["rmag_result_name"] = data[0]["er_specimen_name"] + ":ATRM"
              RmagResRec["er_location_names"] = data[0].get(
                  "er_location_names", "")
              RmagResRec["er_specimen_names"] = data[0]["er_specimen_name"]
              if data_model_num == 2:
                  RmagResRec["er_sample_names"] = data[0].get(
                      "er_sample_name", "")
              RmagResRec["er_site_names"] = data[0].get("er_site_name", "")
              RmagResRec["magic_experiment_names"] = RmagSpecRec["rmag_anisotropy_name"] + ":ATRM"
              RmagResRec["er_citation_names"] = "This study"
              RmagSpecRec["anisotropy_type"] = "ATRM"
              if "magic_instrument_codes" in list(data[0].keys()):
                  RmagSpecRec["magic_instrument_codes"] = data[0]["magic_instrument_codes"]
              else:
                  RmagSpecRec["magic_instrument_codes"] = ""
                  RmagSpecRec["anisotropy_description"] = "Hext statistics adapted to ATRM"
              for rec in data:
                  meths = rec['magic_method_codes'].strip().split(':')
                  Dir = []
                  Dir.append(float(rec["measurement_dec"]))
                  Dir.append(float(rec["measurement_inc"]))
                  Dir.append(float(rec["measurement_magn_moment"]))
                  if "LT-T-Z" in meths:
                      BX.append(pmag.dir2cart(Dir))  # append baseline steps
                  elif "LT-T-I" in meths:
                      X.append(pmag.dir2cart(Dir))
                      nmeas += 1
      #
          if len(BX) == 1:
              for i in range(len(X) - 1):
                  BX.append(BX[0])  # assume first 0 field step as baseline
          elif len(BX) == 0:  # assume baseline is zero
              for i in range(len(X)):
                  BX.append([0., 0., 0.])  # assume baseline of 0
          elif len(BX) != len(X):  # if BX isn't just one measurement or one in between every infield step, just assume it is zero
              print('something odd about the baselines - just assuming zero')
              for i in range(len(X)):
                  BX.append([0., 0., 0.])  # assume baseline of 0
          if nmeas < 6:  # must have at least 6 measurements right now -
              print('skipping specimen ', s, ' too few measurements')
              specimen += 1
          else:
              # B matrix made from design matrix for positions
              B, H, tmpH = pmag.designATRM(npos)
          #
          # subtract optional baseline and put in a work array
          #
              work = np.zeros((nmeas, 3), 'f')
              for i in range(nmeas):
                  for j in range(3):
                      # subtract baseline, if available
                      work[i][j] = X[i][j] - BX[i][j]
          #
          # calculate tensor elements
          # first put ARM components in w vector
          #
              w = np.zeros((npos * 3), 'f')
              index = 0
              for i in range(npos):
                  for j in range(3):
                      w[index] = work[i][j]
                      index += 1
              s = np.zeros((6), 'f')  # initialize the s matrix
              for i in range(6):
                  for j in range(len(w)):
                      s[i] += B[i][j] * w[j]
              trace = s[0] + s[1] + s[2]   # normalize by the trace
              for i in range(6):
                  s[i] = s[i] / trace
              a = pmag.s2a(s)
  
          # ------------------------------------------------------------
          #  Calculating dels is different than in the Kappabridge
          #  routine. Use trace normalized tensor (a) and the applied
          #  unit field directions (tmpH) to generate model X,Y,Z
          #  components. Then compare these with the measured values.
          # ------------------------------------------------------------
              S = 0.
              comp = np.zeros((npos * 3), 'f')
              for i in range(npos):
                  for j in range(3):
                      index = i * 3 + j
                      compare = a[j][0] * tmpH[i][0] + a[j][1] * \
                          tmpH[i][1] + a[j][2] * tmpH[i][2]
                      comp[index] = compare
              for i in range(npos * 3):
                  d = (w[i] / trace) - comp[i]  # del values
                  S += d * d
              nf = float(npos * 3. - 6.)  # number of degrees of freedom
              if S > 0:
                  sigma = np.sqrt(S / nf)
              else:
                  sigma = 0
              hpars = pmag.dohext(nf, sigma, s)
          #
          # prepare for output
          #
              RmagSpecRec["anisotropy_s1"] = '%8.6f' % (s[0])
              RmagSpecRec["anisotropy_s2"] = '%8.6f' % (s[1])
              RmagSpecRec["anisotropy_s3"] = '%8.6f' % (s[2])
              RmagSpecRec["anisotropy_s4"] = '%8.6f' % (s[3])
              RmagSpecRec["anisotropy_s5"] = '%8.6f' % (s[4])
              RmagSpecRec["anisotropy_s6"] = '%8.6f' % (s[5])
              RmagSpecRec["anisotropy_mean"] = '%8.3e' % (trace / 3)
              RmagSpecRec["anisotropy_sigma"] = '%8.6f' % (sigma)
              RmagSpecRec["anisotropy_unit"] = "Am^2"
              RmagSpecRec["anisotropy_n"] = '%i' % (npos)
              RmagSpecRec["anisotropy_tilt_correction"] = '-1'
              # used by thellier_gui - must be taken out for uploading
              RmagSpecRec["anisotropy_F"] = '%7.1f ' % (hpars["F"])
              # used by thellier_gui - must be taken out for uploading
              RmagSpecRec["anisotropy_F_crit"] = hpars["F_crit"]
              RmagResRec["anisotropy_t1"] = '%8.6f ' % (hpars["t1"])
              RmagResRec["anisotropy_t2"] = '%8.6f ' % (hpars["t2"])
              RmagResRec["anisotropy_t3"] = '%8.6f ' % (hpars["t3"])
              RmagResRec["anisotropy_v1_dec"] = '%7.1f ' % (hpars["v1_dec"])
              RmagResRec["anisotropy_v2_dec"] = '%7.1f ' % (hpars["v2_dec"])
              RmagResRec["anisotropy_v3_dec"] = '%7.1f ' % (hpars["v3_dec"])
              RmagResRec["anisotropy_v1_inc"] = '%7.1f ' % (hpars["v1_inc"])
              RmagResRec["anisotropy_v2_inc"] = '%7.1f ' % (hpars["v2_inc"])
              RmagResRec["anisotropy_v3_inc"] = '%7.1f ' % (hpars["v3_inc"])
              RmagResRec["anisotropy_ftest"] = '%7.1f ' % (hpars["F"])
              RmagResRec["anisotropy_ftest12"] = '%7.1f ' % (hpars["F12"])
              RmagResRec["anisotropy_ftest23"] = '%7.1f ' % (hpars["F23"])
              RmagResRec["result_description"] = 'Critical F: ' + \
                  hpars["F_crit"] + ';Critical F12/F13: ' + hpars["F12_crit"]
              if hpars["e12"] > hpars["e13"]:
                  RmagResRec["anisotropy_v1_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v1_zeta_dec"] = '%7.1f ' % (
                      hpars['v2_dec'])
                  RmagResRec["anisotropy_v1_zeta_inc"] = '%7.1f ' % (
                      hpars['v2_inc'])
                  RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
                  RmagResRec["anisotropy_v1_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v1_eta_dec"] = '%7.1f ' % (
                      hpars['v3_dec'])
                  RmagResRec["anisotropy_v1_eta_inc"] = '%7.1f ' % (
                      hpars['v3_inc'])
                  RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
              else:
                  RmagResRec["anisotropy_v1_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v1_zeta_dec"] = '%7.1f ' % (
                      hpars['v3_dec'])
                  RmagResRec["anisotropy_v1_zeta_inc"] = '%7.1f ' % (
                      hpars['v3_inc'])
                  RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
                  RmagResRec["anisotropy_v1_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v1_eta_dec"] = '%7.1f ' % (
                      hpars['v2_dec'])
                  RmagResRec["anisotropy_v1_eta_inc"] = '%7.1f ' % (
                      hpars['v2_inc'])
                  RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
              if hpars["e23"] > hpars['e12']:
                  RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e23'])
                  RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                      hpars['v3_dec'])
                  RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                      hpars['v3_inc'])
                  RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e23'])
                  RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                      hpars['v2_dec'])
                  RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                      hpars['v2_inc'])
                  RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
                  RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
              else:
                  RmagResRec["anisotropy_v2_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e12'])
                  RmagResRec["anisotropy_v2_zeta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v2_zeta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
                  RmagResRec["anisotropy_v3_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e23'])
                  RmagResRec["anisotropy_v3_eta_dec"] = '%7.1f ' % (
                      hpars['v2_dec'])
                  RmagResRec["anisotropy_v3_eta_inc"] = '%7.1f ' % (
                      hpars['v2_inc'])
                  RmagResRec["anisotropy_v3_zeta_semi_angle"] = '%7.1f ' % (
                      hpars['e13'])
                  RmagResRec["anisotropy_v3_zeta_dec"] = '%7.1f ' % (
                      hpars['v1_dec'])
                  RmagResRec["anisotropy_v3_zeta_inc"] = '%7.1f ' % (
                      hpars['v1_inc'])
                  RmagResRec["anisotropy_v2_eta_semi_angle"] = '%7.1f ' % (
                      hpars['e23'])
                  RmagResRec["anisotropy_v2_eta_dec"] = '%7.1f ' % (
                      hpars['v3_dec'])
                  RmagResRec["anisotropy_v2_eta_inc"] = '%7.1f ' % (
                      hpars['v3_inc'])
              RmagResRec["tilt_correction"] = '-1'
              RmagResRec["anisotropy_type"] = 'ATRM'
              RmagResRec["magic_method_codes"] = 'LP-AN-TRM:AE-H'
              RmagSpecRec["magic_method_codes"] = 'LP-AN-TRM:AE-H'
              RmagResRec["magic_software_packages"] = pmag.get_version()
              RmagSpecRec["magic_software_packages"] = pmag.get_version()
              RmagSpecRecs.append(RmagSpecRec)
              RmagResRecs.append(RmagResRec)
              specimen += 1
          if data_model_num == 3:
              SpecRec = RmagResRec.copy()
              SpecRec.update(RmagSpecRec)
              SpecRecs.append(SpecRec)
  
      # finished iterating through specimens,
      # now we need to write out the data to files
      if data_model_num == 3:
          # translate records
          for rec in SpecRecs:
              rec3 = map_magic.convert_aniso('magic3', rec)
              SpecRecs3.append(rec3)
  
          # write output to 3.0 specimens file
          pmag.magic_write(output_spec_file, SpecRecs3, 'specimens')
          print("specimen data stored in {}".format(output_spec_file))
          return True, output_spec_file
  
      else:
          # write output to 2.5 rmag_ files
          pmag.magic_write(rmag_anis, RmagSpecRecs, 'rmag_anisotropy')
          print("specimen tensor elements stored in ", rmag_anis)
          pmag.magic_write(rmag_res, RmagResRecs, 'rmag_results')
          print("specimen statistics and eigenparameters stored in ", rmag_res)
          return True, rmag_anis