1
- # demo_gui.py ---
2
- #
1
+ # demo_gui.py ---
2
+ #
3
3
# Filename: demo_gui.py
4
- # Description:
4
+ # Description:
5
5
# Author: Subhasis Ray
6
- # Maintainer:
6
+ # Maintainer:
7
7
# Created: Wed Jun 16 05:41:58 2010 (+0530)
8
- # Version:
9
- # Last-Updated: Tue Sep 11 14:26:13 2012 (+0530)
10
- # By: subha
11
- # Update #: 318
12
- # URL:
8
+ # Version:
9
+ # Last-Updated: Tue May 30 15:23:07 2023 (+0530)
10
+ # By: Subhasis Ray
11
+ # Update #: 489
12
+ # URL:
13
13
14
14
# Change log:
15
- # Tuesday 18 September 2018 09:51:56 AM IST`
15
+ # Tuesday 18 September 2018 09:51:56 AM IST`
16
16
# Qt Related changes.
17
17
18
- try :
19
- from PyQt4 import QtGui , QtCore
20
- from PyQt4 .Qt import Qt
21
- except ImportError as e :
22
- print ( 'PyQt4 is not found. Doing nothing' )
23
- quit ()
18
+ import matplotlib .pyplot as plt
19
+ import numpy
24
20
25
21
try :
26
- import PyQt4 .Qwt5 as Qwt
22
+ from PyQt5 .QtWidgets import (
23
+ QMainWindow ,
24
+ QFrame ,
25
+ QPushButton ,
26
+ QLabel ,
27
+ QGridLayout ,
28
+ QSizePolicy ,
29
+ QVBoxLayout ,
30
+ QApplication ,
31
+ )
32
+
33
+ from matplotlib .backends .backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
34
+ from matplotlib .backends .backend_qt5agg import (
35
+ NavigationToolbar2QT as NavigationToolbar ,
36
+ )
27
37
except ImportError as e :
28
- print ( 'PyQt4.Qwt5 not found. Doing nothing' )
38
+ print ('PyQt5 is not found. Doing nothing' )
29
39
quit ()
30
-
31
- import numpy
40
+
41
+
32
42
from Izhikevich import IzhikevichDemo
33
43
34
44
35
- class IzhikevichGui (QtGui . QMainWindow ):
45
+ class IzhikevichGui (QMainWindow ):
36
46
"""This is a Qt version of the GUI"""
47
+
37
48
def __init__ (self , * args ):
38
- QtGui . QMainWindow .__init__ (self , * args )
49
+ QMainWindow .__init__ (self , * args )
39
50
self .demo = IzhikevichDemo ()
40
- self .signalMapper = QtCore .QSignalMapper (self )
41
- self .demoFrame = QtGui .QFrame (self )
42
- self .controlPanel = QtGui .QFrame (self .demoFrame )
43
- self .figureNo = {}
44
- self .buttons = {}
45
- for key , value in list (IzhikevichDemo .parameters .items ()):
46
- button = QtGui .QPushButton (key , self .controlPanel )
47
- self .figureNo [value [0 ]] = key
48
- self .buttons [key ] = button
49
- keys = list (self .figureNo .keys ())
50
- keys .sort ()
51
- length = len (keys )
51
+ self .demoFrame = QFrame (self )
52
+ self .controlPanel = QFrame (self .demoFrame )
53
+ # Map figlabels A-T from Izhi paper to params
54
+ # i.e., 'F' -> 'spike_freq_adapt'
55
+ self .label_title = {
56
+ value [0 ]: key for key , value in IzhikevichDemo .parameters .items ()
57
+ }
58
+ labels = sorted (self .label_title .keys ())
59
+ length = len (labels )
52
60
rows = int (numpy .rint (numpy .sqrt (length )))
53
61
cols = int (numpy .ceil (length * 1.0 / rows ))
54
- layout = QtGui .QGridLayout ()
55
- for ii in range (rows ):
56
- for jj in range (cols ):
57
- index = ii * cols + jj
58
- if index < length :
59
- key = self .figureNo [keys [index ]]
60
- button = self .buttons [key ]
61
- button .setToolTip (self .tr (IzhikevichDemo .documentation [key ]))
62
- layout .addWidget (button , ii , jj )
63
- self .connect (button , QtCore .SIGNAL ('clicked()' ), self .signalMapper , QtCore .SLOT ('map()' ))
64
- self .signalMapper .setMapping (button , key )
62
+ layout = QGridLayout ()
63
+ for ii , label in enumerate (labels ):
64
+ row = ii // cols
65
+ col = ii % cols
66
+ title = self .label_title [label ]
67
+ button = QPushButton (title , self )
68
+ button .setToolTip (self .tr (IzhikevichDemo .documentation [title ]))
69
+ layout .addWidget (button , row , col )
70
+ # NOTE: There is a trick here:
71
+ # button.clicked(checked=False) sends a boolean param, but
72
+ # we need to ignore that, while storing the associated
73
+ # `title` local to the lambda, which is done via the
74
+ # keyword param
75
+ button .clicked .connect (
76
+ lambda checked , key = title : self ._simulateAndPlot (key )
77
+ )
65
78
66
- self .connect (self .signalMapper , QtCore .SIGNAL ('mapped(const QString &)' ), self ._simulateAndPlot )
67
79
self .controlPanel .setLayout (layout )
68
- self .plotPanel = QtGui .QFrame (self .demoFrame )
69
- self .VmPlot = Qwt .QwtPlot (self .plotPanel )
70
- self .VmPlot .setAxisTitle (Qwt .QwtPlot .xBottom , 'time (ms)' )
71
- self .VmPlot .setAxisTitle (Qwt .QwtPlot .yLeft , 'Vm (mV)' )
72
- self .VmPlot .replot ()
73
- self .ImPlot = Qwt .QwtPlot (self .plotPanel )
74
- self .ImPlot .setAxisTitle (Qwt .QwtPlot .xBottom , 'time (ms)' )
75
- self .ImPlot .setAxisTitle (Qwt .QwtPlot .yLeft , 'Im (nA)' )
76
- self .vmPlotZoomer = self ._make_zoomer (self .VmPlot )
77
- self .imPlotZoomer = self ._make_zoomer (self .ImPlot )
78
- self .descriptionWidget = QtGui .QLabel ('Click any of the buttons to simulate and plot the corresponding neuron.' )
79
- self .descriptionWidget .setFrameStyle (QtGui .QFrame .Panel | QtGui .QFrame .Sunken )
80
- sizePolicy = QtGui .QSizePolicy (QtGui .QSizePolicy .Expanding , QtGui .QSizePolicy .Expanding )
80
+ self .figure = plt .figure ()
81
+ self .plotPanel = FigureCanvas (self .figure )
82
+ self .navbar = NavigationToolbar (self .plotPanel , self )
83
+ self .VmPlot = self .figure .add_subplot (211 )
84
+ (self .VmCurve ,) = self .VmPlot .plot ([], [], label = 'Vm (mV)' )
85
+ self .VmPlot .set_xlabel ('time (ms)' )
86
+ self .VmPlot .set_ylabel ('Vm (mV)' )
87
+ self .ImPlot = self .figure .add_subplot (212 )
88
+ (self .ImCurve ,) = self .ImPlot .plot ([], [], label = 'Im (nA)' )
89
+ self .ImPlot .set_xlabel ('time (ms)' )
90
+ self .ImPlot .set_ylabel ('Im (nA)' )
91
+ self .descriptionWidget = QLabel (
92
+ 'Click any of the buttons to simulate and plot the corresponding neuron.'
93
+ )
94
+ self .descriptionWidget .setFrameStyle (QFrame .Panel | QFrame .Sunken )
95
+ sizePolicy = QSizePolicy (QSizePolicy .Expanding , QSizePolicy .Expanding )
81
96
self .descriptionWidget .setSizePolicy (sizePolicy )
82
- self .VmPlot .setSizePolicy (sizePolicy )
83
- self .ImPlot .setSizePolicy (sizePolicy )
84
- layout = QtGui .QVBoxLayout ()
85
- layout .addWidget (self .VmPlot )
86
- layout .addWidget (self .ImPlot )
87
- layout .addWidget (self .descriptionWidget )
88
- self .plotPanel .setLayout (layout )
89
- layout = QtGui .QVBoxLayout ()
97
+ layout = QVBoxLayout ()
90
98
layout .addWidget (self .plotPanel )
99
+ layout .addWidget (self .navbar )
100
+ layout .addWidget (self .descriptionWidget )
91
101
layout .addWidget (self .controlPanel )
92
102
self .demoFrame .setLayout (layout )
93
103
self .setCentralWidget (self .demoFrame )
@@ -98,52 +108,36 @@ def _simulateAndPlot(self, key):
98
108
doc = IzhikevichDemo .documentation [key ].replace ('\n ' , '<br/>' )
99
109
text = '<b>%s:</b> %s<p><b>Equation:</b><br/> %s' % (key , doc , equationText )
100
110
self .descriptionWidget .setText (self .tr (text ))
101
- # if key == 'accommodation':
102
- # mbox = QtGui.QMessageBox(self)
103
- # mbox.setText(self.tr('Accommodation cannot be shown with regular Izhikevich model.'))
104
- # mbox.setDetailedText(self.tr('\
105
- # Equation for u for the accommodating neuron is: \
106
- # u\' = a * b * (V + 65)\n Which is different from \
107
- # the regular equation u\' = a * (b*V - u) and cannot \
108
- # be obtained from the latter by any choice of a and b.'))
109
- # mbox.show()
110
- # return
111
+ # if key == 'accommodation':
112
+ # mbox = QtGui.QMessageBox(self)
113
+ # mbox.setText(self.tr('Accommodation cannot be shown with regular Izhikevich model.'))
114
+ # mbox.setDetailedText(self.tr('\
115
+ # Equation for u for the accommodating neuron is: \
116
+ # u\' = a * b * (V + 65)\n Which is different from \
117
+ # the regular equation u\' = a * (b*V - u) and cannot \
118
+ # be obtained from the latter by any choice of a and b.'))
119
+ # mbox.show()
120
+ # return
111
121
(time , Vm , Im ) = self .demo .simulate (key )
112
122
Vm = numpy .array (Vm .vector ) * 1e3
113
123
Im = numpy .array (Im .vector ) * 1e9
114
- self .VmPlot .clear ()
115
- self .ImPlot .clear ()
116
- curve = Qwt .QwtPlotCurve (self .tr (key + '_Vm' ))
117
- curve .setPen (QtCore .Qt .red )
118
- curve .setData (time , numpy .array (Vm ))
119
- curve .attach (self .VmPlot )
120
- curve = Qwt .QwtPlotCurve (self .tr (key + '_Im' ))
121
- curve .setPen (QtCore .Qt .blue )
122
- curve .setData (time , Im )
123
- curve .attach (self .ImPlot )
124
- self .imPlotZoomer .setZoomBase ()
125
- self .vmPlotZoomer .setZoomBase ()
126
- self .ImPlot .replot ()
127
- self .VmPlot .replot ()
128
-
124
+ self .VmCurve .set_data (time , Vm )
125
+ self .ImCurve .set_data (time , Im )
126
+ self .VmPlot .relim () # Recalculate limits
127
+ self .VmPlot .autoscale_view (True , True , True ) # Autoscale
128
+ self .ImPlot .relim () # Recalculate limits
129
+ self .ImPlot .autoscale_view (True , True , True ) # Autoscale
130
+ self .plotPanel .draw ()
131
+ self .demoFrame .repaint ()
129
132
130
- def _make_zoomer (self , plot ):
131
- zoomer = Qwt .QwtPlotZoomer (Qwt .QwtPlot .xBottom ,
132
- Qwt .QwtPlot .yLeft ,
133
- Qwt .QwtPicker .DragSelection ,
134
- Qwt .QwtPicker .AlwaysOn ,
135
- plot .canvas ())
136
- zoomer .setRubberBandPen (QtGui .QPen (QtCore .Qt .white ))
137
- zoomer .setTrackerPen (QtGui .QPen (QtCore .Qt .cyan ))
138
- return zoomer
139
-
140
133
141
134
import sys
135
+
142
136
if __name__ == '__main__' :
143
- app = QtGui . QApplication (sys .argv )
137
+ app = QApplication (sys .argv )
144
138
mainWin = IzhikevichGui ()
145
139
mainWin .show ()
146
140
sys .exit (app .exec_ ())
147
141
148
- #
142
+ #
149
143
# demo_gui.py ends here
0 commit comments