From 5a5a44bc107033154b240278426e60b9a8e6e8b2 Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:39:43 +0100 Subject: [PATCH 01/11] Delete data.pyc --- lintools/data.pyc | Bin 8486 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/data.pyc diff --git a/lintools/data.pyc b/lintools/data.pyc deleted file mode 100644 index 85c3aa2403d6f93d39792ea8591388f0d737fe89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8486 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 Date: Tue, 19 Jun 2018 15:39:52 +0100 Subject: [PATCH 02/11] Delete figure.pyc --- lintools/figure.pyc | Bin 6701 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/figure.pyc diff --git a/lintools/figure.pyc b/lintools/figure.pyc deleted file mode 100644 index 6bb977fcc9ec7dda7348a8ba84559903c71ae7a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6701 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 From bc1f93776db976bd04ee12c2ef38d3f75625a458 Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:40:19 +0100 Subject: [PATCH 03/11] Delete molecule.pyc --- lintools/molecule.pyc | Bin 11649 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/molecule.pyc diff --git a/lintools/molecule.pyc b/lintools/molecule.pyc deleted file mode 100644 index 06070e4da7511e9fa02d0dfaff9d2d0777ad5b61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11649 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 Date: Tue, 19 Jun 2018 15:40:31 +0100 Subject: [PATCH 04/11] Delete plots.pyc --- lintools/plots.pyc | Bin 7147 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/plots.pyc diff --git a/lintools/plots.pyc b/lintools/plots.pyc deleted file mode 100644 index 7056e6a949584d3781a189b75f702b1b001cb290..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7147 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 Date: Tue, 19 Jun 2018 15:40:54 +0100 Subject: [PATCH 05/11] Delete __init__.pyc --- lintools/analysis/__init__.pyc | Bin 116 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/analysis/__init__.pyc diff --git a/lintools/analysis/__init__.pyc b/lintools/analysis/__init__.pyc deleted file mode 100644 index d80757272daa3d701e354da23c12012eac5aca30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116 zcmZSn%*(~=W*C{w00oRd+5w1*S%5?e14FO|NW@PANHCxg#j-%LoXotE{QR6^{lvV) noXX Date: Tue, 19 Jun 2018 15:41:03 +0100 Subject: [PATCH 06/11] Delete hbonds.pyc --- lintools/analysis/hbonds.pyc | Bin 12802 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/analysis/hbonds.pyc diff --git a/lintools/analysis/hbonds.pyc b/lintools/analysis/hbonds.pyc deleted file mode 100644 index 94594e02b99da805556dcca08e7f08484026cc9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12802 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 RQwP)51b%s(Vp0=@{{~M9V445` From 51a138cab015b11bfa383c90225c41baa19b29b7 Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:41:36 +0100 Subject: [PATCH 07/11] Delete residence_time.pyc --- lintools/analysis/residence_time.pyc | Bin 6877 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lintools/analysis/residence_time.pyc diff --git a/lintools/analysis/residence_time.pyc b/lintools/analysis/residence_time.pyc deleted file mode 100644 index dc7822d7d2b9066125e915165ff03a9971d11066..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6877 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 PHzuUd;9Cc`@jLfFk3n-N From 3c4bbc6cfa122dd4c327748be59e9eb5517d5f9c Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:44:12 +0100 Subject: [PATCH 08/11] Add files via upload --- lintools/hbonds.py | 246 +++++++++++++++++++++++++++++++++++++++++++ lintools/lintools.py | 21 ++-- lintools/plots.py | 31 +++--- 3 files changed, 273 insertions(+), 25 deletions(-) create mode 100644 lintools/hbonds.py diff --git a/lintools/hbonds.py b/lintools/hbonds.py new file mode 100644 index 0000000..81990ff --- /dev/null +++ b/lintools/hbonds.py @@ -0,0 +1,246 @@ +from collections import defaultdict +import csv +import MDAnalysis +from MDAnalysis.analysis import hbonds +from timeit import default_timer as timer +from rdkit import Chem +import rdkit +import numpy as np +import os + +class HBonds(object): + """ + This module analyses hydrogen bonds the ligand forms with the protein (version "09.2016"). + The donor and acceptor atoms in ligand molecule are detected by RDKit, then the bonds are + detected by MDAnalysis hydrogen bonding analysis and counted by time (how many total bonds + per frame) and by type (fraction of time per each hydrogen bond). Information about the + total count of hydrogen bonds over time is provided in a data file (CSV format). Each hydro- + gen bond is then analysed to decide whether to plot it in the final image. + + Takes: + * topology_data_object * - information about the system (lintools.Data object) + * trajectory * - list of trajectories + * start_frame_num * - list^^ of frame numbers for start of analysis (Opt) + * end_frame_num * - list^^ of frame numbers for end of analysis (Opt) + * skip * - list^^ of numbers of how many frames should be skipped for this analysis (Opt) + * distance * - distance between hydrogen bond donor and acceptor atoms in angstroms + * analysis_cutoff * - (user-defined) fraction of time a hydrogen bond has to be + present for to be plotted (default - 0.3). It is multiplied by number of trajectories + + ^^ The reason these values are lists is because several trajectories can be submitted for + analysis and different values could be required for each simulation. Therefore, similarly + as with trajectories, start, end and skip variables are submitted as lists with values + corresponding for each trajectory. + + Example: trajectory = ["1.xtc","2.xtc"] #Both are 1000 frames, but the user only wants to + analyse second half the the second trajectory + start = [0(for the first traj),500(for the second traj)] + Other values can be left as default. + """ + __version__ = "06.2018" + def __init__(self, topology_data_object, trajectory, start_frame_num=None,end_frame_num=None,skip=None,analysis_cutoff=0.3,distance=3): + self.hbonds = None + self.HDonorSmarts = Chem.MolFromSmarts('[$([N;!H0;v3]),$([N;!H0;+1;v4]),$([O,S;H1;+0]),$([n;H1;+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) + self.donors = [] + self.acceptors = [] + self.topology_data = topology_data_object + self.trajectory = trajectory + self.hbonds = {} + self.hbonds_timesteps={} + self.hbonds_by_time = {} + self.hbonds_by_type = {} + self.hbonds_timesteps_by_type = {} + self.start_frame_num = start_frame_num + self.end_frame_num = end_frame_num + self.skip = skip + self.find_donors_and_acceptors_in_ligand() + if len(trajectory)>0: + self.analyse_hydrogen_bonds_traj(distance) + else: + self.analyse_hydrogen_bonds_topology(distance) + self.determine_hbonds_for_drawing(analysis_cutoff) + self.write_output_files() + def find_donors_and_acceptors_in_ligand(self): + """ + 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. + """ + 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]]) + def analyse_hydrogen_bonds_traj(self,distance=3): + """ + MDAnalysis.analysis.hbonds module is used to analyse hydrogen bonds formed between protein + and ligand for each submitted trajectory. The hydrogen bonds are then counted by total value + per frame (count_by_time), as well as obtaining the frequency of each individual hydrogen + bond (count_by_type). + + Format of h.table below is time, donor_index, acceptor_index, donor_resnm, donor_resid, donor_atom, acceptor_resnm, acceptor_resid, acceptor_atom, distance, angle. + count_by_type should return atom indices, residue names, residue numbers (for donors and acceptors) and the fraction of the total time, but actually format is:- + + donor_atom, acceptor_atom, donor_atom_name, acceptor_atom_name, donor_resname, donor_resid, acceptor_resname, acceptor_resid, time. + + + Takes: + * distance * - distance between hydrogen bond donor and acceptor in angstroms + Output: + * self.hbonds * - array with information about all detected hydrogen bonds + * self.hbonds_by_time * - total hbond number by frame + * self.hbonds_by_type * - frequency of each hydrogen bond + + """ + i=0 + for traj in self.trajectory: + self.topology_data.load_trajectory(traj) + start = timer() + h = MDAnalysis.analysis.hbonds.HydrogenBondAnalysis(self.topology_data.universe,'(segid '+str(self.topology_data.universe.ligand.segids[0])+' and resid '+str(self.topology_data.universe.ligand.resids[0])+')',"protein",distance=3,acceptors=self.acceptors,donors=self.donors,start=self.start_frame_num[i],stop=self.end_frame_num[i],step=self.skip[i]) + h.run() + h.generate_table() + end = timer() + self.hbonds[i]=h.table + self.hbonds_timesteps[i] =h.timesteps + self.hbonds_by_time[i] = h.count_by_time() + self.hbonds_by_type[i] = self.count_by_type(h.table,h.timesteps) + self.hbonds_timesteps_by_type[i] = h.timesteps_by_type() + i+=1 + + def count_by_type(self,table,timesteps): + """Count how many times each individual hydrogen bonds occured throughout the simulation. + Returns numpy array.""" + hbonds = defaultdict(int) + for contact in table: + #count by residue name not by protein ring + pkey = (contact.donor_index,contact.acceptor_index,contact.donor_atom, contact.acceptor_atom,contact.donor_resnm,contact.donor_resid, contact.acceptor_resnm,contact.acceptor_resid) + hbonds[pkey]+=1 + dtype = [("donor_index",int),("acceptor_index",int),("donor_atom","|U4"),("acceptor_atom","|U4"),("donor_resnm","|U8"),("donor_resid","|U8"),("acceptor_resnm","|U8"),("acceptor_resid","|U8"),("frequency",float) ] + out = np.empty((len(hbonds),),dtype=dtype) + tsteps = float(len(timesteps)) + for cursor,(key,count) in enumerate(hbonds.iteritems()): + out[cursor] = key + (count / tsteps,) + return out.view(np.recarray) + + def analyse_hydrogen_bonds_topology(self,distance=3): + #This is the routine that is called if only a single coordinate file is requested. + """ + MDAnalysis.analysis.hbonds module is used to analyse hydrogen bonds formed between protein + and ligand for each submitted trajectory. The hydrogen bonds are then counted by total value + per frame (count_by_time), as well as obtaining the frequency of each individual hydrogen + bond (count_by_type). This function is used in case no trajectory has been submitted for analysis. + + Takes: + * distance * - distance between hydrogen bond donor and acceptor in angstroms + Output: + * self.hbonds * - array with information about all detected hydrogen bonds + * self.hbonds_by_time * - total hbond number by frame + * self.hbonds_by_type * - frequency of each hydrogen bond + """ + + h = MDAnalysis.analysis.hbonds.HydrogenBondAnalysis(self.topology_data.universe,'(segid '+str(self.topology_data.universe.ligand.segids[0])+' and resid '+str(self.topology_data.universe.ligand.resids[0])+')',"protein",distance=3,acceptors=self.acceptors,donors=self.donors) + h.run() + h.generate_table() + self.hbonds[0]=h.table + self.hbonds_by_time[0] = h.count_by_time() + self.hbonds_by_type[0] = h.count_by_type() + + def determine_hbonds_for_drawing(self, analysis_cutoff): + """ + Since plotting all hydrogen bonds could lead to a messy plot, a cutoff has to be imple- + mented. In this function the frequency of each hydrogen bond is summated and the total + compared against analysis cutoff - a fraction multiplied by trajectory count. Those + hydrogen bonds that are present for longer than analysis cutoff will be plotted in the + final plot. + + Takes: + * analysis_cutoff * - (user-defined) fraction of time a hydrogen bond has to be + present for to be plotted (default - 0.3). It is multiplied by number of trajectories + Output: + * frequency * - dictionary of hydrogen bond donor-acceptor indices and frequencies + These hydrogen bonds will be plotted in the final image. + + """ + self.frequency = defaultdict(int) + for traj in self.hbonds_by_type: + for bond in self.hbonds_by_type[traj]: + # frequency[(residue_atom_idx,ligand_atom_name,residue_atom_name)]=frequency + # residue atom name will be used to determine if hydrogen bond is interacting with a sidechain or bakcbone + # Following looks problematic for the trajectory subroutine as LD's routine does not return indices..? + if bond["donor_resnm"]!="LIG": + self.frequency[(bond["donor_index"],bond["acceptor_atom"],bond["donor_atom"],bond["acceptor_index"])] += bond["frequency"] + #check whether ligand is donor or acceptor + else: + self.frequency[(bond["acceptor_index"],bond["donor_atom"],bond["acceptor_atom"],bond["donor_index"])] += bond["frequency"] + + #Add the frequency counts + self.frequency = {i:self.frequency[i] for i in self.frequency if self.frequency[i]>(int(len(self.trajectory))*analysis_cutoff)} + + + #change the ligand atomname to a heavy atom - required for plot since only heavy atoms shown in final image + self.hbonds_for_drawing = {} + for bond in self.frequency: + atomname = bond[1] + if atomname.startswith("O",0) or atomname.startswith("N",0): + lig_atom=atomname + else: + atomindex = [index for index,atom in enumerate(self.topology_data.universe.ligand.atoms) if atom.name==atomname][0] + rdkit_atom = self.topology_data.mol.GetAtomWithIdx(atomindex) + for neigh in rdkit_atom.GetNeighbors(): + neigh_atom_id = neigh.GetIdx() + lig_atom = [atom.name for index,atom in enumerate(self.topology_data.universe.ligand.atoms) if index==neigh_atom_id][0] + self.hbonds_for_drawing[(bond[0],lig_atom,bond[2],bond[3])]=self.frequency[bond] + + def write_output_files(self): + #This is probably not the most efficient code, but its probably easier to read (PCB). + #Note that total may be more than the apparent sum because the total is the total hbonds for each time, whereas we are only dumping out individual files for ones where + #there is greater a certain % of time occurance. + + """ + The total hydrogen bond count per frame is provided as CSV output file. + Each trajectory has a separate file. + """ + os.mkdir("analysis") + os.chdir("analysis") + os.mkdir("hydrogen_bonds") + os.chdir("hydrogen_bonds") + for traj in range(len(self.trajectory)): + with open('hbonds_data_total_'+str(traj)+'.csv', 'wb') as outfile: + hwriter = csv.writer(outfile, delimiter=',') + for time in self.hbonds_by_time[traj]: + hwriter.writerow([time[0],time[1]]) + for bond in self.hbonds_by_type[traj]: + if bond["donor_resnm"]=="LIG" and (bond["acceptor_index"],bond["donor_index"]) in [(k[0],k[3]) for k,v in self.hbonds_for_drawing.items()]: + with open('hbond_'+bond["acceptor_resnm"]+"_"+str(bond["acceptor_resid"])+"_"+bond["donor_atom"]+"_"+str(traj)+".csv","wb") as outfile: + hwriter = csv.writer(outfile, delimiter=',') + for time in self.hbonds_timesteps[traj]: + result = 0 + for x in self.hbonds[traj]: + if (x[0]==time and x["acceptor_index"]==bond["acceptor_index"]): + result = result + 1 + hwriter.writerow([time,result]) + if bond["donor_resnm"]!="LIG" and (bond["donor_index"],bond["acceptor_index"]) in [(k[0],k[3]) for k,v in self.hbonds_for_drawing.items()]: + with open('hbond_'+bond["donor_resnm"]+"_"+str(bond["donor_resid"])+"_"+bond["acceptor_atom"]+"_"+str(traj)+".csv","wb") as outfile: + hwriter = csv.writer(outfile, delimiter=',') + for time in self.hbonds_timesteps[traj]: + result = 0 + for x in self.hbonds[traj]: + if (x[0]==time and x["donor_index"]==bond["donor_index"]): + result = result + 1 + hwriter.writerow([time,result]) + os.chdir("../../") diff --git a/lintools/lintools.py b/lintools/lintools.py index 21e2ed7..c5a1d8c 100755 --- a/lintools/lintools.py +++ b/lintools/lintools.py @@ -38,13 +38,12 @@ class Lintools(object): * end_frame * - end frame(s) for trajectory analysis (can be different for each trajectory) * skip * - number of frames to skip (can be different for each trajectory) * analysis_cutoff * - a fraction of time a residue has to fullfil the analysis parameters for (default - 0.3) - * sasa * - set this to 1 to turn on solvent accessible surface area calculation (currently only works across whole trajectory) * diagram_type * - string of the selected diagram type (e.g. "amino" or "clocks") * output_name * - name of the folder with results and the final SVG file """ - __version__ = "06.2018" - def __init__(self,topology,trajectory,mol_file,ligand,offset,cutoff,start_frame,end_frame,skip,analysis_cutoff,sasa,diagram_type,output_name,cfg): + __version__ = "09.2016" + def __init__(self,topology,trajectory,mol_file,ligand,offset,cutoff,start_frame,end_frame,skip,analysis_cutoff,diagram_type,output_name,cfg): """Defines the input variables.""" self.topology = os.path.abspath(topology) try: @@ -69,7 +68,6 @@ def __init__(self,topology,trajectory,mol_file,ligand,offset,cutoff,start_frame, self.end = end_frame self.skip = skip self.analysis_cutoff = analysis_cutoff - self.sasa = sasa self.diagram_type = diagram_type self.output_name = output_name def data_input_and_res_time_analysis(self): @@ -93,17 +91,16 @@ def analysis_of_prot_lig_interactions(self): """ self.hbonds = HBonds(self.topol_data,self.trajectory,self.start,self.end,self.skip,self.analysis_cutoff,distance=3) self.pistacking = PiStacking(self.topol_data,self.trajectory,self.start,self.end,self.skip, self.analysis_cutoff) - if self.sasa==1: - self.sasa = SASA(self.topol_data,self.trajectory) + self.sasa = SASA(self.topol_data,self.trajectory) self.lig_descr = LigDescr(self.topol_data) if self.trajectory!=[]: self.rmsf = RMSF_measurements(self.topol_data,self.topology,self.trajectory,self.ligand,self.start,self.end,self.skip) self.salt_bridges = SaltBridges(self.topol_data,self.trajectory,self.lig_descr,self.start,self.end,self.skip,self.analysis_cutoff) - def plot_residues(self): + def plot_residues(self, colormap): """ Calls Plot() that plots the residues with the required diagram_type. """ - self.plots = Plots(self.topol_data,self.diagram_type) + self.plots = Plots(self.topol_data, self.diagram_type, colormap) def draw_figure(self,data_for_color=None, data_for_size=None, data_for_clouds=None, rot_bonds=None, color_for_clouds="Blues", color_type_color="viridis"): """ Draws molecule through Molecule() and then puts the final figure together with @@ -149,7 +146,6 @@ def write_config_file(self, cfg): 'offset': self.offset, 'distance cutoff': self.cutoff, 'analysis cutoff': self.analysis_cutoff, - 'sasa': self.sasa, 'diagram type': self.diagram_type, 'output name': self.output_name}, 'representation':{ @@ -188,7 +184,6 @@ def remove_files(self): parser.add_argument('-o', '--outname', dest = "output_name", help='Name for output folder and file') parser.add_argument('-c', '--cutoff', dest = "cutoff", default = 3.5, help='Cutoff distance in angstroms.') parser.add_argument('-ac', '--analysis_cutoff', dest = "analysis_cutoff", default=0.3, help='Analysis cutoff - a feature has to appear for at least a fraction of the simulation to be plotted.') - parser.add_argument('-sasa', '--sasa', dest = "sasa", default = 0, help='Perform solvent accessible surface area (sasa) calculation') args = parser.parse_args() @@ -197,7 +192,7 @@ def remove_files(self): if args.config!=None: - #If config file exists, args.will be ingnored + #If config file exists, args.will be ignored print "#####################################################################" print "WARNING" print "The arguments from command line will be ignored," @@ -209,7 +204,7 @@ def remove_files(self): cfg = yaml.load(ymlfile) ## Check config file input - mainly topology and output file, also handling bad input - lintools = Lintools(cfg['input']['topology'],cfg['input']['trajectory'],cfg['input']['mol file'],cfg['input']['ligand'],cfg['input']['offset'],float(cfg['input']['distance cutoff']),cfg['input']['traj start'],cfg['input']['traj end'],cfg['input']['traj skip'],cfg['input']['analysis cutoff'],cfg['input']['sasa'],cfg['input']['diagram type'],cfg['input']['output name'],cfg=True) + lintools = Lintools(cfg['input']['topology'],cfg['input']['trajectory'],cfg['input']['mol file'],cfg['input']['ligand'],cfg['input']['offset'],float(cfg['input']['distance cutoff']),cfg['input']['traj start'],cfg['input']['traj end'],cfg['input']['traj skip'],cfg['input']['analysis cutoff'],cfg['input']['diagram type'],cfg['input']['output name'],cfg=True) lintools.save_files() lintools.data_input_and_res_time_analysis() lintools.analysis_of_prot_lig_interactions() @@ -281,7 +276,7 @@ def find_diagram_type(): ligand_name = find_ligand_name() diagram_type = find_diagram_type() - lintools = Lintools(args.topology,args.trajectory,None,ligand_name,0,args.cutoff,args.start_frame,args.end_frame,args.skip,float(args.analysis_cutoff),args.sasa,diagram_type,args.output_name,cfg=False) + lintools = Lintools(args.topology,args.trajectory,None,ligand_name,0,args.cutoff,args.start_frame,args.end_frame,args.skip,float(args.analysis_cutoff),diagram_type,args.output_name,cfg=False) lintools.save_files() lintools.data_input_and_res_time_analysis() lintools.analysis_of_prot_lig_interactions() diff --git a/lintools/plots.py b/lintools/plots.py index 5a10585..36943e7 100755 --- a/lintools/plots.py +++ b/lintools/plots.py @@ -23,21 +23,28 @@ class Plots(object): """ __version__ = "09.2016" matplotlib.rcParams['svg.fonttype'] = 'none' - matplotlib.rcParams['font.weight']=900 + matplotlib.rcParams['font.weight'] = 900 matplotlib.rcParams['text.usetex'] = False matplotlib.rcParams['patch.linewidth'] = 0 - def __init__(self, topology_data_object,diagram_type,colormap='summer'): + def __init__(self, topology_data_object, diagram_type, colormap='summer'): self.topology_data = topology_data_object - self.colors_amino_acids = {"acidic":"#D9774B", "basic":"#889DCC", - "aromatic":"#9FC74A", "polar":"#D06AC1", - "hydrophobic":"#6AC297","lipids":"#ffff99", - "water":"turquoise","ions":"gold"} - self.amino_acids = {"ASP":"acidic","GLU":"acidic","LYS":"basic","ARG":"basic", - "PHE":"aromatic","TYR":"aromatic","TRP":"aromatic","SER":"polar", - "THR":"polar","ASN":"polar","GLN":"polar","CYS":"polar", - "HIS":"polar","ALA":"hydrophobic","VAL":"hydrophobic", - "ILE":"hydrophobic","LEU":"hydrophobic","MET":"hydrophobic","GLY":"hydrophobic","PRO":"hydrophobic", - "PC":"lipids","HOH":"water","SOL":"water"} + self.colors_amino_acids = {"acidic": "#D9774B", "basic": "#889DCC", + "aromatic": "#9FC74A", "polar": "#D06AC1", + "hydrophobic": "#6AC297", + "lipids": "#ffff99", "water": "turquoise", + "ions": "gold"} + self.amino_acids = {"ASP": "acidic","GLU": "acidic","LYS": "basic", + "ARG": "basic", "PHE": "aromatic", + "TYR": "aromatic", "TRP": "aromatic", + "SER": "polar", "THR": "polar", "ASN": "polar", + "GLN": "polar", "CYS": "polar", "HIS": "polar", + "ALA": "hydrophobic", "VAL": "hydrophobic", + "ILE": "hydrophobic", "LEU": "hydrophobic", + "MET": "hydrophobic", "GLY": "hydrophobic", + "PRO": "hydrophobic", "PC": "lipids", + "HOH": "water", "SOL": "water"} + # Let's try to fix this so that default config works + self.colormap = colormap if diagram_type == "amino": self.plot_amino_diagrams() if diagram_type == "domains": From 0430de5f5487e55bccbc23512a8c7c66440014c5 Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:45:56 +0100 Subject: [PATCH 09/11] Delete hbonds.py --- lintools/hbonds.py | 246 --------------------------------------------- 1 file changed, 246 deletions(-) delete mode 100644 lintools/hbonds.py diff --git a/lintools/hbonds.py b/lintools/hbonds.py deleted file mode 100644 index 81990ff..0000000 --- a/lintools/hbonds.py +++ /dev/null @@ -1,246 +0,0 @@ -from collections import defaultdict -import csv -import MDAnalysis -from MDAnalysis.analysis import hbonds -from timeit import default_timer as timer -from rdkit import Chem -import rdkit -import numpy as np -import os - -class HBonds(object): - """ - This module analyses hydrogen bonds the ligand forms with the protein (version "09.2016"). - The donor and acceptor atoms in ligand molecule are detected by RDKit, then the bonds are - detected by MDAnalysis hydrogen bonding analysis and counted by time (how many total bonds - per frame) and by type (fraction of time per each hydrogen bond). Information about the - total count of hydrogen bonds over time is provided in a data file (CSV format). Each hydro- - gen bond is then analysed to decide whether to plot it in the final image. - - Takes: - * topology_data_object * - information about the system (lintools.Data object) - * trajectory * - list of trajectories - * start_frame_num * - list^^ of frame numbers for start of analysis (Opt) - * end_frame_num * - list^^ of frame numbers for end of analysis (Opt) - * skip * - list^^ of numbers of how many frames should be skipped for this analysis (Opt) - * distance * - distance between hydrogen bond donor and acceptor atoms in angstroms - * analysis_cutoff * - (user-defined) fraction of time a hydrogen bond has to be - present for to be plotted (default - 0.3). It is multiplied by number of trajectories - - ^^ The reason these values are lists is because several trajectories can be submitted for - analysis and different values could be required for each simulation. Therefore, similarly - as with trajectories, start, end and skip variables are submitted as lists with values - corresponding for each trajectory. - - Example: trajectory = ["1.xtc","2.xtc"] #Both are 1000 frames, but the user only wants to - analyse second half the the second trajectory - start = [0(for the first traj),500(for the second traj)] - Other values can be left as default. - """ - __version__ = "06.2018" - def __init__(self, topology_data_object, trajectory, start_frame_num=None,end_frame_num=None,skip=None,analysis_cutoff=0.3,distance=3): - self.hbonds = None - self.HDonorSmarts = Chem.MolFromSmarts('[$([N;!H0;v3]),$([N;!H0;+1;v4]),$([O,S;H1;+0]),$([n;H1;+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) - self.donors = [] - self.acceptors = [] - self.topology_data = topology_data_object - self.trajectory = trajectory - self.hbonds = {} - self.hbonds_timesteps={} - self.hbonds_by_time = {} - self.hbonds_by_type = {} - self.hbonds_timesteps_by_type = {} - self.start_frame_num = start_frame_num - self.end_frame_num = end_frame_num - self.skip = skip - self.find_donors_and_acceptors_in_ligand() - if len(trajectory)>0: - self.analyse_hydrogen_bonds_traj(distance) - else: - self.analyse_hydrogen_bonds_topology(distance) - self.determine_hbonds_for_drawing(analysis_cutoff) - self.write_output_files() - def find_donors_and_acceptors_in_ligand(self): - """ - 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. - """ - 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]]) - def analyse_hydrogen_bonds_traj(self,distance=3): - """ - MDAnalysis.analysis.hbonds module is used to analyse hydrogen bonds formed between protein - and ligand for each submitted trajectory. The hydrogen bonds are then counted by total value - per frame (count_by_time), as well as obtaining the frequency of each individual hydrogen - bond (count_by_type). - - Format of h.table below is time, donor_index, acceptor_index, donor_resnm, donor_resid, donor_atom, acceptor_resnm, acceptor_resid, acceptor_atom, distance, angle. - count_by_type should return atom indices, residue names, residue numbers (for donors and acceptors) and the fraction of the total time, but actually format is:- - - donor_atom, acceptor_atom, donor_atom_name, acceptor_atom_name, donor_resname, donor_resid, acceptor_resname, acceptor_resid, time. - - - Takes: - * distance * - distance between hydrogen bond donor and acceptor in angstroms - Output: - * self.hbonds * - array with information about all detected hydrogen bonds - * self.hbonds_by_time * - total hbond number by frame - * self.hbonds_by_type * - frequency of each hydrogen bond - - """ - i=0 - for traj in self.trajectory: - self.topology_data.load_trajectory(traj) - start = timer() - h = MDAnalysis.analysis.hbonds.HydrogenBondAnalysis(self.topology_data.universe,'(segid '+str(self.topology_data.universe.ligand.segids[0])+' and resid '+str(self.topology_data.universe.ligand.resids[0])+')',"protein",distance=3,acceptors=self.acceptors,donors=self.donors,start=self.start_frame_num[i],stop=self.end_frame_num[i],step=self.skip[i]) - h.run() - h.generate_table() - end = timer() - self.hbonds[i]=h.table - self.hbonds_timesteps[i] =h.timesteps - self.hbonds_by_time[i] = h.count_by_time() - self.hbonds_by_type[i] = self.count_by_type(h.table,h.timesteps) - self.hbonds_timesteps_by_type[i] = h.timesteps_by_type() - i+=1 - - def count_by_type(self,table,timesteps): - """Count how many times each individual hydrogen bonds occured throughout the simulation. - Returns numpy array.""" - hbonds = defaultdict(int) - for contact in table: - #count by residue name not by protein ring - pkey = (contact.donor_index,contact.acceptor_index,contact.donor_atom, contact.acceptor_atom,contact.donor_resnm,contact.donor_resid, contact.acceptor_resnm,contact.acceptor_resid) - hbonds[pkey]+=1 - dtype = [("donor_index",int),("acceptor_index",int),("donor_atom","|U4"),("acceptor_atom","|U4"),("donor_resnm","|U8"),("donor_resid","|U8"),("acceptor_resnm","|U8"),("acceptor_resid","|U8"),("frequency",float) ] - out = np.empty((len(hbonds),),dtype=dtype) - tsteps = float(len(timesteps)) - for cursor,(key,count) in enumerate(hbonds.iteritems()): - out[cursor] = key + (count / tsteps,) - return out.view(np.recarray) - - def analyse_hydrogen_bonds_topology(self,distance=3): - #This is the routine that is called if only a single coordinate file is requested. - """ - MDAnalysis.analysis.hbonds module is used to analyse hydrogen bonds formed between protein - and ligand for each submitted trajectory. The hydrogen bonds are then counted by total value - per frame (count_by_time), as well as obtaining the frequency of each individual hydrogen - bond (count_by_type). This function is used in case no trajectory has been submitted for analysis. - - Takes: - * distance * - distance between hydrogen bond donor and acceptor in angstroms - Output: - * self.hbonds * - array with information about all detected hydrogen bonds - * self.hbonds_by_time * - total hbond number by frame - * self.hbonds_by_type * - frequency of each hydrogen bond - """ - - h = MDAnalysis.analysis.hbonds.HydrogenBondAnalysis(self.topology_data.universe,'(segid '+str(self.topology_data.universe.ligand.segids[0])+' and resid '+str(self.topology_data.universe.ligand.resids[0])+')',"protein",distance=3,acceptors=self.acceptors,donors=self.donors) - h.run() - h.generate_table() - self.hbonds[0]=h.table - self.hbonds_by_time[0] = h.count_by_time() - self.hbonds_by_type[0] = h.count_by_type() - - def determine_hbonds_for_drawing(self, analysis_cutoff): - """ - Since plotting all hydrogen bonds could lead to a messy plot, a cutoff has to be imple- - mented. In this function the frequency of each hydrogen bond is summated and the total - compared against analysis cutoff - a fraction multiplied by trajectory count. Those - hydrogen bonds that are present for longer than analysis cutoff will be plotted in the - final plot. - - Takes: - * analysis_cutoff * - (user-defined) fraction of time a hydrogen bond has to be - present for to be plotted (default - 0.3). It is multiplied by number of trajectories - Output: - * frequency * - dictionary of hydrogen bond donor-acceptor indices and frequencies - These hydrogen bonds will be plotted in the final image. - - """ - self.frequency = defaultdict(int) - for traj in self.hbonds_by_type: - for bond in self.hbonds_by_type[traj]: - # frequency[(residue_atom_idx,ligand_atom_name,residue_atom_name)]=frequency - # residue atom name will be used to determine if hydrogen bond is interacting with a sidechain or bakcbone - # Following looks problematic for the trajectory subroutine as LD's routine does not return indices..? - if bond["donor_resnm"]!="LIG": - self.frequency[(bond["donor_index"],bond["acceptor_atom"],bond["donor_atom"],bond["acceptor_index"])] += bond["frequency"] - #check whether ligand is donor or acceptor - else: - self.frequency[(bond["acceptor_index"],bond["donor_atom"],bond["acceptor_atom"],bond["donor_index"])] += bond["frequency"] - - #Add the frequency counts - self.frequency = {i:self.frequency[i] for i in self.frequency if self.frequency[i]>(int(len(self.trajectory))*analysis_cutoff)} - - - #change the ligand atomname to a heavy atom - required for plot since only heavy atoms shown in final image - self.hbonds_for_drawing = {} - for bond in self.frequency: - atomname = bond[1] - if atomname.startswith("O",0) or atomname.startswith("N",0): - lig_atom=atomname - else: - atomindex = [index for index,atom in enumerate(self.topology_data.universe.ligand.atoms) if atom.name==atomname][0] - rdkit_atom = self.topology_data.mol.GetAtomWithIdx(atomindex) - for neigh in rdkit_atom.GetNeighbors(): - neigh_atom_id = neigh.GetIdx() - lig_atom = [atom.name for index,atom in enumerate(self.topology_data.universe.ligand.atoms) if index==neigh_atom_id][0] - self.hbonds_for_drawing[(bond[0],lig_atom,bond[2],bond[3])]=self.frequency[bond] - - def write_output_files(self): - #This is probably not the most efficient code, but its probably easier to read (PCB). - #Note that total may be more than the apparent sum because the total is the total hbonds for each time, whereas we are only dumping out individual files for ones where - #there is greater a certain % of time occurance. - - """ - The total hydrogen bond count per frame is provided as CSV output file. - Each trajectory has a separate file. - """ - os.mkdir("analysis") - os.chdir("analysis") - os.mkdir("hydrogen_bonds") - os.chdir("hydrogen_bonds") - for traj in range(len(self.trajectory)): - with open('hbonds_data_total_'+str(traj)+'.csv', 'wb') as outfile: - hwriter = csv.writer(outfile, delimiter=',') - for time in self.hbonds_by_time[traj]: - hwriter.writerow([time[0],time[1]]) - for bond in self.hbonds_by_type[traj]: - if bond["donor_resnm"]=="LIG" and (bond["acceptor_index"],bond["donor_index"]) in [(k[0],k[3]) for k,v in self.hbonds_for_drawing.items()]: - with open('hbond_'+bond["acceptor_resnm"]+"_"+str(bond["acceptor_resid"])+"_"+bond["donor_atom"]+"_"+str(traj)+".csv","wb") as outfile: - hwriter = csv.writer(outfile, delimiter=',') - for time in self.hbonds_timesteps[traj]: - result = 0 - for x in self.hbonds[traj]: - if (x[0]==time and x["acceptor_index"]==bond["acceptor_index"]): - result = result + 1 - hwriter.writerow([time,result]) - if bond["donor_resnm"]!="LIG" and (bond["donor_index"],bond["acceptor_index"]) in [(k[0],k[3]) for k,v in self.hbonds_for_drawing.items()]: - with open('hbond_'+bond["donor_resnm"]+"_"+str(bond["donor_resid"])+"_"+bond["acceptor_atom"]+"_"+str(traj)+".csv","wb") as outfile: - hwriter = csv.writer(outfile, delimiter=',') - for time in self.hbonds_timesteps[traj]: - result = 0 - for x in self.hbonds[traj]: - if (x[0]==time and x["donor_index"]==bond["donor_index"]): - result = result + 1 - hwriter.writerow([time,result]) - os.chdir("../../") From 40a29d90eba20fee3292fa492573bdaefa063dbb Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:49:01 +0100 Subject: [PATCH 10/11] Added ability to change colormap from 'summer'. Added self.colormap = colormap to Plots(object) class. --- lintools/plots.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lintools/plots.py b/lintools/plots.py index 36943e7..72881b5 100755 --- a/lintools/plots.py +++ b/lintools/plots.py @@ -4,7 +4,6 @@ from matplotlib import pylab import numpy - class Plots(object): """ This module plots the residue data. From 931873cf8a3fe9d6334e3e6751a1afa89b59015d Mon Sep 17 00:00:00 2001 From: ShadSBCB Date: Tue, 19 Jun 2018 15:52:00 +0100 Subject: [PATCH 11/11] Update lintools.py Added self.colormap to plot_residues() of Lintools (lintools.py) --- lintools/lintools.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lintools/lintools.py b/lintools/lintools.py index c5a1d8c..34c77ce 100755 --- a/lintools/lintools.py +++ b/lintools/lintools.py @@ -1,4 +1,3 @@ - from argparse import ArgumentParser import os import shutil @@ -169,7 +168,6 @@ def remove_files(self): if os.path.isfile(f)==True: os.remove(f) - if __name__ == '__main__': ################################################################################################################# @@ -189,8 +187,6 @@ def remove_files(self): #################################################################################################################### - - if args.config!=None: #If config file exists, args.will be ignored print "#####################################################################"