docs: def on_menu_make_MagIC_results_tables(self, event):
          """
           Creates or Updates Specimens or Pmag Specimens MagIC table,
           overwrites .redo file for safety, and starts User dialog to
           generate other MagIC tables for later contribution to the MagIC
           database. The following describes the steps used in the 2.5 data
           format to do this:
  
           1. read pmag_specimens.txt, pmag_samples.txt, pmag_sites.txt, and
              sort out lines with LP-DIR in magic_codes
           2. saves a clean pmag_*.txt files without LP-DIR stuff as
              pmag_*.txt.tmp
           3. write a new file pmag_specimens.txt
           4. merge pmag_specimens.txt and pmag_specimens.txt.tmp using
              combine_magic.py
           5. delete pmag_specimens.txt.tmp
           6 (optional) extracting new pag_*.txt files (except
              pmag_specimens.txt) using specimens_results_magic.py
           7: if #6: merge pmag_*.txt and pmag_*.txt.tmp using combine_magic.py
              if not #6: save pmag_*.txt.tmp as pmag_*.txt
          """
  
          # ---------------------------------------
          # save pmag_*.txt.tmp without directional data
          # ---------------------------------------
          self.on_menu_save_interpretation(None)
  
          # ---------------------------------------
          # dialog box to choose coordinate systems for pmag_specimens.txt
          # ---------------------------------------
          dia = demag_dialogs.magic_pmag_specimens_table_dialog(None)
          CoorTypes = []
          if self.test_mode:
              CoorTypes = ['DA-DIR']
          elif dia.ShowModal() == wx.ID_OK:  # Until the user clicks OK, show the message
              if dia.cb_spec_coor.GetValue() == True:
                  CoorTypes.append('DA-DIR')
              if dia.cb_geo_coor.GetValue() == True:
                  CoorTypes.append('DA-DIR-GEO')
              if dia.cb_tilt_coor.GetValue() == True:
                  CoorTypes.append('DA-DIR-TILT')
          else:
              self.user_warning("MagIC tables not saved")
              print("MagIC tables not saved")
              return
          # ------------------------------
  
          self.PmagRecsOld = {}
          if self.data_model == 3.0:
              FILES = []
          else:
              FILES = ['pmag_specimens.txt']
          for FILE in FILES:
              self.PmagRecsOld[FILE] = []
              meas_data = []
              try:
                  meas_data, file_type = pmag.magic_read(
                      os.path.join(self.WD, FILE))
                  print(("-I- Read old magic file  %s\n" %
                         os.path.join(self.WD, FILE)))
                  # if FILE !='pmag_specimens.txt':
                  os.remove(os.path.join(self.WD, FILE))
                  print(("-I- Delete old magic file  %s\n" %
                         os.path.join(self.WD, FILE)))
  
              except (OSError, IOError) as e:
                  continue
  
              for rec in meas_data:
                  if "magic_method_codes" in list(rec.keys()):
                      if "LP-DIR" not in rec['magic_method_codes'] and "DE-" not in rec['magic_method_codes']:
                          self.PmagRecsOld[FILE].append(rec)
  
          # ---------------------------------------
          # write a new pmag_specimens.txt
          # ---------------------------------------
  
          specimens_list = list(self.pmag_results_data['specimens'].keys())
          specimens_list.sort()
          PmagSpecs = []
          for specimen in specimens_list:
              for dirtype in CoorTypes:
                  i = 0
                  for fit in self.pmag_results_data['specimens'][specimen]:
                      mpars = fit.get(dirtype)
                      if not mpars:
                          mpars = self.get_PCA_parameters(
                              specimen, fit, fit.tmin, fit.tmax, dirtype, fit.PCA_type)
                          if not mpars or 'specimen_dec' not in list(mpars.keys()):
                              self.user_warning("Could not calculate interpretation for specimen %s and fit %s in coordinate system %s while exporting pmag tables, skipping" % (
                                  specimen, fit.name, dirtype))
                              continue
  
                      PmagSpecRec = {}
                      PmagSpecRec["magic_software_packages"] = pmag.get_version(
                      ) + ': demag_gui'
                      PmagSpecRec["er_specimen_name"] = specimen
                      PmagSpecRec["er_sample_name"] = self.Data_hierarchy['sample_of_specimen'][specimen]
                      PmagSpecRec["er_site_name"] = self.Data_hierarchy['site_of_specimen'][specimen]
                      PmagSpecRec["er_location_name"] = self.Data_hierarchy['location_of_specimen'][specimen]
                      if specimen in list(self.Data_hierarchy['expedition_name_of_specimen'].keys()):
                          PmagSpecRec["er_expedition_name"] = self.Data_hierarchy['expedition_name_of_specimen'][specimen]
                      PmagSpecRec["er_citation_names"] = "This study"
                      if "magic_experiment_name" in self.Data[specimen]:
                          PmagSpecRec["magic_experiment_names"] = self.Data[specimen]["magic_experiment_name"]
                      if 'magic_instrument_codes' in list(self.Data[specimen].keys()):
                          PmagSpecRec["magic_instrument_codes"] = self.Data[specimen]['magic_instrument_codes']
                      PmagSpecRec['specimen_correction'] = 'u'
                      PmagSpecRec['specimen_direction_type'] = mpars["specimen_direction_type"]
                      PmagSpecRec['specimen_dec'] = "%.1f" % mpars["specimen_dec"]
                      PmagSpecRec['specimen_inc'] = "%.1f" % mpars["specimen_inc"]
                      PmagSpecRec['specimen_flag'] = "g"
                      if fit in self.bad_fits:
                          PmagSpecRec['specimen_flag'] = "b"
  
                      if "C" in fit.tmin or "C" in fit.tmax:
                          PmagSpecRec['measurement_step_unit'] = "K"
                      else:
                          PmagSpecRec['measurement_step_unit'] = "T"
  
                      if "C" in fit.tmin:
                          PmagSpecRec['measurement_step_min'] = "%.0f" % (
                              mpars["measurement_step_min"]+273.)
                      elif "mT" in fit.tmin:
                          PmagSpecRec['measurement_step_min'] = "%8.3e" % (
                              mpars["measurement_step_min"]*1e-3)
                      else:
                          if PmagSpecRec['measurement_step_unit'] == "K":
                              PmagSpecRec['measurement_step_min'] = "%.0f" % (
                                  mpars["measurement_step_min"]+273.)
                          else:
                              PmagSpecRec['measurement_step_min'] = "%8.3e" % (
                                  mpars["measurement_step_min"]*1e-3)
  
                      if "C" in fit.tmax:
                          PmagSpecRec['measurement_step_max'] = "%.0f" % (
                              mpars["measurement_step_max"]+273.)
                      elif "mT" in fit.tmax:
                          PmagSpecRec['measurement_step_max'] = "%8.3e" % (
                              mpars["measurement_step_max"]*1e-3)
                      else:
                          if PmagSpecRec['measurement_step_unit'] == "K":
                              PmagSpecRec['measurement_step_min'] = "%.0f" % (
                                  mpars["measurement_step_min"]+273.)
                          else:
                              PmagSpecRec['measurement_step_min'] = "%8.3e" % (
                                  mpars["measurement_step_min"]*1e-3)
  
                      PmagSpecRec['specimen_n'] = "%.0f" % mpars["specimen_n"]
                      calculation_type = mpars['calculation_type']
                      PmagSpecRec["magic_method_codes"] = self.Data[specimen]['magic_method_codes'] + \
                          ":"+calculation_type+":"+dirtype
                      PmagSpecRec["specimen_comp_n"] = str(
                          len(self.pmag_results_data["specimens"][specimen]))
                      PmagSpecRec["specimen_comp_name"] = fit.name
                      if fit in self.bad_fits:
                          PmagSpecRec["specimen_flag"] = "b"
                      else:
                          PmagSpecRec["specimen_flag"] = "g"
                      if calculation_type in ["DE-BFL", "DE-BFL-A", "DE-BFL-O"]:
                          PmagSpecRec['specimen_direction_type'] = 'l'
                          PmagSpecRec['specimen_mad'] = "%.1f" % float(
                              mpars["specimen_mad"])
                          PmagSpecRec['specimen_dang'] = "%.1f" % float(
                              mpars['specimen_dang'])
                          PmagSpecRec['specimen_alpha95'] = ""
                      elif calculation_type in ["DE-BFP"]:
                          PmagSpecRec['specimen_direction_type'] = 'p'
                          PmagSpecRec['specimen_mad'] = "%.1f" % float(
                              mpars['specimen_mad'])
                          PmagSpecRec['specimen_dang'] = ""
                          PmagSpecRec['specimen_alpha95'] = ""
                          if self.data_model == 3.0:
                              if 'bfv_dec' not in list(mpars.keys()) or \
                                 'bfv_inc' not in list(mpars.keys()):
                                  self.calculate_best_fit_vectors(
                                      high_level_type="sites", high_level_name=PmagSpecRec["er_site_name"], dirtype=dirtype)
                                  mpars = fit.get(dirtype)
                              try:
                                  PmagSpecRec['dir_bfv_dec'] = "%.1f" % mpars['bfv_dec']
                                  PmagSpecRec['dir_bfv_inc'] = "%.1f" % mpars['bfv_inc']
                              except KeyError:
                                  print("Error calculating BFV during export of interpretations for %s, %s, %s" % (
                                      fit.name, specimen, dirtype))
                      elif calculation_type in ["DE-FM"]:
                          PmagSpecRec['specimen_direction_type'] = 'l'
                          PmagSpecRec['specimen_mad'] = ""
                          PmagSpecRec['specimen_dang'] = ""
                          PmagSpecRec['specimen_alpha95'] = "%.1f" % float(
                              mpars['specimen_alpha95'])
                      if dirtype == 'DA-DIR-TILT':
                          PmagSpecRec['specimen_tilt_correction'] = "100"
                      elif dirtype == 'DA-DIR-GEO':
                          PmagSpecRec['specimen_tilt_correction'] = "0"
                      else:
                          PmagSpecRec['specimen_tilt_correction'] = "-1"
                      PmagSpecs.append(PmagSpecRec)
                      i += 1
  
          # add the 'old' lines with no "LP-DIR" in
          if 'pmag_specimens.txt' in list(self.PmagRecsOld.keys()):
              for rec in self.PmagRecsOld['pmag_specimens.txt']:
                  PmagSpecs.append(rec)
          PmagSpecs_fixed = self.merge_pmag_recs(PmagSpecs)
  
          if len(PmagSpecs_fixed) == 0:
              self.user_warning(
                  "No data to save to MagIC tables please create some interpretations before saving")
              print("No data to save, MagIC tables not written")
              return
  
          if self.data_model == 3.0:
  
              # translate demag_gui output to 3.0 DataFrame
              ndf2_5 = DataFrame(PmagSpecs_fixed)
              if 'specimen_direction_type' in ndf2_5.columns:
                  # doesn't exist in new model
                  del ndf2_5['specimen_direction_type']
              ndf3_0 = ndf2_5.rename(columns=map_magic.spec_magic2_2_magic3_map)
              if 'specimen' in ndf3_0.columns:
                  ndf3_0 = ndf3_0.set_index("specimen")
                  # replace the removed specimen column
                  ndf3_0['specimen'] = ndf3_0.index
              # prefer keeping analyst_names in txt
              if 'analyst_names' in ndf3_0:
                  del ndf3_0['analyst_names']
  
              # get current 3.0 DataFrame from contribution object
              if 'specimens' not in self.con.tables:
                  cols = ndf3_0.columns
                  self.con.add_empty_magic_table('specimens', col_names=cols)
              spmdf = self.con.tables['specimens']
              # remove translation collisions or deprecated terms
              for dc in ["dir_comp_name", "magic_method_codes"]:
                  if dc in spmdf.df.columns:
                      del spmdf.df[dc]
  
              # merge previous df with new interpretations DataFrame
              # (do not include non-directional data in the merge or else it
              # will be overwritten)
  
              # fix index names
              spmdf.df.index.name = "specimen_name"
              ndf3_0.index.name = "specimen_name"
              # pull out directional/non-directional data
              if 'method_codes' not in spmdf.df:
                  spmdf.df['method_codes'] = ''
              directional = spmdf.df['method_codes'].str.contains('LP-DIR').astype(bool)
              non_directional_df = spmdf.df[~directional]
              spmdf.df = spmdf.df[directional]
              # merge new interpretations with old specimen information
              directional_df = spmdf.merge_dfs(ndf3_0)
              # add any missing columns to non_directional_df
              for col in directional_df.columns:
                  if col not in non_directional_df.columns:
                      non_directional_df[col] = ""
              # make sure columns are ordered the same so that we can concatenate
              non_directional_df.sort_index(axis='columns', inplace=True)
              directional_df.sort_index(axis='columns', inplace=True)
              # put directional/non-directional data back together
              merged = pd.concat([non_directional_df, directional_df])
              merged.sort_index(inplace=True)
              spmdf.df = merged
  
              # write to disk
              spmdf.write_magic_file(dir_path=self.WD)
  
              TEXT = "specimens interpretations are saved in specimens.txt.\nPress OK to save to samples/sites/locations/ages tables."
              self.dlg = wx.MessageDialog(
                  self, caption="Other Tables", message=TEXT, style=wx.OK | wx.CANCEL)
              result = self.show_dlg(self.dlg)
              if result == wx.ID_OK:
                  self.dlg.Destroy()
              else:
                  self.dlg.Destroy()
                  return
  
          else:
              pmag.magic_write(os.path.join(
                  self.WD, "pmag_specimens.txt"), PmagSpecs_fixed, 'pmag_specimens')
              print(("specimen data stored in %s\n" %
                     os.path.join(self.WD, "pmag_specimens.txt")))
  
              TEXT = "specimens interpretations are saved in pmag_specimens.txt.\nPress OK for pmag_samples/pmag_sites/pmag_results tables."
              dlg = wx.MessageDialog(
                  self, caption="Other Pmag Tables", message=TEXT, style=wx.OK | wx.CANCEL)
              result = self.show_dlg(dlg)
              if result == wx.ID_OK:
                  dlg.Destroy()
              else:
                  dlg.Destroy()
                  return
  
          # --------------------------------
  
          dia = demag_dialogs.magic_pmag_tables_dialog(
              None, self.WD, self.Data, self.Data_info)
  
          if self.show_dlg(dia) == wx.ID_OK:  # Until the user clicks OK, show the message
              self.On_close_MagIC_dialog(dia)