1 | #!/usr/bin/env python
|
---|
2 | # gui_example.py
|
---|
3 | #
|
---|
4 | # Copyright 2007 Frank Eisenmenger, U.H.E. Hansmann,
|
---|
5 | # Jan H. Meinke, Sandipan Mohanty
|
---|
6 | #
|
---|
7 | # Display the Calpha trace and energy of a Monte Carlo simulation of a protein using Qt4.
|
---|
8 | import sys
|
---|
9 | sys.path.append("../../")
|
---|
10 |
|
---|
11 | import universe
|
---|
12 | import protein
|
---|
13 | import algorithms
|
---|
14 | from PyQt4 import QtCore, QtGui
|
---|
15 |
|
---|
16 | class CAlphaTraceWidget(QtGui.QWidget):
|
---|
17 | """Displays a 2D projection of the Calpha trace of the protein p. The
|
---|
18 | projection simply drops the z coordinate.
|
---|
19 | """
|
---|
20 | def __init__(self, protein, parent = 0):
|
---|
21 | """Initialize the widget.
|
---|
22 |
|
---|
23 | @param p the protein.Protein to be displayed
|
---|
24 | @param parent parent widget if applicable.
|
---|
25 | """
|
---|
26 | QtGui.QWidget.__init__(self)
|
---|
27 | self.protein = protein
|
---|
28 | self.calphaList = []
|
---|
29 | for a in self.protein.atoms():
|
---|
30 | if a.name().lower().strip() == 'ca':
|
---|
31 | self.calphaList.append(a)
|
---|
32 | self.centralAtom = self.calphaList[len(self.calphaList) / 2]
|
---|
33 |
|
---|
34 | def paintEvent(self, event):
|
---|
35 | """Draw little circles in the position of the Calpha atoms of p."""
|
---|
36 | diameter = 2
|
---|
37 | avgCalphaDistance = 4
|
---|
38 | zmin = -avgCalphaDistance * len(self.protein)
|
---|
39 | zmax = avgCalphaDistance * len(self.protein)
|
---|
40 |
|
---|
41 | self.calphaList.sort(self.atomZSort)
|
---|
42 |
|
---|
43 | painter = QtGui.QPainter(self)
|
---|
44 | painter.setRenderHint(QtGui.QPainter.Antialiasing, 1)
|
---|
45 | painter.translate(self.width() / 2, self.height() / 2)
|
---|
46 | xscale = 1.5 * self.width() / (avgCalphaDistance * len(self.protein))
|
---|
47 | yscale = 1.5 * self.height() / (avgCalphaDistance * len(self.protein))
|
---|
48 | scale = min(xscale, yscale)
|
---|
49 | painter.scale(scale, scale)
|
---|
50 | myGradient = QtGui.QRadialGradient(QtCore.QPointF(0, 0), 72)
|
---|
51 | myGradient.setColorAt(0, QtCore.Qt.white)
|
---|
52 | myGradient.setColorAt(1, QtCore.Qt.black)
|
---|
53 | painter.setBrush(QtGui.QBrush(myGradient))
|
---|
54 |
|
---|
55 | painter.translate(-self.centralAtom.position()[0], -self.centralAtom.position()[1])
|
---|
56 |
|
---|
57 |
|
---|
58 | for a in self.calphaList:
|
---|
59 | pos = a.position()
|
---|
60 | if pos[2] < zmin:
|
---|
61 | zscale = 0.1
|
---|
62 | elif pos[2] > zmax:
|
---|
63 | zscale = 5.0
|
---|
64 | else:
|
---|
65 | zscale = (pos[2] - zmin) / (zmax - zmin) * 4.9 + 0.1
|
---|
66 |
|
---|
67 | painter.save()
|
---|
68 | painter.translate(pos[0], pos[1])
|
---|
69 | painter.scale(zscale * diameter / 100, zscale * diameter / 100)
|
---|
70 | painter.drawEllipse(-50, -50, 100, 100)
|
---|
71 | painter.restore()
|
---|
72 |
|
---|
73 | painter.setWorldMatrixEnabled(0)
|
---|
74 | painter.drawText(5,self.height() -5 , QtCore.QString("E=%s" % self.protein.energy()))
|
---|
75 | painter.setWorldMatrixEnabled(1)
|
---|
76 |
|
---|
77 | def atomZSort(self, a, b):
|
---|
78 | za = a.position()[2]
|
---|
79 | zb = b.position()[2]
|
---|
80 | if za < zb:
|
---|
81 | return -1
|
---|
82 | elif za > zb:
|
---|
83 | return 1
|
---|
84 | else:
|
---|
85 | return 0
|
---|
86 |
|
---|
87 |
|
---|
88 | class WorkThread(QtCore.QThread):
|
---|
89 | def __init__(self, f):
|
---|
90 | QtCore.QThread.__init__(self)
|
---|
91 | self.function= f
|
---|
92 |
|
---|
93 | def run(self):
|
---|
94 | import os.path
|
---|
95 | from os import system
|
---|
96 | for i in range(0, 1000):
|
---|
97 | print "Performing sweep %s." % i
|
---|
98 | self.function()
|
---|
99 | try:
|
---|
100 | print os.path.getmtime('best.png'), os.path.getmtime('best.pdb')
|
---|
101 | if os.path.getmtime('best.png') < os.path.getmtime('best.pdb'):
|
---|
102 | os.system('pymol -c best.pml')
|
---|
103 | except os.error,e:
|
---|
104 | os.system('pymol -c best.pml')
|
---|
105 |
|
---|
106 | self.emit(QtCore.SIGNAL('finishedSweep(int)'), i)
|
---|
107 |
|
---|
108 | class TemperatureDial(QtGui.QDial):
|
---|
109 |
|
---|
110 | def __init__(self, Tmin, Tmax):
|
---|
111 | QtGui.QDial.__init__(self)
|
---|
112 | self.setMinimum(Tmin)
|
---|
113 | self.setMaximum(Tmax)
|
---|
114 | self.setNotchTarget(60)
|
---|
115 | self.setNotchesVisible(1)
|
---|
116 |
|
---|
117 | class MainWidget(QtGui.QWidget):
|
---|
118 |
|
---|
119 | def __init__(self):
|
---|
120 | QtGui.QWidget.__init__(self)
|
---|
121 | self.resize(640,480)
|
---|
122 | self.setWindowTitle("MC Simulation of Protein A (1BDD)")
|
---|
123 | topLevelLayout = QtGui.QHBoxLayout()
|
---|
124 | sideBarLayout = QtGui.QVBoxLayout()
|
---|
125 |
|
---|
126 | self.maxSweeps = 1000
|
---|
127 | self.myU = universe.Universe()
|
---|
128 | self.p = protein.Protein('../1bdd.seq')
|
---|
129 | self.myMC = algorithms.CanonicalMonteCarlo(self.myU, 1, self.maxSweeps)
|
---|
130 | self.myWorkThread = WorkThread(self.myMC.sweep)
|
---|
131 |
|
---|
132 | self.labelList = [['E', self.p.energy], ['R<sub>gyr</sub>', self.p.rgyr, 0], ['hb' ,self.p.hbond]]
|
---|
133 |
|
---|
134 | myCAlphaTraceWidget = CAlphaTraceWidget(self.p)
|
---|
135 | topLevelLayout.addWidget(myCAlphaTraceWidget, 1)
|
---|
136 |
|
---|
137 | self.createSideBar(sideBarLayout)
|
---|
138 | topLevelLayout.addLayout(sideBarLayout)
|
---|
139 |
|
---|
140 | self.setLayout(topLevelLayout)
|
---|
141 |
|
---|
142 | self.myWorkThread.start()
|
---|
143 |
|
---|
144 | self.connect(self.myWorkThread, QtCore.SIGNAL("finishedSweep(int)"), self.finishedSweep)
|
---|
145 | self.connect(self.myWorkThread, QtCore.SIGNAL("finishedSweep(int)"), self.myProgressBar, QtCore.SLOT("setValue(int)"))
|
---|
146 |
|
---|
147 | def createSideBar(self, sideBarLayout):
|
---|
148 |
|
---|
149 | myTDial = TemperatureDial(1, 1200)
|
---|
150 | myTDial.setValue(self.myU.temperature())
|
---|
151 | sideBarLayout.addWidget(myTDial)
|
---|
152 | temperatureLabel = QtGui.QLabel("%s" % myTDial.value())
|
---|
153 | self.connect(myTDial, QtCore.SIGNAL("valueChanged(int)"), temperatureLabel, QtCore.SLOT("setNum(int)"))
|
---|
154 | self.connect(myTDial, QtCore.SIGNAL("valueChanged(int)"), self.myU.setTemperature)
|
---|
155 | sideBarLayout.addWidget(temperatureLabel)
|
---|
156 | sideBarLayout.addStretch(1)
|
---|
157 | self.labels = {}
|
---|
158 | for name in self.labelList:
|
---|
159 | if len(name) > 2:
|
---|
160 | labelText = "%s: %8.3f" % (name[0], name[1]()[name[2]])
|
---|
161 | else:
|
---|
162 | labelText = "%s: %8.3f" % (name[0], name[1]())
|
---|
163 | self.labels[name[0]] = QtGui.QLabel(labelText)
|
---|
164 | sideBarLayout.addWidget(self.labels[name[0]])
|
---|
165 | sideBarLayout.addStretch(2)
|
---|
166 | self.bestImageLabel = QtGui.QLabel()
|
---|
167 | self.bestImageLabel.setText('Waiting...')
|
---|
168 | self.bestImageLabel.setToolTip('Waiting ...')
|
---|
169 | sideBarLayout.addWidget(self.bestImageLabel)
|
---|
170 |
|
---|
171 | self.myProgressBar = QtGui.QProgressBar()
|
---|
172 | self.myProgressBar.setRange(0, self.maxSweeps - 1)
|
---|
173 | self.myProgressBar.setValue(0)
|
---|
174 |
|
---|
175 | sideBarLayout.addWidget(self.myProgressBar)
|
---|
176 |
|
---|
177 | def finishedSweep(self, sweep):
|
---|
178 | for name in self.labelList:
|
---|
179 | if len(name) > 2:
|
---|
180 | labelText = "%s: %8.3f" % (name[0], name[1]()[name[2]])
|
---|
181 | else:
|
---|
182 | labelText = "%s: %8.3f" % (name[0], name[1]())
|
---|
183 | self.labels[name[0]].setText(labelText)
|
---|
184 | bestPix = QtGui.QPixmap("best.png")
|
---|
185 | scaledPix = bestPix.scaledToWidth(100)
|
---|
186 | self.bestImageLabel.setPixmap(scaledPix)
|
---|
187 | self.bestImageLabel.setToolTip('<img src="best.png"> E=%s at t=%s' % self.myMC.minimumEnergy())
|
---|
188 | self.setWindowIcon(QtGui.QIcon(scaledPix))
|
---|
189 | self.update()
|
---|
190 |
|
---|
191 | if __name__ == "__main__":
|
---|
192 | myApp = QtGui.QApplication(sys.argv)
|
---|
193 | myMain = MainWidget()
|
---|
194 | myMain.show()
|
---|
195 | sys.exit(myApp.exec_())
|
---|