docs: def add_pdb_set(self, pdb_names, lchains, rchains, is_complex, notes = None):
          '''lchains and rchains should be lists of pairs (p, c, n) where p is a PDB object (bio/pdb.py:PDB), c is a chain
             identifier, and n is the NMR model number (or zero if this is not applicable).
             (character). This allows us to represent combinations of unbound chains.
             is_complex should be set to True if the PDB chains collectively form a complex.'''
  
          # If PDB objects differ and is_complex is set, raise an exception
          # This is not foolproof - we use the PDB object reference which could differ if the same PDB were loaded more than
          # once and passed in. However, that would be bad practice and this check is much cheaper than comparing the PDB content.
          if len(set([pc[0] for pc in lchains + rchains])) > 1 and is_complex:
              raise Exception('The PDB set cannot be marked as a complex as it is defined using multiple PDB objects.')
  
          # Check for unique occurrences of PDB chains (same caveat applies as above)
          all_chains = [(pc[0], pc[1]) for pc in lchains + rchains]
          if not len(all_chains) == len(set(all_chains)):
              raise Exception('Each PDB chain should be included at most once.')
  
          # Make sure that the chains exist in the PDB objects
          for pc in lchains + rchains:
              assert(pc[0] in pdb_names)
              assert(pc[1] in pc[0].atom_sequences)
  
          # Create the metadata
          set_number = len(self.pdb_sets)
          pdb_set = dict(
              set_number = set_number,
              is_complex = is_complex,
              notes = notes,
              chains = dict(L = [], R = []),
              pdb_set_id = None
          )
  
          # Add the PDB chains
          pdb_set_id = []
          for chain_set_def in ((lchains, 'L'), (rchains, 'R')):
              for pc in sorted(chain_set_def[0]):
                  chain_set = pdb_set['chains'][chain_set_def[1]]
                  nmr_model = None
                  if len(pc) > 2:
                      nmr_model = pc[2]
                  chain_set.append(dict(
                      chain_index = len(chain_set),
                      pdb_file_id = pdb_names[pc[0]],
                      chain_id = pc[1],
                      nmr_model = nmr_model,
                  ))
                  pdb_set_id.append('{0}:{1}:{2}:{3}'.format(chain_set_def[0], pdb_names[pc[0]], pc[1], nmr_model))
          pdb_set['pdb_set_id'] = sorted(pdb_set_id)
          print(pdb_set['pdb_set_id'])
  
          # Make sure we do not already have this set defined (the Complex should contain a unique list of bags of chains).
          if pdb_set['pdb_set_id'] in [ps['pdb_set_id'] for ps in self.pdb_sets]:
              raise Exception('This PDB set has already been defined (same PDB chains/NMR models).')
  
          self.pdb_sets.append(pdb_set)