Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

#$Id: autodockNavigator.py 282 2016-12-05 01:15:03Z sarkiss $ 

"Virtual Screenening Controller" 

from vsModel import VSModel 

from dirNavigator import DirNavigator 

import os, wx, StringIO, sys 

from time import strftime 

import  wx.lib.scrolledpanel as scrolled 

from MolKit.protein import Protein, Chain, Residue 

 

class MolTreeSplitMacro(wx.SplitterWindow): 

    def __init__(self, parent): 

        wx.SplitterWindow.__init__(self, parent, -1,style = wx.SP_LIVE_UPDATE) 

        self.ligandTree = DirNavigator(self) 

        self.macromoleculeTree = DirNavigator(self) 

        self.SplitHorizontally(self.ligandTree, self.macromoleculeTree) 

        if wx.Platform ==  '__WXGTK__':#on mac bottom panel takes the whole space 

            self.SetSashGravity(0.5) 

 

    def AppendLigand(self, name, select=True): 

        "Adds a ligand to the tree" 

        fileName = name+'.pdbqt' 

        fullPath = os.path.join(self.ligandTree.basePath, fileName) 

        if self.ligandTree.treeDict.has_key(fullPath): 

            item = self.ligandTree.treeDict[fullPath] 

        else: 

            root = self.ligandTree.tree.RootItem 

            item = self.ligandTree.tree.AppendItem(root, fileName) 

            self.ligandTree.tree.SetItemImage(item, self.ligandTree.molIconIndex, wx.TreeItemIcon_Normal) 

            self.ligandTree.tree.SetPyData(item, fullPath) 

            self.ligandTree.treeDict[fullPath] = item 

        #self.ligandTree.tree.UnselectAll() 

        if select == True: 

            self.ligandTree.tree.SelectItem(item) 

 

class AutoDockNavigator: 

    def __init__(self, frame): 

        self.vsModel = VSModel() 

        self.autodockTree = MolTreeSplitMacro(frame.navigator) 

        self.autodockTree.ligandTree.BuildTree(self.vsModel.ligandsFolder) 

        self.autodockTree.macromoleculeTree.BuildTree(self.vsModel.macromoleculesFolder) 

        self.autodockTree.macromoleculeTree.tree.UnselectAll() 

        from icons import adtPNG 

        frame.navigator.AddPage(self.autodockTree, 'AutoDock', bitmap=adtPNG) 

        self.frame = frame 

        frame.vsModel = self.vsModel 

#        self.autodockTree.Bind(wx.EVT_SHOW, self.SetActive) 

#         

#    def SetActive(self, event): 

#        "This method is bound to wx.EVT_SHOW, i.e., invoked when this page is shown"     

#        try: 

#            self.autodockTree.ligandTree.OnRefresh(None) 

#        except: #might be called on exit; just to be on a safe side. 

