code: def find_donors_and_acceptors_in_ligand(self):
          
          atom_names=[x.name for x in self.topology_data.universe.ligand]
          try:
              for atom in self.topology_data.mol.GetSubstructMatches(self.HDonorSmarts, uniquify=1):
                  self.donors.append(atom_names[atom[0]])
              for atom in self.topology_data.mol.GetSubstructMatches(self.HAcceptorSmarts, uniquify=1):
                  self.acceptors.append(atom_names[atom[0]])
          except Exception as e:
              m = Chem.MolFromPDBFile("lig.pdb")
              self.donors = []
              self.acceptors = []
              for atom in m.GetSubstructMatches(self.HDonorSmarts, uniquify=1):
                  self.donors.append(atom_names[atom[0]])
              haccep = "[$([O,S;H1;v2]-[!$(*=[O,N,P,S])]),$([O,S;H0;v2]),$([O,S;-]),$([N;v3;!$(N-*=!@[O,N,P,S])]),$([nH0,o,s;+0])]"
              self.HAcceptorSmarts = Chem.MolFromSmarts(haccep)
              for atom in m.GetSubstructMatches(self.HAcceptorSmarts, uniquify=1):
                  self.acceptors.append(atom_names[atom[0]])
docs: Since MDAnalysis a pre-set list for acceptor and donor atoms for proteins and solvents
          from specific forcefields, it is necessary to find donor and acceptor atoms for the
          ligand molecule. This function uses RDKit and searches through ligand atoms to find
          matches for pre-set list of possible donor and acceptor atoms. The resulting list is then
          parsed to MDAnalysis through the donors and acceptors arguments.