docs: def hysteresis_magic(output_dir_path=".", input_dir_path="", spec_file="specimens.txt",
                       meas_file="measurements.txt", fmt="svg",
                       save_plots=True, make_plots=True, pltspec="", n_specs=5, interactive=False):
      """
      Calculate hysteresis parameters and plot hysteresis data.
      Plotting may be called interactively with save_plots==False,
      or be suppressed entirely with make_plots==False.
  
      Parameters
      ----------
      output_dir_path : str, default "."
          Note: if using Windows, all figures will be saved to working directly
                *not* dir_path
      input_dir_path : str
          path for intput file if different from output_dir_path (default is same)
      spec_file : str, default "specimens.txt"
          output file to save hysteresis data
      meas_file : str, default "measurements.txt"
          input measurement file
      fmt : str, default "svg"
          format for figures, [svg, jpg, pdf, png]
      save_plots : bool, default True
          if True, generate and save all requested plots
      make_plots : bool, default True
          if False, skip making plots and just save hysteresis data
          (if False, save_plots will be set to False also)
      pltspec : str, default ""
          specimen name to plot, otherwise will plot all specimens
      n_specs : int
          number of specimens to plot, default 5
          if you want to make all possible plots, specify "all"
      interactive : bool, default False
          interactively plot and display for each specimen
          (this is best used on the command line or in the Python interpreter)
  
  
      Returns
      ---------
      Tuple : (True or False indicating if conversion was sucessful, output file names written)
      """
      # put plots in output_dir_path, unless isServer
      incl_directory = True
      if pmagplotlib.isServer or set_env.IS_WIN:
          incl_directory = False
      # figure out directory/file paths
      input_dir_path, output_dir_path = pmag.fix_directories(input_dir_path, output_dir_path)
      spec_file = pmag.resolve_file_name(spec_file, input_dir_path)
      meas_file = pmag.resolve_file_name(meas_file, input_dir_path)
      # format and initialize variables
      verbose = pmagplotlib.verbose
      version_num = pmag.get_version()
      if not make_plots:
          irm_init, imag_init = -1, -1
          save_plots = False
      if save_plots:
          verbose = False
      if pltspec:
          pass
      if interactive:
          save_plots = False
  
      SpecRecs = []
      #
      #
      meas_data, file_type = pmag.magic_read(meas_file)
      if file_type != 'measurements':
          print('bad file', meas_file)
          return False, []
      #
      # initialize some variables
      # define figure numbers for hyst,deltaM,DdeltaM curves
      HystRecs, RemRecs = [], []
      HDD = {}
      if verbose and make_plots:
          print("Plots may be on top of each other - use mouse to place ")
      if make_plots:
          HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'] = 1, 2, 3
          if make_plots and (not save_plots):
              pmagplotlib.plot_init(HDD['DdeltaM'], 5, 5)
              pmagplotlib.plot_init(HDD['deltaM'], 5, 5)
              pmagplotlib.plot_init(HDD['hyst'], 5, 5)
          imag_init = 0
          irm_init = 0
      else:
          HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'], HDD['irm'], HDD['imag'] = 0, 0, 0, 0, 0
      #
      if spec_file:
          prior_data, file_type = pmag.magic_read(spec_file)
      #
      # get list of unique experiment names and specimen names
      #
      experiment_names, sids = [], []
      hys_data = pmag.get_dictitem(meas_data, 'method_codes', 'LP-HYS', 'has')
      dcd_data = pmag.get_dictitem(
          meas_data, 'method_codes', 'LP-IRM-DCD', 'has')
      imag_data = pmag.get_dictitem(meas_data, 'method_codes', 'LP-IMAG', 'has')
      for rec in hys_data:
          if rec['experiment'] not in experiment_names:
              experiment_names.append(rec['experiment'])
          if rec['specimen'] not in sids:
              sids.append(rec['specimen'])
      #
      k = 0
      # if plotting only one specimen, find it
      if pltspec:
          k = sids.index(pltspec)
      # if plotting only n specimens, remove others from the list
      elif n_specs != "all":
          try:
              sids = sids[:n_specs]
          except:
              pass
      cnt = 0
      while k < len(sids):
          specimen = sids[k]
          if pltspec:
              if specimen != pltspec:
                  k += 1
                  continue
          else:
              for key, value in HDD.items():
                  cnt += 1
                  HDD[key] = cnt
  
              #HDD = {key: value + len(HDD) + k for (key, value) in HDD.items()}
          # initialize a new specimen hysteresis record
          HystRec = {'specimen': specimen, 'experiment': ""}
          if verbose and make_plots:
              print(specimen, k+1, 'out of ', len(sids))
      #
      #
          # B,M for hysteresis, Bdcd,Mdcd for irm-dcd data
          B, M, Bdcd, Mdcd = [], [], [], []
          Bimag, Mimag = [], []  # Bimag,Mimag for initial magnetization curves
          # fish out all the LP-HYS data for this specimen
          spec_data = pmag.get_dictitem(hys_data, 'specimen', specimen, 'T')
          if len(spec_data) > 0:
              meths = spec_data[0]['method_codes'].split(':')
              e = spec_data[0]['experiment']
              HystRec['experiment'] = spec_data[0]['experiment']
              for rec in spec_data:
                  B.append(float(rec['meas_field_dc']))
                  M.append(float(rec['magn_moment']))
          # fish out all the data for this specimen
          spec_data = pmag.get_dictitem(dcd_data, 'specimen', specimen, 'T')
          if len(spec_data) > 0:
              HystRec['experiment'] = HystRec['experiment'] + \
                  ':'+spec_data[0]['experiment']
              irm_exp = spec_data[0]['experiment']
              for rec in spec_data:
                  Bdcd.append(float(rec['treat_dc_field']))
                  Mdcd.append(float(rec['magn_moment']))
          # fish out all the data for this specimen
          spec_data = pmag.get_dictitem(imag_data, 'specimen', specimen, 'T')
          if len(spec_data) > 0:
              imag_exp = spec_data[0]['experiment']
              for rec in spec_data:
                  Bimag.append(float(rec['meas_field_dc']))
                  Mimag.append(float(rec['magn_moment']))
      #
      # now plot the hysteresis curve
      #
          if len(B) > 0:
              hmeths = []
              for meth in meths:
                  hmeths.append(meth)
  
              hpars = pmagplotlib.plot_hdd(HDD, B, M, e)
              if interactive:
                  if not set_env.IS_WIN:
                      pmagplotlib.draw_figs(HDD)
      #
              if make_plots:
                  pmagplotlib.plot_hpars(HDD, hpars, 'bs')
              HystRec['hyst_mr_moment'] = hpars['hysteresis_mr_moment']
              HystRec['hyst_ms_moment'] = hpars['hysteresis_ms_moment']
              HystRec['hyst_bc'] = hpars['hysteresis_bc']
              HystRec['hyst_bcr'] = hpars['hysteresis_bcr']
              HystRec['hyst_xhf'] = hpars['hysteresis_xhf']
              HystRec['experiments'] = e
              HystRec['software_packages'] = version_num
              if hpars["magic_method_codes"] not in hmeths:
                  hmeths.append(hpars["magic_method_codes"])
              methods = ""
              for meth in hmeths:
                  methods = methods+meth.strip()+":"
              HystRec["method_codes"] = methods[:-1]
              HystRec["citations"] = "This study"
      #
          if len(Bdcd) > 0:
              rmeths = []
              for meth in meths:
                  rmeths.append(meth)
              if verbose and make_plots:
                  print('plotting IRM')
              if irm_init == 0:
                  cnt += 1
                  HDD['irm'] = cnt #5 if 'imag' in HDD else 4
                  if make_plots and (not save_plots):
                      pmagplotlib.plot_init(HDD['irm'], 5, 5)
                  irm_init = 1
              rpars = pmagplotlib.plot_irm(HDD['irm'], Bdcd, Mdcd, irm_exp)
              HystRec['rem_mr_moment'] = rpars['remanence_mr_moment']
              HystRec['rem_bcr'] = rpars['remanence_bcr']
              HystRec['experiments'] = specimen+':'+irm_exp
              if rpars["magic_method_codes"] not in meths:
                  meths.append(rpars["magic_method_codes"])
              methods = ""
              for meth in rmeths:
                  methods = methods+meth.strip()+":"
              HystRec["method_codes"] = HystRec['method_codes']+':'+methods[:-1]
              HystRec["citations"] = "This study"
          else:
              if irm_init:
                  pmagplotlib.clearFIG(HDD['irm'])
          if len(Bimag) > 0:
              if verbose and make_plots:
                  print('plotting initial magnetization curve')
  # first normalize by Ms
              Mnorm = []
              for m in Mimag:
                  Mnorm.append(m / float(hpars['hysteresis_ms_moment']))
              if imag_init == 0:
                  HDD['imag'] = 4
                  if make_plots and (not save_plots):
                      pmagplotlib.plot_init(HDD['imag'], 5, 5)
                  imag_init = 1
              pmagplotlib.plot_imag(HDD['imag'], Bimag, Mnorm, imag_exp)
          else:
              if imag_init:
                  pmagplotlib.clearFIG(HDD['imag'])
          if len(list(HystRec.keys())) > 0:
              HystRecs.append(HystRec)
      #
          files = {}
          if save_plots and make_plots:
              if pltspec:
                  s = pltspec
              else:
                  s = specimen
              files = {}
              for key in list(HDD.keys()):
                  if incl_directory:
                      files[key] = os.path.join(output_dir_path, s+'_'+key+'.'+fmt)
                  else:
                      files[key] = s+'_'+key+'.'+fmt
              if make_plots and save_plots:
                  pmagplotlib.save_plots(HDD, files, incl_directory=incl_directory)
              #if pltspec:
              #    return True, []
          if interactive:
              pmagplotlib.draw_figs(HDD)
              ans = input(
                  "S[a]ve plots, [s]pecimen name, [q]uit, <return> to continue\n ")
              if ans == "a":
                  files = {}
                  for key in list(HDD.keys()):
                      if incl_directory:
                          files[key] = os.path.join(output_dir_path, specimen+'_'+key+'.'+fmt)
                      else:
                          files[key] = specimen+'_'+key+'.'+fmt
                  pmagplotlib.save_plots(HDD, files, incl_directory=incl_directory)
              if ans == '':
                  k += 1
              if ans == "p":
                  del HystRecs[-1]
                  k -= 1
              if ans == 'q':
                  print("Good bye")
                  return True, []
              if ans == 's':
                  keepon = 1
                  specimen = input(
                      'Enter desired specimen name (or first part there of): ')
                  while keepon == 1:
                      try:
                          k = sids.index(specimen)
                          keepon = 0
                      except:
                          tmplist = []
                          for qq in range(len(sids)):
                              if specimen in sids[qq]:
                                  tmplist.append(sids[qq])
                          print(specimen, " not found, but this was: ")
                          print(tmplist)
                          specimen = input('Select one or try again\n ')
                          k = sids.index(specimen)
  
          else:
              k += 1
          if len(B) == 0 and len(Bdcd) == 0:
              if verbose:
                  print('skipping this one - no hysteresis data')
              k += 1
          if k < len(sids):
              # must re-init figs for Windows to keep size
              if make_plots and set_env.IS_WIN:
                  if not save_plots:
                      pmagplotlib.plot_init(HDD['DdeltaM'], 5, 5)
                      pmagplotlib.plot_init(HDD['deltaM'], 5, 5)
                      pmagplotlib.plot_init(HDD['hyst'], 5, 5)
                  if len(Bimag) > 0:
                      HDD['imag'] = 4
                      if not save_plots:
                          pmagplotlib.plot_init(HDD['imag'], 5, 5)
                  if len(Bdcd) > 0:
                      HDD['irm'] = 5 if 'imag' in HDD else 4
                      if not save_plots:
                          pmagplotlib.plot_init(HDD['irm'], 5, 5)
              elif not make_plots and set_env.IS_WIN:
                  HDD['hyst'], HDD['deltaM'], HDD['DdeltaM'], HDD['irm'], HDD['imag'] = 0, 0, 0, 0, 0
      if len(HystRecs) > 0:
          #  go through prior_data, clean out prior results and save combined file as spec_file
          SpecRecs, keys = [], list(HystRecs[0].keys())
          if len(prior_data) > 0:
              prior_keys = list(prior_data[0].keys())
          else:
              prior_keys = []
          for rec in prior_data:
              for key in keys:
                  if key not in list(rec.keys()):
                      rec[key] = ""
              if 'LP-HYS' not in rec['method_codes']:
                  SpecRecs.append(rec)
          for rec in HystRecs:
              for key in prior_keys:
                  if key not in list(rec.keys()):
                      rec[key] = ""
              prior = pmag.get_dictitem(
                  prior_data, 'specimen', rec['specimen'], 'T')
              if len(prior) > 0 and 'sample' in list(prior[0].keys()):
                  # pull sample name from prior specimens table
                  rec['sample'] = prior[0]['sample']
              SpecRecs.append(rec)
          # drop unnecessary/duplicate rows
          #dir_path = os.path.split(spec_file)[0]
          con = cb.Contribution(input_dir_path, read_tables=[])
          con.add_magic_table_from_data('specimens', SpecRecs)
          con.tables['specimens'].drop_duplicate_rows(
              ignore_cols=['specimen', 'sample', 'citations', 'software_packages'])
          con.tables['specimens'].df = con.tables['specimens'].df.drop_duplicates()
          spec_file = os.path.join(output_dir_path, os.path.split(spec_file)[1])
          con.write_table_to_file('specimens', custom_name=spec_file)
          if verbose:
              print("hysteresis parameters saved in ", spec_file)
          return True, [spec_file]