#            pass 

 

    def AddLigand(self, mol, charges_to_add='gasteiger', select=True, use_=False): 

        "Creates ligand pdbqt, updates Ligands tree under Navigator > AutoDock  and Ligands table under View > Tables" 

        mol.name = mol.name.replace(' ', '_') 

        mol.name = mol.name.replace('\t', '_') 

        mol_molDict = self.frame.TryCommand(self.vsModel.PrepareLigandMol, mol, charges_to_add=charges_to_add, use_=use_) 

        if mol_molDict: 

            mol, molDict = mol_molDict[0], mol_molDict[1] 

        else: 

            return None 

        self.autodockTree.AppendLigand(mol.name, select=select) 

        #database part 

        autodock_elements = "" 

        for item in molDict['autodock_element']: 

            autodock_elements += str(item) +" " 

        args = (mol.name, len(mol.allAtoms), strftime("%Y.%m.%d %H:%M:%S"), molDict['TORSDOF'], autodock_elements) 

        if not hasattr(self.frame.dbView, 'ligandsTable'): 

            self.frame.dbView.Activate(None) 

        self.frame.dbView.ligandsTable.AddItem(args) 

        return mol 

 

    def AddMacromolecule(self, mol): 

        "Creates pdbqt for macromolecule and updates Macromolecules tree under Navigator > AutoDock." 

        mol = self.CleanHetatms(mol) 

        if not mol: return 

        mol = self.SelectAlternate(mol) 

        if not mol: return 

        RPO = self.frame.TryCommand(self.vsModel.PrepareReceptorMol, mol) 

        self.RefreshMacroolecules() 

        item = self.autodockTree.macromoleculeTree.treeDict[self.vsModel.receptorFolder] 

        self.autodockTree.macromoleculeTree.tree.SelectItem(item) 

        if RPO: 

            return self.vsModel.macromoleculePath 

        else: 

            return None 

 

    def MakeFlexResidues(self, flexRes): 

        mol = self.SelectAlternate(flexRes[0].top) 

        if not mol: return 

        dlg = wx.ProgressDialog("Please Wait...", "Creating Flexible Residues...", 

                               parent=self.frame, style = wx.PD_APP_MODAL) 

        if mol != flexRes[0].top: 

            fRes = [] 

            for res in flexRes: 

                name = res.full_name() 

                fRes = mol.NodesFromName(name) 

            flexRes = fRes 

            self.frame.TryCommand(mol.buildBondsByDistance) 

        self.frame.TryCommand(self.vsModel.PrepareFlexReceptor, flexRes) 

        dlg.Destroy() 

        self.RefreshMacroolecules() 

 

    def RefreshMacroolecules(self): 

        self.autodockTree.macromoleculeTree.OnRefresh(None) 

 

        #self.autodockTree.macromoleculeTree.tree.UnselectAll()         

