First the atom names of protein charge centers are found as these can be different in different forcefields.
        Then a Euclidian distance is measured between charged ligand atoms and respective inverted charge centres on
        protein. If the distance s lower than threshold (5.5 angstrom) the interaction is recognised as a salt bridge.

def find_salt_bridges(self):
        """First the atom names of protein charge centers are found as these can be different in different forcefields.
        Then a Euclidian distance is measured between charged ligand atoms and respective inverted charge centres on
        protein. If the distance s lower than threshold (5.5 angstrom) the interaction is recognised as a salt bridge."""
        #Define charge centers for protein - atom names
        charge_definitions = {"ARG":"name C* and around 1.4 (name N* and not name N)", #carbon atom surrounded by nitrogens that are not in the peptide bond
                            "LYS":"name N* and not name N", # The nitrogen that is not in the peptide bond
                            "HIS":"name N* and not name N", # Both nitrogens (charge distributed between them)
                            "ASP":"name C* and around 1.4 (name O* and not name O)", # Carbon surrounded by oxygens not in peptide bond
                            "GLU":"name C* and around 1.4 (name O* and not name O)" # Carbon surrounded by oxygens not in peptide bond
        }
        alternative_name_sel = {"ASP":"CG", "ARG":"CZ","GLU":"CD"}
        prot_charge_center = {}
        # Find the atom names - these can different in different forcefields
        for res in ["ASP","GLU","HIS","LYS","ARG"]:
            for residue in self.topology_data.universe.residues:
                if residue.resname == res:
                    atomselection = residue.atoms
                    try:
                        name_selection = atomselection.select_atoms(charge_definitions[res])
                        prot_charge_center[res]=name_selection.names[0]
                    except Exception as e:
                        #In case MDAnalysis misbehaves and cannot use around
                        prot_charge_center[res]=alternative_name_sel[res]
                    break

        #Measure distances
        data = namedtuple("saltbridge","frame time ligandatomid ligandatomname distance resname resid segid")
        i=0
        if self.trajectory==[]:
            self.trajectory = [self.topology_data.universe.filename]
            self.start_frame_num=[None]
            self.end_frame_num = [None]
            self.skip =[None]
        for traj in self.trajectory:
            self.timeseries=[]
            self.timesteps=[frame.time for frame in self.topology_data.universe.trajectory[self.start_frame_num[i]:self.end_frame_num[i]:self.skip[i]]]
            start = timer()
            self.topology_data.load_trajectory(traj)
            for atom in self.lig_descr.ligand_atoms:
                if self.lig_descr.ligand_atoms[atom]["Formal charges"]<0:
                    for residue in self.topology_data.dict_of_plotted_res:
                        if residue[0] in ["LYS","ARG","HIS"]:
                            pos_res_atom = self.topology_data.universe.select_atoms("resname "+residue[0]+" and resid "+residue[1]+" and segid "+ residue[2]+" and name "+prot_charge_center[residue[0]])
                            lig_atom = self.topology_data.universe.ligand.select_atoms("name "+self.lig_descr.ligand_atoms[atom]["name"])
                            for frame in self.topology_data.universe.trajectory[self.start_frame_num[i]:self.end_frame_num[i]:self.skip[i]]:
                                if residue[0]==["HIS"]:
                                    #HIS has two atoms in the selection - need to find a middle point (i.e. centroid)
                                    pos_res_pos = pos_res_atom.centroid()
                                    dist = math.euclidean3d(pos_res_pos,lig_atom.positions[0])
                                else:
                                    dist = math.euclidean3d(pos_res_atom.positions[0],lig_atom.positions[0])
                                if dist <= math.saltbridge_dist:
                                    contacts = data(frame=frame.frame, time=frame.time, ligandatomid=lig_atom.atoms.ids, ligandatomname=lig_atom.atoms.names,
                                                    distance=dist, resname=residue[0],resid=residue[1],segid=residue[2])
                                    self.timeseries.append(contacts)
                if self.lig_descr.ligand_atoms[atom]["Formal charges"]>0:
                    for residue in self.topology_data.dict_of_plotted_res:
                        if residue[0] in ["ASP","GLU"]:
                            neg_res_atom = self.topology_data.universe.select_atoms("resname "+residue[0]+" and resid "+residue[1]+" and segid "+ residue[2]+" and name "+prot_charge_center[residue[0]])
                            lig_atom = self.topology_data.universe.ligand.select_atoms("name "+self.lig_descr.ligand_atoms[atom]["name"])
                            for frame in self.topology_data.universe.trajectory[self.start_frame_num[i]:self.end_frame_num[i]:self.skip[i]]:
                                dist = math.euclidean3d(neg_res_atom.positions[0],lig_atom.positions[0])
                                if dist <= self.saltbridge_dist:
                                    contacts = data(frame=frame.frame, time=frame.time, ligandatomid=lig_atom.atoms.ids[0], ligandatomname=lig_atom.atoms.names[0],
                                                    distance=dist, resname=residue[0],resid=residue[1],segid=residue[2])
                                    self.timeseries.append(contacts)
            self.saltbridges[i] = self.make_table()

            self.saltbridges_by_time[i] = self.count_by_time()
            self.saltbridges_by_type[i] = self.count_by_type()
            i+=1
        end = timer()
        print "Salt Bridges:"+str(end-start)