docs: def _get_ATOM_sequences(self):
          '''Creates the ATOM Sequences.'''
  
          # Get a list of all residues with ATOM or HETATM records
          atom_sequences = {}
          structural_residue_IDs_set = set() # use a set for a quicker lookup
          ignore_HETATMs = True # todo: fix this if we need to deal with HETATMs
  
          residue_lines_by_chain = []
          structural_residue_IDs_set = []
  
          present_chain_ids = {}
          for l in self.structure_lines:
              if len(l) > 21 and l[:3] != 'TER':
                  present_chain_ids[l[21]] = present_chain_ids.get(l[21], set())
                  present_chain_ids[l[21]].add(l[:6])
  
          model_index = 0
          residue_lines_by_chain.append([])
          structural_residue_IDs_set.append(set())
          full_code_map = {}
          hetatm_map = {}
          full_atom_map = {}
          for l in self.structure_lines:
              chain_id = None
              if l.startswith("TER   "):
                  model_index += 1
                  residue_lines_by_chain.append([])
                  structural_residue_IDs_set.append(set())
              else:
                  residue_id = l[21:27]
                  if residue_id not in structural_residue_IDs_set[model_index]:
                      residue_lines_by_chain[model_index].append(l)
                      structural_residue_IDs_set[model_index].add(residue_id)
                  if l.startswith('ATOM'):
                      chain_id = l[21]
                      # Only use ATOM records to build the code map as chains can have ligands HETATMs
                      full_code_map[chain_id] = full_code_map.get(chain_id, set())
                      full_code_map[chain_id].add(l[17:20].strip())
  
                      # Only use ATOM records to build the atom map as CA-only chains can have ligands described in full as HETATMs
                      full_atom_map[chain_id] = full_atom_map.get(chain_id, set())
                      full_atom_map[chain_id].add(l[12:16].strip())
                  elif l.startswith('HETATM'):
                      chain_id = l[21]
                      hetatm_map[chain_id] = hetatm_map.get(chain_id, set())
                      hetatm_map[chain_id].add(l[17:20].strip())
  
          # Get the residues used by the residue lines. These can be used to determine the chain type if the header is missing.
          for chain_id in self.atom_chain_order:
              if full_code_map.get(chain_id):
                  # The chains may contain other molecules e.g. MG or HOH so before we decide their type based on residue types alone,
                  # we subtract out those non-canonicals
                  canonical_molecules = full_code_map[chain_id].intersection(dna_nucleotides.union(rna_nucleotides).union(residue_types_3))
  
                  determined_chain_type = None
                  if canonical_molecules.union(dna_nucleotides) == dna_nucleotides:
                      determined_chain_type = 'DNA'
                  elif canonical_molecules.union(rna_nucleotides) == rna_nucleotides:
                      determined_chain_type = 'RNA'
                  elif len(full_code_map[chain_id]) == 1 and 'UNK' in full_code_map[chain_id]:
                      determined_chain_type = 'Unknown'
                  elif canonical_molecules:
                      if len(full_atom_map[chain_id]) == 1 and 'CA' in full_atom_map[chain_id]:
                          determined_chain_type = 'Protein skeleton'
                      else:
                          determined_chain_type = 'Protein'
                  else:
                      determined_chain_type = PDB._determine_heterogen_chain_type(canonical_molecules)
  
                  if self.chain_types.get(chain_id):
                      assert(self.chain_types[chain_id] == determined_chain_type)
                  else:
                      self.chain_types[chain_id] = determined_chain_type
  
          line_types_by_chain = []
          chain_ids = []
          for model_index in range(len(residue_lines_by_chain)):
              line_types = set()
              if residue_lines_by_chain[model_index]:
                  if missing_chain_ids.get(self.pdb_id):
                      chain_ids.append(missing_chain_ids[self.pdb_id])
                  else:
                      chain_ids.append(residue_lines_by_chain[model_index][0][21])
              for l in residue_lines_by_chain[model_index]:
                  line_types.add(l[0:6])
              if line_types == set(['ATOM']):
                  line_types_by_chain.append('ATOM')
              elif line_types == set(['HETATM']):
                  line_types_by_chain.append('HETATM')
              else:
                  line_types_by_chain.append('Mixed')
  
          for x in range(0, len(residue_lines_by_chain)):
              residue_lines = residue_lines_by_chain[x]
              line_types = line_types_by_chain[x]
              if ignore_HETATMs and line_types == 'HETATM':
                  continue
  
              for y in range(len(residue_lines)):
                  l = residue_lines[y]
                  residue_type = l[17:20].strip()
                  if l.startswith("HETATM"):
                      if self.modified_residue_mapping_3.get(residue_type):
                          residue_type = self.modified_residue_mapping_3[residue_type]
                      elif y == (len(residue_lines) - 1):
                          # last residue in the chain
                          if residue_type == 'NH2':
                              residue_type = 'UNK' # fixes a few cases e.g. 1MBG, 1K9Q, 1KA6
                          elif ignore_HETATMs:
                              continue
  
                      elif ignore_HETATMs:
                          continue
  
                  residue_id = l[21:27]
                  chain_id = l[21]
                  if missing_chain_ids.get(self.pdb_id):
                      chain_id = missing_chain_ids[self.pdb_id]
  
                  if chain_id in self.chain_types:
                      # This means the pdb had SEQRES and we constructed atom_sequences
                      chain_type = self.chain_types[chain_id]
                  else:
                      # Otherwise assume this is protein
                      chain_type = 'Protein'
  
                  atom_sequences[chain_id] = atom_sequences.get(chain_id, Sequence(chain_type))
  
                  residue_type = self.modified_residue_mapping_3.get(residue_type, residue_type)
  
                  short_residue_type = None
                  if residue_type == 'UNK':
                      short_residue_type = 'X'
                  elif chain_type == 'Unknown':
                      assert(False) # we should not reach here - Unknown chains should only contain UNK records
                  elif chain_type == 'Protein' or chain_type == 'Protein skeleton':
                      short_residue_type = residue_type_3to1_map.get(residue_type) or protonated_residue_type_3to1_map.get(residue_type) or non_canonical_amino_acids.get(residue_type)
                  elif chain_type == 'DNA':
                      short_residue_type = dna_nucleotides_2to1_map.get(residue_type) or non_canonical_dna.get(residue_type)
                  elif chain_type == 'RNA':
                      short_residue_type = non_canonical_rna.get(residue_type) or residue_type
  
                  if not short_residue_type:
                      if l.startswith("ATOM") and l[12:16] == ' OH2' and l[17:20] == 'TIP':
                          continue
                      elif not self.strict:
                          short_residue_type = 'X'
                      else:
                          raise NonCanonicalResidueException("Unrecognized residue type %s in PDB file '%s', residue ID '%s'." % (residue_type, str(self.pdb_id), str(residue_id)))
  
                  #structural_residue_IDs.append((residue_id, short_residue_type))
                  # KAB - way to allow for multiresidue noncanonical AA's
                  if len(short_residue_type) == 1:
                      atom_sequences[chain_id].add(PDBResidue(residue_id[0], residue_id[1:], short_residue_type, chain_type))
                  else:
                      for char in short_residue_type:
                          atom_sequences[chain_id].add(PDBResidue(residue_id[0], residue_id[1:], char, chain_type))
  
          # Assign 'Ligand' or 'Heterogen' to all HETATM-only chains
          for chain_id in present_chain_ids.keys():
              if chain_id not in self.chain_types:
                  assert('ATOM  ' not in present_chain_ids[chain_id])
                  self.chain_types[chain_id] = PDB._determine_heterogen_chain_type(hetatm_map.get(chain_id, set()))
          self.atom_sequences = atom_sequences