#TODO: Replace wx.SplitterWindow with aui.notbook splited vertically 

 

    def CleanHetatms(self, mol): 

        """Allow users to choose what to do with HETATMs""" 

        hetRes = [] 

        hetatms = [atom for atom in mol.chains.residues.hetatm ] 

        for item in hetatms: 

            parent = item.parent 

            if len(parent.children) > 1: #for waters and other single atom residues in pdb 

                if len(parent.parent.children) > 3: continue #when hetatms are part of a bigger chain, keep it 

                if not parent in hetRes: 

                    if parent.type in ["WAT", "HOH"]: continue 

                    hetRes.append(parent) 

 

        if hetRes: 

            #ask user to select what to do with HETATMS 

            dlg = SelectHetDialog(self.frame, hetRes) 

            self.dlg = dlg #used for testing         

            if dlg.ShowModal() != wx.ID_OK: 

                dlg.Destroy() 

                return 

            for index, item in enumerate(dlg.boxes): 

                fate = item.GetCurrentSelection() 

                if fate == 1: #"Remove" 

                    hetRes[index].parent.remove(hetRes[index]) 

                    for atom in hetRes[index].atoms: 

                        hetRes[index].top.allAtoms.remove(atom) 

                    #mol.chains.residues.remove(hetRes[index]) was not working 

                elif fate == 2: #"Remove and Save As pdbqt": 

                    parser = hetRes[index].top.parser #hold on to parser otherwise, after adopt below it's gone. This is needed in AddLigand later.  

                    hetRes[index].parent.residues.remove(hetRes[index]) 

                    for atom in hetRes[index].atoms: 

                        hetRes[index].top.allAtoms.remove(atom) 

                    ligand = Protein() 

                    ligand.name = hetRes[index].name 

                    chain= Chain() 

                    chain.adopt(hetRes[index]) 

                    ligand.adopt(chain) 

                    ligand.allAtoms = hetRes[index].atoms 

                    ligand.allAtoms.top = ligand 

                    ligand.parser =  parser 

                    self.AddLigand(ligand, select=False) 

            dlg.Destroy() 

        return mol 

 

    def SelectAlternate(self, mol): 

        """Checks to see if there are alternate positions present in mol.  

        If there are atoms with alternate positions, then show SelectAltDialog which  

        allows users to select alternate conformation to retain.  

        """ 

        mol.name = mol.name.replace(' ', '_') 

        mol.name = mol.name.replace('\t', '_') 

        #check for alt conformations 

        altCounter = [] 

        altDict = {} 

        altDictIndexes = {} 

        counter = 0 

        for index, item in enumerate(mol.allAtoms.altname):#handles alternates 

            if item: 

                name = mol.allAtoms[index].parent.name 

                if mol.allAtoms[index].parent.type in ["WAT", "HOH"]: continue 

                if altDict.has_key(name): 

                    altDict[name].append(item) 

                    altDictIndexes[name].append(index) 

                else: 

                    altDict[name] = [item] 

                    altDictIndexes[name] = [index] 

                    altCounter.append(name) 

        if altCounter: 

            #ask user to select conformation 

            dlg = SelectAltDialog(self.frame, altDict, altCounter) 

            self.dlg = dlg #used for testing         

            if dlg.ShowModal() != wx.ID_OK: 

                dlg.Destroy() 

                return 

 

            remove_atoms = [] 

            for index, item in enumerate(dlg.boxes): 

                name = altCounter[index] 

                altName = item.GetValue() 

                for atomIndex in altDictIndexes[name]: 

                    if mol.allAtoms[atomIndex].altname != altName: 

                        atom = mol.allAtoms[atomIndex] 

                        for bond in atom.bonds: 

                            if bond.atom1 != atom: 

                                del bond.atom1.bonds[bond.atom1.bonds.index(bond)] 

                            else: 

                                del bond.atom2.bonds[bond.atom2.bonds.index(bond)] 

                        parent = atom.parent 

                        i = parent.atoms.index(atom) 

                        parent.atoms.__delitem__(i) 

                        remove_atoms.append(atom) 

                    else: 

                        atom = mol.allAtoms[atomIndex] 

                        atom.altname = None 

                        atom.name = atom.name.replace("@"+altName,"") 

            for atom in remove_atoms: 

                mol.allAtoms.remove(atom) 

            dlg.Destroy() 

        return mol 

 

class SelectHetDialog(wx.Dialog): 

    "Select Dialog for HETATM" 

    def __init__(self, parent, hetRes): 

 

        pre = wx.PreDialog() 

        pre.Create(parent, -1, "Make Macromolecule - HETATM") 

        # This next step is the most important, it turns this Python 

        # object into the real wrapper of the dialog (instead of pre) 

        # as far as the wxPython extension is concerned. 

        self.PostCreate(pre) 

        # This extra style can be set after the UI object has been created. 

        if 'wxMac' in wx.PlatformInfo: 

            self.SetExtraStyle(wx.DIALOG_EX_METAL) 

        self.boxes = [] #this list stores Combo Boxes 

        # Now continue with the normal construction of the dialog 

        # contents 

        sPanel = scrolled.ScrolledPanel(self) 

        mainSizer = wx.BoxSizer(wx.VERTICAL) 

        sizer = wx.BoxSizer(wx.VERTICAL) 

        label = wx.StaticText(sPanel, -1, """ How to handle non-standard residues (HETATM) :         

         

   - Keep (include in the final pdbqt). 

   - Remove (remove before making pdbqt). 

   - Remove and Save As (ligand) pdbqt. 

 

Press Enter to accept these defaults.""") 

        sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) 

 

        fate = "Keep" 

        if len(hetRes) < 5: 

            fate = "Remove and Save As pdbqt" 

        for res in hetRes: 

            box = wx.BoxSizer(wx.HORIZONTAL) 

            #add residue here  

            label = wx.StaticText(sPanel, -1, res.full_name()) 

            box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 10) 

            cb = wx.Choice(sPanel, -1, 

                             choices = ["Keep", "Remove", "Remove and Save As pdbqt"], 

                             ) 

            if len(res.atoms) < 4: # for HOH 

                fate = "Remove" 

            cb.SetStringSelection(fate) 

            self.boxes.append(cb) 

            box.Add(cb, 1, wx.ALIGN_CENTRE|wx.ALL, 2) 

            sizer.Add(box, 0, wx.GROW|wx.ALIGN_LEFT|wx.RIGHT|wx.LEFT, 5) 

        sPanel.SetSizer( sizer ) 

 

        line = wx.StaticLine(sPanel, -1, size=(20,-1), style=wx.LI_HORIZONTAL) 

        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) 

        btnsizer = wx.StdDialogButtonSizer() 

        btn = wx.Button(sPanel, wx.ID_OK) 

        btn.SetDefault() 

        btnsizer.AddButton(btn) 

        btn = wx.Button(sPanel, wx.ID_CANCEL) 

        btnsizer.AddButton(btn) 

        btnsizer.Realize() 

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 

        mainSizer.Add(sPanel, 2, wx.EXPAND) 

        self.SetSizer(mainSizer) 

        sizer.Fit(self) 

        if len(hetRes) > 10: 

            sPanel.SetAutoLayout(1) 

            sPanel.SetupScrolling(scroll_x=False) 

 

