docs: def __parse(self):
          """
          Parse
          Accept the text file. We'll open it, read it, and return a compiled dictionary to write to a json file
          May write a chronology CSV and a data CSV if those sections are available
          :return:
          """
          logger_noaa_lpd.info("enter parse")
  
          # Strings
          missing_str = ''
          data_filename = ''
  
          # Counters
          grant_id = 0
          funding_id = 0
          data_col_ct = 1
          line_num = 0
  
          # Boolean markers
          description_on = False
          publication_on = False
          abstract_on = False
          site_info_on = False
          chronology_on = False
          chron_vals_on = False
          variables_on = False
          data_vals_on = False
          data_on = False
  
          # Lists
          lat = []
          lon = []
          elev = []
          pub = []
          funding = []
          temp_abstract = []
          temp_description = []
          data_var_names = []
          data_col_list = []
          data_tables = []
  
          # All dictionaries needed to create JSON structure
          temp_funding = OrderedDict()
          temp_pub = OrderedDict()
          core_len = OrderedDict()
          geo_properties = OrderedDict()
          chron_dict = OrderedDict()
          data_dict_upper = OrderedDict()
          final_dict = OrderedDict()
  
          try:
              # Open the text file in read mode. We'll read one line at a time until EOF
              with open(self.filename_txt, 'r') as f:
                  logger_noaa_lpd.info("opened noaa file: {}".format(self.filename_txt))
                  for line in iter(f):
                      line_num += 1
  
                      # PUBLICATION
                      # There can be multiple publications. Create a dictionary for each one.
                      if publication_on:
                          # End of the section. Add the dictionary for this one publication to the overall list
                          if '-----' in line:
                              temp_pub = self.__reorganize_doi(temp_pub)
                              pub.append(temp_pub.copy())
                              temp_abstract.clear()
                              temp_pub.clear()
                              publication_on = False
                              logger_noaa_lpd.info("end section: Publication")
                          elif abstract_on:
                              # End of abstract: possibly more variables after.
                              if "#" in line:
                                  abstract_on = False
                                  temp_pub['abstract'] = ''.join(temp_abstract)
                                  logger_noaa_lpd.info("end section: Abstract")
                                  line = self.__str_cleanup(line)
                                  key, value = self.__slice_key_val(line)
                                  temp_pub[self.__camel_case(key)] = value
                              else:
                                  temp_abstract.append(self.__str_cleanup(line))
  
                          # Add all info into the current publication dictionary
                          else:
                              line = self.__str_cleanup(line)
                              key, value = self.__slice_key_val(line)
                              if key in ("Author", "Authors"):
                                  temp_pub["author"] = self.__reorganize_authors(value)
                              else:
                                  temp_pub[self.__camel_case(key)] = value
                                  if key == 'Abstract':
                                      logger_noaa_lpd.info("reading section: Abstract")
                                      abstract_on = True
                                      temp_abstract.append(value)
  
                      # DESCRIPTION AND NOTES
                      # Descriptions are often long paragraphs spanning multiple lines, but don't follow the key/value format
                      elif description_on:
  
                          # End of the section. Turn marker off and combine all the lines in the section
                          if '-------' in line:
                              description_on = False
                              value = ''.join(temp_description)
                              final_dict['description'] = value
                              logger_noaa_lpd.info("end section: Description_and_Notes")
  
                          # The first line in the section. Split into key, value
                          elif 'Description:' in line:
                              key, val = self.__slice_key_val(line)
                              temp_description.append(val)
  
                          # Keep a running list of all lines in the section
                          else:
                              line = self.__str_cleanup(line)
                              temp_description.append(line)
  
                      # SITE INFORMATION (Geo)
                      elif site_info_on:
  
                          if '-------' in line:
                              site_info_on = False
                              logger_noaa_lpd.info("end section: Site_Information")
  
                          else:
                              line = self.__str_cleanup(line)
                              key, value = self.__slice_key_val(line)
                              if key.lower() in ["northernmost_latitude", "southernmost_latitude"]:
                                  lat.append(self.__convert_num(value))
  
                              elif key.lower() in ["easternmost_longitude", "westernmost_longitude"]:
                                  lon.append(self.__convert_num(value))
  
                              elif key.lower() in ["site_name", "location", "country", "elevation"]:
                                  if key.lower() == 'elevation':
                                      val, unit = self.__split_name_unit(value)
                                      elev.append(val)
                                  else:
                                      geo_properties[self.__camel_case(key)] = value
  
                      # CHRONOLOGY
                      elif chronology_on:
                          """
                          HOW IT WORKS:
                          Chronology will be started at "Chronology:" section header
                          Every line starting with a "#" will be ignored
                          The first line without a "#" is considered the variable header line. Variable names are parsed.
                          Each following line will be considered column data and sorted accordingly.
                          Once the "-----" barrier is reached, we exit the chronology section.
                          """
                          # When reaching the end of the chron section, set the marker to off and close the CSV file
                          if '-------' in line:
                              # Turn off markers to exit section
                              chronology_on = False
                              chron_vals_on = False
                              try:
                                  # If nothing between the chronology start and the end barrier, then there won't be a CSV
                                  if chron_start_line != line_num - 1:
                                      try:
                                          chron_csv.close()
                                          logger_noaa_lpd.info("parse: chronology: no data found in chronology section")
                                      except NameError:
                                          logger_noaa_lpd.debug(
                                              "parse: chronology_on: NameError: chron_csv ref before assignment, {}".format(
                                                  self.filename_txt))
                                          print(
                                              "Chronology section is incorrectly formatted. "
                                              "Section data will not be converted")
  
                                  logger_noaa_lpd.info("end section: Chronology")
                              except NameError:
                                  logger_noaa_lpd.debug(
                                      "parse: chronology_on: NameError: chron_start_line ref before assignment, {}".format(
                                          self.filename_txt))
                                  print("Chronology section is incorrectly formatted. Section data will not be converted")
  
                          # Data values line. Split, then write to CSV file
                          elif chron_vals_on:
                              values = line.split()
                              try:
                                  cw.writerow(values)
                              except NameError:
                                  logger_noaa_lpd.debug(
                                      "parse: chronology_on: NameError: csv writer ref before assignment, {}".format(
                                          self.filename_txt))
                                  print("Chronology section is incorrectly formatted. Section data will not be converted")
  
                          else:
                              try:
                                  # Chron variable headers line
                                  if line and line[0] != "#":
                                      chron_filename = self.dsn + '.chron1.measurementTable1.csv'
                                      # Organize the var header into a dictionary
                                      variables = self.__reorganize_chron_header(line)
  
                                      # Create a dictionary of info for each column
                                      chron_col_list = self.__create_chron_cols(variables)
                                      chron_dict['filename'] = chron_filename
                                      chron_dict['chronTableName'] = 'Chronology'
                                      chron_dict['columns'] = chron_col_list
  
                                      # Open CSV for writing
                                      csv_path = os.path.join(self.dir_bag, chron_filename)
                                      chron_csv = open(csv_path, 'w+', newline='')
                                      logger_noaa_lpd.info("opened csv file: {}".format(chron_filename))
                                      cw = csv.writer(chron_csv)
                                      # Turn the marker on to start processing the values columns
                                      chron_vals_on = True
                              except IndexError:
                                  logger_noaa_lpd.debug("parse: chronology: IndexError when attempting chron var header")
  
                      # VARIABLES
                      elif variables_on:
                          """
                          HOW IT WORKS:
                          Variable lines are the only lines that have a "##" in front of them.
                          Ignore all lines that don't match the "##" regex.
                          Once there's a match, start parsing the variable lines, and create a column entry for each line.
                          """
                          process_line = False
                          # End of the section. Turn marker off
                          if "------" in line:
                              variables_on = False
                              logger_noaa_lpd.info("end section: Variables")
                          for item in NOAA_VAR_LINES:
                              if item.lower() in line.lower():
                                  process_line = False
                          for item in NOAA_EMPTY:
                              if item == line:
                                  process_line = False
                          m = re.match(re_var, line)
                          if m:
                              process_line = True
  
                          # If the line isn't in the ignore list, then it's a variable line
                          if process_line:
  
                              # Split the line items, and cleanup
                              cleaned_line = self.__separate_data_vars(line)
  
                              # Add the items into a column dictionary
                              data_col_dict = self.__create_paleo_col(cleaned_line, data_col_ct)
  
                              # Keep a list of all variable names
                              try:
                                  # Use this list later to cross check with the variable line in the Data section
                                  data_var_names.append(data_col_dict['variableName'])
                              except KeyError:
                                  data_var_names.append('')
                                  logger_noaa_lpd.warn("parse: variables: "
                                                       "KeyError: {} not found in {}".format("variableName", "data_col_dict"))
                              # Add the column dictionary into a final dictionary
                              data_col_list.append(data_col_dict)
                              data_col_ct += 1
  
                      # DATA
                      # Missing Value, Create data columns, and output Data CSV
                      elif data_on:
                          """
                          HOW IT WORKS:
                          Capture the "Missing Value" entry, if it exists.
                          Data lines should not have a "#" in front of them.
                          The first line without a "#" should be the variable header line
                          All lines that follow should have column data.
                          """
                          # Do not process blank or template lines
                          process_line = True
                          for item in NOAA_DATA_LINES:
                              if item in line:
                                  process_line = False
                          for item in NOAA_EMPTY:
                              if item == line:
                                  process_line = False
                          for item in ALTS_MV:
                              # Missing value found. Store entry
                              if item in line.lower():
                                  process_line = False
                                  line = self.__str_cleanup(line)
                                  key, missing_str = self.__slice_key_val(line)
  
                          if process_line:
                              # Split the line at each space (There SHOULD one space between each variable. Not always true)
                              values = line.split()
                              # Write all data values to CSV
                              if data_vals_on:
                                  try:
                                      dw.writerow(values)
                                  except NameError:
                                      logger_noaa_lpd.debug(
                                          "parse: data_on: NameError: csv writer ref before assignment, {}".format(
                                              self.filename_txt))
  
                              # Check for the line of variables
                              else:
                                  var = self.__str_cleanup(values[0].lstrip())
                                  # Check if a variable name is in the current line
                                  if var.lower() in line.lower():
                                      data_vals_on = True
                                      logger_noaa_lpd.info("start section: Data_Values")
                                      # Open CSV for writing
                                      data_filename = "{}.paleoData1.measurementTable1.csv".format(self.dsn)
                                      csv_path = os.path.join(self.dir_bag, data_filename)
                                      data_csv = open(csv_path, 'w+', newline='')
                                      logger_noaa_lpd.info("opened csv file: {}".format(data_filename))
                                      dw = csv.writer(data_csv)
  
                      # METADATA
                      else:
                          # Line Continuation: Sometimes there are items that span a few lines.
                          # If this happens, we want to combine them all properly into one entry.
                          if '#' not in line and line not in NOAA_EMPTY and old_val:
                              if old_key in ('funding', 'agency'):
                                  try:
                                      temp_funding[old_key] = old_val + line
                                  except KeyError as e:
                                      logger_noaa_lpd.debug(
                                          "parse: metadata: line continuation: {} not found in {}, {}".format(old_key,
                                                                                                              "temp_funding",
                                                                                                              e))
                              else:
                                  try:
                                      final_dict[old_key] = old_val + line
                                  except KeyError as e:
                                      logger_noaa_lpd.debug(
                                          "parse: metadata: line continuation: {} not found in {}, {}".format(old_key,
                                                                                                              "temp_funding",
                                                                                                              e))
  
                          # No Line Continuation: This is the start or a new entry
                          else:
                              line = self.__str_cleanup(line)
  
                              # Grab the key and value from the current line
                              try:
                                  # Split the line into key, value pieces
                                  key, value = self.__slice_key_val(line)
                                  l_key = key.lower()
                                  cc_key= self.__camel_case(key)
  
                                  # If there is no value, then we are at a section header.
                                  # Data often has a blank value, so that is a special check.
                                  if not value or l_key == 'data':
                                      # Turn on markers if we run into section headers
                                      if l_key == 'description_and_notes':
                                          description_on = True
                                          logger_noaa_lpd.info("reading section: Description_and_Notes")
                                      elif l_key == 'publication':
                                          publication_on = True
                                          logger_noaa_lpd.info("reading section: Publication")
                                      elif l_key == 'site_information':
                                          site_info_on = True
                                          logger_noaa_lpd.info("reading section: Site_Information")
                                      elif l_key == 'chronology':
                                          chronology_on = True
                                          logger_noaa_lpd.info("reading section: Chronology")
                                          chron_start_line = line_num
                                      elif l_key == 'variables':
                                          variables_on = True
                                          logger_noaa_lpd.info("reading section: Variables")
                                      elif l_key == 'data':
                                          data_on = True
                                          logger_noaa_lpd.info("reading section: Data")
                                  # For all
                                  else:
                                      # Ignore any entries that are specified in the skip list
                                      _ignore = [item.lower() for item in NOAA_KEYS_BY_SECTION["Ignore"]]
                                      if l_key not in _ignore:
                                          # There can be multiple funding agencies and grants. Keep a list of dict entries
                                          _funding = [item.lower() for item in NOAA_KEYS_BY_SECTION["Funding_Agency"]]
                                          if l_key in _funding:
                                              if l_key == 'funding_agency_name':
                                                  funding_id += 1
                                                  key = 'agency'
                                              elif l_key == 'grant':
                                                  grant_id += 1
                                                  key = 'grant'
                                              temp_funding[key] = value
                                              # If both counters are matching, we are ready to add content to the funding list
                                              if grant_id == funding_id:
                                                  funding.append(temp_funding.copy())
                                                  temp_funding.clear()
                                          else:
                                              # There's likely two "Online_Resource"s, and we need both, so check and concat
                                              if cc_key == "onlineResource":
                                                  # If it exists, append. If not, add entry as a list
                                                  if cc_key in final_dict:
                                                      final_dict[cc_key].append(value)
                                                  else:
                                                      final_dict[cc_key] = [value]
                                              else:
                                                  final_dict[cc_key] = value
                                          # Keep track of old key in case we have a line continuation
                                          old_key = key
                                          old_val = value.strip()
                              except TypeError as e:
                                  logger_noaa_lpd.warn(
                                      "parse: TypeError: none type received from slice_key_val, {}".format(e))
  
              # Wait to close the data CSV until we reached the end of the text file
              try:
                  data_csv.close()
                  logger_noaa_lpd.info("end section: Data_Values")
                  logger_noaa_lpd.info("end section: Data")
              except NameError as e:
                  print("Error: NOAA text file is contains format errors. Unable to process.")
                  logger_noaa_lpd.debug(
                      "parse: NameError: failed to close csv, invalid formatting in NOAA txt file, {}".format(e))
  
              # Piece together measurements block
              logger_noaa_lpd.info("compiling final paleoData")
              data_dict_upper['filename'] = data_filename
              data_dict_upper['paleoDataTableName'] = 'Data'
              data_dict_upper['missingValue'] = missing_str
              data_dict_upper['columns'] = data_col_list
              data_tables.append(data_dict_upper)
  
              # Piece together geo block
              logger_noaa_lpd.info("compiling final geo")
              geo = self.__create_coordinates(lat, lon, elev)
              geo['properties'] = geo_properties
  
              # Piece together final dictionary
              logger_noaa_lpd.info("compiling final master")
              final_dict['pub'] = pub
              final_dict['funding'] = funding
              final_dict['geo'] = geo
              final_dict['coreLength'] = core_len
              final_dict['chronData'] = [{"chronMeasurementTable": chron_dict}]
              final_dict['paleoData'] = data_tables
              self.metadata = final_dict
              logger_noaa_lpd.info("final dictionary compiled")
  
              # Start cleaning up the metadata
              logger_noaa_lpd.info("removing empty fields")
              self.metadata = rm_empty_fields(self.metadata)
              logger_noaa_lpd.info("removing empty doi")
              self.metadata = rm_empty_doi(self.metadata)
              logger_noaa_lpd.info("removing irrelevant keys")
              self.__remove_irr_fields()
  
          except Exception as e:
              logger_noaa_lpd.debug("parse: {}".format(e))
  
          logger_noaa_lpd.info("exit parse")
          return