Newer
Older
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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
import psutil
from PyQt4 import Qt, QtCore, QtGui
import datetime
import numpy as np
import config
#check if command line flag --nompl set to disable matplotlib
if not(config.nompl):
try:
import matplotlib
if matplotlib.get_backend() != 'QT4Agg':
matplotlib.use('QT4Agg')
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
config.mplLoaded=True
# print "matplotlib try successful"
except:
# print "matplotlib except case"
#case where matplotlib not available - need to know this for handling plotting tabs
config.mplLoaded=False
pass
else:
config.mplLoaded=False #use this flag to test case when matplotlib is not available
def constantUpdateActor(self,config):
#check duration
Ndur=self.duration
#update global variables
#mode to show status in percentage
cpu_stats = psutil.cpu_times_percent(interval=0,percpu=False) #syntax seems to be same for psutil versions 1 and 2
percentcpubusy = 100.0 - cpu_stats.idle
self.ui.progressBarStatusCPU.setValue(round(percentcpubusy))
percentmembusy=psutil.virtual_memory().percent
self.ui.progressBarStatusMemory.setValue(round(percentmembusy))
Ncpus=len(psutil.cpu_percent(percpu=True))
self.ui.Ncpus=Ncpus
totalcpustr='CPU Count: '+str(Ncpus)
# print "Total CPU str: ",totalcpustr
self.ui.labelCPUCount.setText(totalcpustr)
totalmem=int(round(float(psutil.virtual_memory().total)/(1024*1024*1024))) #psutil syntax OK for both versions
# print "Total Mem: ",totalmem
self.ui.labelMemUsage.setText('Memory Usage: '+str(totalmem*percentmembusy/100)+' GB')
self.ui.totalmem=totalmem
totalmemstr='Max Mem: '+str(totalmem)+' GB'
# print "Total Mem str: ",totalmemstr
self.ui.labelMaxMem.setText(totalmemstr)
# print "** config.mplLoaded: ",config.mplLoaded
if config.mplLoaded:
#update first position with most recent value overwriting oldest value which has been shifted to first position
self.ui.cpu=np.roll(self.ui.cpu,1)
self.ui.cpu[0]=percentcpubusy
self.ui.mem=np.roll(self.ui.mem,1)
self.ui.mem[0]=percentmembusy
# self.ui.dt=np.roll(self.ui.dt,1)
# self.ui.dt[0]=datetime.datetime.now()
# update system tab
if self.ui.tabWidget.currentIndex() == config.SYST_TAB:
#determine the computer uptime
if config.psutilVer == 1:
uptime = str(datetime.datetime.now() - datetime.datetime.fromtimestamp(psutil.BOOT_TIME))
else:
uptime = str(datetime.datetime.now() - datetime.datetime.fromtimestamp(psutil.boot_time()))
self.ui.labelUptime.setText("System Uptime: "+uptime)
#update the number of users each time interval as well
userInfo=psutil.get_users() if config.psutilVer == 1 else psutil.users()
lst=[]
for item in userInfo:
lst.append(item.name)
uusers=set(lst)
Nuusers=len(uusers)
self.ui.labelNUsers.setText("Number of Users Logged On: "+str(Nuusers))
#update the history plot
if self.ui.tabWidget.currentIndex() == config.HIST_TAB:
#only update history plot if tab is active
font = {'family' : 'sans-serif',
'weight' : 'bold',
'size' : 10}
matplotlib.rc('font', **font)
xtime=range(0,self.ui.Nsamples+1,self.update)
Npts=Ndur/self.update
plt.figure(self.ui.figure.number) #make plot figure active
plt.clf() #clear figure each time for rolling updates to show
plt.plot(xtime[0:Npts+1],self.ui.cpu[0:Npts+1],color='Blue',label='CPU Busy')
plt.plot(xtime[0:Npts+1],self.ui.mem[0:Npts+1],color='Green',label='Mem Busy')
plt.title('Composite CPU and Memory Activity',fontsize=10,fontweight='bold')
plt.ylabel('% Busy',fontsize=9.5,fontweight='bold')
if self.update == 1:
xlab="Seconds with 1 Second Updates"
elif self.update == 2:
xlab="Seconds with 2 Second Updates"
elif self.update == 5:
xlab="Seconds with 5 Second Updates"
elif self.update == 10:
xlab="Seconds with 10 Second Updates"
plt.xlabel(xlab,fontsize=9.5,fontweight='bold')
plt.legend(loc="upper right",prop={'size':9})
plt.xlim([0,Ndur])
self.ui.canvas.draw()
#update the process table
if self.ui.tabWidget.currentIndex() == config.PROC_TAB:
#only update process table if tab is active
updateProcTable(self,config)
#update the Users bar chart
if self.ui.tabWidget.currentIndex() == config.USER_TAB:
#only update bar chart if the tab is active.
updateUserChart(self,config)
def updateProcTable(self,config):
if self.doUpdates==True:
table=self.ui.tableWidgetProcess
#first remove all rows
Nrows=table.rowCount()
for row in range(Nrows):
table.removeRow(0)
#get the processes
pidList=psutil.get_pid_list() if config.psutilVer == 1 else psutil.pids()
Npids=len(pidList)
#now add rows to the table according to the number of processes
# for row in range(Npids):
# table.insertRow(0)
#now populate the table
row=0 #table row counter incremented for each row added to the process table
rout=0 #counter for number of rows to remove due to invalid processes
memtot=psutil.virtual_memory() #psutil syntax OK for both versions
#determine which column has been selected for sorting
column_sorted=table.horizontalHeader().sortIndicatorSection()
order = table.horizontalHeader().sortIndicatorOrder()
#temporarily set sort column to outside column range so that table items can be filled properly
table.sortItems(5,order=QtCore.Qt.AscendingOrder)
#print table.horizontalHeader().sortIndicatorSection()
#create empty dictionaries to be used by the process table
d_user={}
d_cpu={}
d_mem={}
d_name={}
#fill the dictionaries - seems to need to be done faster than within loop which also fills the table...not sure why...
for proc in psutil.process_iter():
cpupct=proc.get_cpu_percent(interval=0) if config.psutilVer == 1 else proc.cpu_percent(interval=0)
memVal=float(int(float(proc.get_memory_percent())*100.0))/100.0 if config.psutilVer == 1 else float(int(float(proc.memory_percent())*100.0))/100.0
try:
#don't update dictionaries if name gives an access denied error when checking process name
pname=proc.name if config.psutilVer == 1 else proc.name()
d_user.update({proc.pid:proc.username}) if config.psutilVer == 1 else d_user.update({proc.pid:proc.username()})
d_cpu.update({proc.pid:cpupct})
d_mem.update({proc.pid:memVal})
d_name.update({proc.pid:pname})
except:
pass #place holder
#now fill the table for display
for proc in d_user.keys():
#print "proc: ",proc," type: ",type(proc)
pid=int(proc)
#print "pid: ",pid
table.insertRow(0)
#print "inserting row"
#set process id
item=QtGui.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole,pid)
table.setItem(0,0,item)
#set username
#print " d_user[proc]: ",d_user[proc]," proc: ",proc
table.setItem(0,1,QtGui.QTableWidgetItem(d_user[proc]))
#set CPU %
item=QtGui.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole,d_cpu[proc])
table.setItem(0,2,item)
#set memory %
item=QtGui.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole,d_mem[proc])
table.setItem(0,3,item)
#set process name
table.setItem(0,4,QtGui.QTableWidgetItem(d_name[proc]))
row+=1
# for row in range(rout):
# table.removeRow(Npids-row)
#restore sort to previously selected column
#table.sortItems(column_sorted,order=QtCore.Qt.AscendingOrder)
table.sortItems(column_sorted,order=order)
self.ui.labelLastUpdate.setText("Last Update: "+str(datetime.datetime.now()))
def updateUserChart(self,config):
font = {'family' : 'sans-serif',
'weight' : 'bold',
'size' : 9}
matplotlib.rc('font', **font)
f=plt.figure(self.ui.figure2.number)
# self.ui.figure2=plt.figure(2)
plt.clf()
plt.cla()
# f.gca().cla()
#create empty dictionaries to be used by the process table
d_user={}
d_cpu={}
d_mem={}
d_name={}
#fill the dictionaries - seems to need to be done faster than within loop which also fills the table...not sure why...
for proc in psutil.process_iter():
cpupct=proc.get_cpu_percent(interval=0) if config.psutilVer == 1 else proc.cpu_percent(interval=0)
memVal=float(int(float(proc.get_memory_percent())*100.0))/100.0 if config.psutilVer == 1 else float(int(float(proc.memory_percent())*100.0))/100.0
try:
#don't update dictionaries if name gives an access denied error when checking process name
pname=proc.name if config.psutilVer == 1 else proc.name()
d_user.update({proc.pid:proc.username}) if config.psutilVer == 1 else d_user.update({proc.pid:proc.username()})
d_cpu.update({proc.pid:cpupct})
d_mem.update({proc.pid:memVal})
d_name.update({proc.pid:pname})
except:
pass #place holder
users=d_user.values()
users_unique=list(set(users)) #use set() to find unique users then convert the resulting set to a list via list()
Nusers=len(users_unique)
#create cpu and memory by users dictionaries
cpu_by_users={}
mem_by_users={}
for u in range(Nusers):
cpu_by_users.update({users_unique[u]:0})
mem_by_users.update({users_unique[u]:0})
#apparently update does not order keys in sequence to users_unique
#thus need to re-create users_unique according to the order of the users
#in the cpu and mem dictionary keys
users_unique=list(cpu_by_users.keys())
#fill cpu and memory dictionaries sequencing thru each PID
for pid in d_user.keys():
user=d_user[pid]
cpu_by_users[user]=cpu_by_users[user] + d_cpu[pid]
mem_by_users[user]=mem_by_users[user] + d_mem[pid]
#now convert to a list which we can index
cpu_by_users_lst=cpu_by_users.values()
mem_by_users_lst=mem_by_users.values()
width=0.85
colors=['b','g','r','c','m','y','gray','hotpink','brown','k']
Nmax=len(colors) #don't want to have more users than colors...
if self.ui.radioButtonCPU.isChecked():
sortBy='cpu'
elif self.ui.radioButtonMem.isChecked():
sortBy='mem'
else:
print "invalid radio button selection - using CPU sort as default"
sortBy='cpu'
#sortBy='cpu' # 'cpu' or 'mem' - use for debugging
#create sort index
if sortBy=='cpu':
indx=sorted(range(len(cpu_by_users_lst)), key=cpu_by_users_lst.__getitem__,reverse=True)
elif sortBy=='mem':
indx=sorted(range(len(mem_by_users_lst)), key=mem_by_users_lst.__getitem__,reverse=True)
else:
print 'Incorrect sort parameter'
#sort lists
cpu_by_users_sorted=[cpu_by_users_lst[x] for x in indx]
mem_by_users_sorted=[mem_by_users_lst[x] for x in indx]
users_unique_sorted=[users_unique[x] for x in indx]
#restrict the number of users we'll show to Nmax
if Nusers > Nmax:
#replace the Nmaxth - 1 element with the total of the values from index Nmax - 1 to the end of the list
cpu_by_users_sorted[Nmax-1]=sum(cpu_by_users_sorted[Nmax-1:])
mem_remaining=sum(mem_by_users_sorted[Nmax-1:])
users_unique_sorted[Nmax-1]='Remaining'
Nshow=Nmax
else:
Nshow=Nusers
if min(cpu_by_users_sorted) < 0:
print " *** cp_by_users_sorted has values less than zero"
print cpu_by_users_sorted
print " ***"
if min(mem_by_users_sorted) < 0:
print " *** mem_by_users_sorted has values less than zero"
print mem_by_users_sorted
print " ***"
#range check the values of the sorted lists - may not be necessary, just being cautious...
tst=np.array(cpu_by_users_sorted)<0 #need an array for summing
indx=cpu_by_users_sorted<0 #need bool list for indexing
if sum(tst) > 0:
print "cpu_by_users < 0: ",sum(indx)
cpu_by_users_sorted[indx]=0
tst=np.array(cpu_by_users_sorted)>self.ui.Ncpus*100
indx=cpu_by_users_sorted>self.ui.Ncpus*100
if sum(tst) > 0:
print "cpu_by_users > Ncpus*100: ",sum(indx)
cpu_by_users_sorted[indx]=self.ui.Ncpus*100
tst=np.array(mem_by_users_sorted)<0
indx=mem_by_users_sorted<0
if sum(tst) > 0:
print "mem_by_users < 0: ",sum(indx)
mem_by_users_sorted[indx]=0
tst=np.array(mem_by_users_sorted)>self.ui.totalmem
indx=mem_by_users_sorted>self.ui.totalmem
if sum(tst) > 0:
print "mem_by_users > totalmem: ",sum(indx)
mem_by_users_sorted[indx]=self.ui.totalmem
p=[] #list to contain plot objects for use by the legend
ind=np.arange(2)
for u in range(Nshow):
if u == 0:
p.append(plt.bar(ind,(cpu_by_users_sorted[u],mem_by_users_sorted[u]),width,bottom=(0,0),color=colors[u]))
else:
p.append(plt.bar(ind,(cpu_by_users_sorted[u],mem_by_users_sorted[u]),width,bottom=(sum(cpu_by_users_sorted[0:u]),sum(mem_by_users_sorted[0:u])),color=colors[u]))
plt.title('CPU and Memory Usage by User',fontsize=10,fontweight='bold')
#remove default yaxis ticks then redraw them via ax1 and ax2 below
frame=plt.gca()
frame.axes.get_yaxis().set_ticks([])
plt.xticks(np.arange(2)+width/2.,('CPU','Mem'),fontsize=9,fontweight='bold')
ymaxCPU=round(int((sum(cpu_by_users_sorted[0:Nshow])+100)/100)*100)
ymaxMEM=round(int((sum(mem_by_users_sorted[0:Nshow])+100)/100)*100)
ymax=max([ymaxCPU,ymaxMEM,100])
# plt.ylim([0,ymax])
#compute composite %
ylab=np.arange(6)/5.0*float(ymax)/float(self.ui.Ncpus)
ylab=ylab*10
tmp=ylab.astype('int')
tmp1=tmp.astype('float')
tmp1=tmp1/10
ylab1=tmp1
ax1=plt.twinx()
ax1.set_ylabel('Composite CPU Percent',fontsize=9,fontweight='bold')
ax1.yaxis.set_ticks_position('left')
ax1.yaxis.set_label_position('left')
ax1.set_yticks(ylab1)
usersLegend=users_unique_sorted[0:Nshow]
#reverse legend print order to have legend correspond with the order data are placed in the bar chart
usersLegend.reverse()
p.reverse()
plt.legend(p,usersLegend)
#place second y axis label on plot
ylab2=np.arange(5)/4.0*float(ymax)
ax2=plt.twinx()
ax2.set_ylabel('Percent',fontsize=9,fontweight='bold')
ax2.set_yticks(ylab2)
#ax2.set_yticks(ylab2)
ax2.yaxis.set_ticks_position('right')
ax2.yaxis.set_label_position('right')
self.ui.canvas2.draw()
def reLayout(self):
tmpWidget=QtGui.QWidget()
tmpWidget.setLayout(self.ui.layout2)
tmpLayout = QtGui.QVBoxLayout(self.ui.frameBar)