class SelectAltDialog(wx.Dialog): 

    "Select Conformation Dialog" 

    def __init__(self, parent, altDict, altCounter): 

 

        pre = wx.PreDialog() 

        pre.Create(parent, -1, "Select Conformation") 

        # This next step is the most important, it turns this Python 

        # object into the real wrapper of the dialog (instead of pre) 

        # as far as the wxPython extension is concerned. 

        self.PostCreate(pre) 

        # This extra style can be set after the UI object has been created. 

        if 'wxMac' in wx.PlatformInfo: 

            self.SetExtraStyle(wx.DIALOG_EX_METAL) 

        self.boxes = [] #this list stores Combo Boxes 

        # Now continue with the normal construction of the dialog 

        # contents 

        sPanel = scrolled.ScrolledPanel(self) 

        mainSizer = wx.BoxSizer(wx.VERTICAL) 

        sizer = wx.BoxSizer(wx.VERTICAL) 

        label = wx.StaticText(sPanel, -1, """ Select alternate conformations. 

 

Press Enter to accept these defaults.""") 

        sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) 

        for name in altCounter: 

            box = wx.BoxSizer(wx.HORIZONTAL) 

            #add residue here  

            label = wx.StaticText(sPanel, -1, name) 

            box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 2) 

            cb = wx.ComboBox(sPanel, 500, altDict[name][0], (90, 50), 

                             (160, -1), list( set(altDict[name]) ), 

                             wx.CB_DROPDOWN | wx.CB_READONLY | wx.CB_SORT ) 

            self.boxes.append(cb) 

            box.Add(cb, 1, wx.ALIGN_CENTRE|wx.ALL, 2) 

            sizer.Add(box, 0, wx.GROW|wx.ALIGN_LEFT|wx.RIGHT|wx.LEFT, 5) 

        sPanel.SetSizer( sizer ) 

        line = wx.StaticLine(sPanel, -1, size=(20,-1), style=wx.LI_HORIZONTAL) 

        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) 

        btnsizer = wx.StdDialogButtonSizer() 

        btn = wx.Button(sPanel, wx.ID_OK) 

        btn.SetDefault() 

        btnsizer.AddButton(btn) 

        btn = wx.Button(sPanel, wx.ID_CANCEL) 

        btnsizer.AddButton(btn) 

        btnsizer.Realize() 

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 

        mainSizer.Add(sPanel, 2, wx.EXPAND) 

        self.SetSizer(mainSizer) 

        sizer.Fit(self) 

        if len(altCounter) > 10: 

            sPanel.SetAutoLayout(1) 

            sPanel.SetupScrolling(scroll_x=False)