File indexing completed on 2025-01-18 10:17:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 import os
0017 import sys
0018 import zmq
0019 import json
0020 import threading
0021 import time
0022 from tkinter import *
0023 import tkinter.ttk as ttk
0024 import tkinter.font as tkFont
0025
0026
0027
0028
0029
0030
0031 DONE = False
0032 PORT = 11238
0033 HOST = 'localhost'
0034 SOCKET = None
0035
0036
0037
0038
0039
0040
0041
0042
0043 class MultiColumnListbox(object):
0044 def __init__(self, parent, columns, title=None, titlevar=None):
0045 self.parent = parent
0046 self.columns = columns
0047 self.item_map = {}
0048 self.tree = None
0049 self._setup_widgets(title, titlevar)
0050 self._build_tree()
0051
0052 def _setup_widgets(self, title, titlevar):
0053 self.parent.columnconfigure(0, weight=1)
0054 self.parent.rowconfigure(0, weight=1)
0055 self.parent.rowconfigure(1, weight=10)
0056
0057 if title:
0058 msg = ttk.Label(self.parent, wraplength="4i", justify="left", anchor="n", padding=(10, 2, 10, 6), text=title, width=55)
0059 elif titlevar:
0060 msg = ttk.Label(self.parent, wraplength="4i", justify="left", anchor="n", padding=(10, 2, 10, 6), textvariable=titlevar, width=55)
0061 if 'msg' in locals() : msg.grid(row=0, column=0, sticky=W+E)
0062
0063
0064 container = ttk.Frame(self.parent)
0065 container.grid(row=1, column=0, sticky=N+S+W+E)
0066 container.columnconfigure(0, weight=1)
0067 container.rowconfigure(0, weight=1)
0068
0069
0070 self.tree = ttk.Treeview(container,columns=self.columns, height=15, show="headings")
0071 vsb = ttk.Scrollbar(container,orient="vertical", command=self.tree.yview)
0072 hsb = ttk.Scrollbar(container,orient="horizontal", command=self.tree.xview)
0073 self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)
0074 self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
0075 vsb.grid(column=1, row=0, sticky='ns', in_=container)
0076 hsb.grid(column=0, row=1, sticky='ew', in_=container)
0077
0078 def _build_tree(self):
0079 for col in self.columns:
0080 self.tree.heading(col, text=col.title(), command=lambda c=col: self.sortby(self.tree, c, 0))
0081
0082 myanchor = E
0083 if col == self.columns[0]: myanchor=W
0084 colwidth = int(tkFont.Font().measure(col.title()))
0085 self.tree.column(col, width=colwidth, anchor=myanchor, stretch=NO)
0086
0087
0088
0089
0090 def _upsrt_row(self, row):
0091
0092 row_list = []
0093 for col in self.columns:
0094 if col in row:
0095 row_list.append( row[col] )
0096 else:
0097 row_list.append( '' )
0098 item = tuple(row_list)
0099
0100
0101 mykey = item[0]
0102 if len(item) > 1 : mykey += ':' + item[1]
0103 if mykey not in self.item_map.keys():
0104 self.item_map[mykey] = self.tree.insert('', 'end', values=item)
0105
0106 for ix, val in enumerate(item):
0107 self.tree.set(self.item_map[mykey], self.columns[ix], val)
0108 col_w = tkFont.Font().measure(val) + 10
0109 if self.tree.column(self.columns[ix],width=None)<col_w:
0110 self.tree.column(self.columns[ix], width=col_w)
0111
0112
0113 def sortby(self, tree, col, descending):
0114
0115 data = [(tree.set(child, col), child) for child in tree.get_children('')]
0116
0117
0118
0119 data.sort(reverse=descending)
0120 for ix, item in enumerate(data): tree.move(item[1], '', ix)
0121
0122 tree.heading(col, command=lambda column=col: self.sortby(tree, column, int(not descending)))
0123
0124 def clear(self):
0125 self.tree.delete(*self.tree.get_children())
0126 self.item_map={}
0127
0128
0129
0130 class MyWindow(ttk.Frame):
0131
0132
0133
0134 def __init__(self, master=None):
0135 ttk.Frame.__init__(self, master)
0136 self.master = master
0137 self.init_window()
0138 self.cmd_queue = []
0139 self.debug_window = None
0140
0141
0142
0143 def init_window(self):
0144
0145
0146 preferred_fonts = ['Comic Sans MS', 'URW Gothic', 'Courier']
0147 available_fonts=list(tkFont.families())
0148 self.bannerFont = None
0149 for f in preferred_fonts:
0150 for af in available_fonts:
0151 if af.startswith( f ):
0152 self.bannerFont = tkFont.Font(family=af, size=36)
0153 break
0154 if self.bannerFont : break
0155 if self.bannerFont == None : self.bannerFont = tkFont.Font(family=preferred_fonts[-1], size=36)
0156
0157 self.labelsFont = tkFont.Font(family="Helvetica", size=16)
0158 self.labmap = {}
0159
0160 self.master.title('JANA Status/Control GUI')
0161 self.grid(row=0, column=0, sticky=N+S+E+W )
0162 Grid.rowconfigure(self, 0, weight=1)
0163 Grid.columnconfigure(self, 0, weight=1)
0164
0165
0166 bannerframe = ttk.Frame(self)
0167 bannerframe.grid( row=0, sticky=E+W)
0168 ttk.Label(bannerframe, anchor='center', text='JANA Status/Control GUI', font=self.bannerFont, background='white').grid(row=0, column=0, sticky=E+W)
0169 Grid.columnconfigure(bannerframe, 0, weight=1)
0170
0171
0172 infoframe = ttk.Frame(self)
0173 infoframe.grid( row=1, sticky=N+S+E+W)
0174
0175
0176 labels = {
0177 'program':'Program Name',
0178 'host' :'host',
0179 'PID' :'PID',
0180 'NEventsProcessed': 'Number of Events',
0181 'rate_avg': 'Avg. Rate (Hz)',
0182 'rate_instantaneous': 'Rate (Hz)',
0183 'NThreads': 'Number of Threads',
0184 'cpu_total': 'CPU Total Usage (%)',
0185 'cpu_idle': 'CPU idle (%)',
0186 'cpu_nice': 'CPU nice (%)',
0187 'cpu_sys': 'CPU system (%)',
0188 'cpu_user': 'CPU user (%)',
0189 'ram_tot_GB': 'RAM total (GB)',
0190 'ram_avail_GB': 'RAM avail. (GB)',
0191 'ram_free_GB': 'RAM free (GB)',
0192 'ram_used_this_proc_GB': 'RAM used this proc (GB)'
0193 }
0194 procinfoframe = ttk.Frame(infoframe)
0195 procinfoframe.grid( row=0, column=0, sticky=N+S+E+W, padx=30, ipadx=10 )
0196 for i,(varname,label) in enumerate(labels.items()):
0197 self.labmap[varname] = StringVar()
0198 ttk.Label(procinfoframe, anchor='e', text=label+': ', font=self.labelsFont).grid(row=i, column=0, sticky=E+W)
0199 ttk.Label(procinfoframe, anchor='w', textvariable=self.labmap[varname], font=self.labelsFont ).grid(row=i, column=1, sticky=E+W)
0200
0201
0202 for key in self.labmap.keys(): self.labmap[key].set('---')
0203
0204
0205 facinfoframe = ttk.Frame(infoframe)
0206 facinfoframe.grid( row=0, column=1, sticky=N+S+E+W, padx=30, ipadx=10 )
0207 self.facinfo_columns = ['FactoryName', 'FactoryTag', 'DataType', 'plugin']
0208 self.factory_info = MultiColumnListbox(facinfoframe, columns=self.facinfo_columns, title='Factories')
0209
0210
0211 controlframe = ttk.Frame(self)
0212 controlframe.grid( row=2, sticky=N+S+E+W)
0213 controlframe.columnconfigure(0, weight=1)
0214
0215
0216 nthreadsframe = ttk.Frame(controlframe)
0217 nthreadsframe.grid( row=0, sticky=E+W)
0218 ttk.Label(nthreadsframe, anchor='center', text='Num. threads', background='white').grid(row=0, column=0, columnspan=2, sticky=E+W)
0219
0220
0221 but1 = ttk.Button(nthreadsframe, text='--', command=self.DecrNThreads)
0222 but1.grid(row=1, column=0)
0223 but2 = ttk.Button(nthreadsframe, text='++', command=self.IncrNthreads)
0224 but2.grid(row=1, column=1)
0225 but3 = ttk.Button(controlframe, text='Debugger', command=self.OpenDebugger)
0226 but3.grid(row=0, column=2)
0227
0228
0229
0230 remotequitButton = ttk.Button(controlframe, text="Quit Remote",command=self.QuitRemote)
0231 remotequitButton.grid( row=2, column=0, columnspan=10, sticky=E+W )
0232
0233
0234 guicontrolframe = ttk.Frame(self)
0235 guicontrolframe.grid( row=3, sticky=E+W )
0236 guicontrolframe.columnconfigure(1, weight=1)
0237
0238 closeButton = ttk.Button(guicontrolframe, text="Quit",command=self.Quit)
0239 closeButton.grid( row=0, column=2, sticky=E+W)
0240 closeButton.columnconfigure(0, weight=1)
0241
0242
0243 Grid.rowconfigure(self, 0, weight=1)
0244 Grid.rowconfigure(self, 1, weight=10)
0245 Grid.rowconfigure(self, 2, weight=10)
0246 Grid.rowconfigure(self, 3, weight=1)
0247 Grid.columnconfigure(self, 0, weight=1)
0248
0249
0250
0251
0252
0253
0254
0255 def PrintResult(self, cmd, result):
0256 print('command: ' + cmd + ' -- result: ' + result)
0257
0258
0259
0260 def Quit(self):
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 print('Quitting ...')
0275 if self.debug_window:
0276 self.cmd_queue.append( ('debug_mode 0', self.PrintResult) )
0277 self.after(2000, self.Cleanup)
0278 else:
0279 self.Cleanup()
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 def Cleanup(self):
0290 global DONE, SOCKET
0291
0292 print(' - closing ZMQ socket ...')
0293 DONE=True
0294 if SOCKET:
0295 SOCKET.close(linger=0)
0296 context.destroy(linger=0)
0297 SOCKET = None
0298
0299
0300
0301 def QuitRemote(self):
0302 self.cmd_queue.append( ('quit', self.PrintResult) )
0303
0304
0305
0306 def DecrNThreads(self):
0307 self.cmd_queue.append( ('decrement_nthreads', self.PrintResult) )
0308
0309
0310
0311 def IncrNthreads(self):
0312 self.cmd_queue.append( ('increment_nthreads', self.PrintResult) )
0313
0314
0315
0316 def OpenDebugger(self):
0317 if not self.debug_window:
0318 self.debug_window = MyDebugWindow(self)
0319 self.debug_window.RaiseToTop()
0320 self.cmd_queue.append( ('debug_mode 1', self.PrintResult) )
0321
0322
0323
0324 def Test(self):
0325 self.cmd_queue.append( ('debug_mode 1', self.PrintResult) )
0326 self.cmd_queue.append( ('next_event', self.PrintResult) )
0327 self.cmd_queue.append( ('get_object_count', self.PrintResult) )
0328
0329 if not self.debug_window:
0330 self.debug_window = MyDebugWindow(self)
0331 self.debug_window.RaiseToTop()
0332
0333
0334
0335 def SetProcInfo(self, cmd, result):
0336
0337 info = json.loads(result)
0338 self.last_info = info
0339
0340
0341
0342
0343 labkeys = self.labmap.keys()
0344 for k,v in info.items():
0345 if k in labkeys: self.labmap[k].set(v)
0346
0347
0348
0349 def SetFactoryList(self, cmd, result):
0350 s = json.loads( result )
0351 if 'factories' in s :
0352 for finfo in s['factories']:
0353
0354 finfo['FactoryName'] = finfo['factory_name']
0355 finfo['FactoryTag'] = finfo['factory_tag']
0356 finfo['plugin'] = finfo['plugin_name']
0357 finfo['DataType'] = finfo['object_name']
0358 self.factory_info._upsrt_row(finfo)
0359
0360
0361
0362
0363
0364
0365 def TimerUpdate(self):
0366 icntr = 0
0367 while not DONE:
0368
0369
0370 self.cmd_queue.append( ('get_status', self.SetProcInfo) )
0371 if icntr%4 == 0 : self.cmd_queue.append( ('get_factory_list', self.SetFactoryList) )
0372 if self.debug_window :
0373 if icntr%2 == 0 : self.cmd_queue.append( ('get_object_count', self.debug_window.SetFactoryObjectCountList) )
0374
0375
0376 while len(self.cmd_queue)>0:
0377 try:
0378 (cmd,callback) = self.cmd_queue.pop(0)
0379 try:
0380 SOCKET.send( cmd.encode() )
0381 message = SOCKET.recv()
0382 callback(cmd, message.decode())
0383 except:
0384 pass
0385 except:
0386
0387 break
0388
0389
0390 icntr += 1
0391 icntr = (icntr+1)%1000
0392
0393
0394 if DONE: break
0395 time.sleep(0.5)
0396
0397
0398 root.quit()
0399
0400
0401
0402 class MyDebugWindow(ttk.Frame):
0403
0404
0405
0406 def __init__(self, parent):
0407 master = Toplevel(parent.master)
0408 ttk.Frame.__init__(self, master)
0409 self.master = master
0410 self.parent = parent
0411 self.master.title("JANA Debugger")
0412
0413
0414 width = 1200
0415 height = 700
0416 xoffset = self.parent.master.winfo_x() + self.parent.master.winfo_width()/2 - width/2
0417 yoffset = self.parent.master.winfo_y() + self.parent.master.winfo_height()/2 - height/2
0418 geometry = '%dx%d+%d+%d' % (width, height, xoffset, yoffset)
0419 self.master.geometry(geometry)
0420 self.labmap = {}
0421 self.init_window()
0422
0423 self.Stop()
0424
0425
0426
0427 def init_window(self):
0428
0429 self.master.title('JANA Debugger')
0430 self.master.rowconfigure(0, weight=1)
0431 self.master.columnconfigure(0, weight=1)
0432 self.grid(row=0, column=0, sticky=N+S+E+W , ipadx=10, ipady=10, padx=10, pady=10)
0433 self.rowconfigure(0, weight=1 )
0434 self.rowconfigure(1, weight=1)
0435 self.rowconfigure(2, weight=50)
0436 self.rowconfigure(3, weight=1)
0437 self.rowconfigure(10, weight=1 )
0438 self.columnconfigure(0, weight=1)
0439
0440 self.labelsFont = self.parent.labelsFont
0441 self.bannerFont = self.parent.bannerFont
0442
0443
0444 bannerframe = ttk.Frame(self)
0445 bannerframe.grid( row=0, column=0, sticky=E+W)
0446 bannerframe.columnconfigure( 0, weight=1)
0447 ttk.Label(bannerframe, anchor='center', text='JANA Debugger', font=self.bannerFont, background='white').grid(row=0, column=0, sticky=E+W)
0448
0449
0450 eventinfoframe = ttk.Frame(self)
0451 eventinfoframe.grid( row=1, column=0, sticky=N+S+E+W)
0452
0453
0454 labels = {
0455 'program':'Program Name',
0456 'host' :'host',
0457 'PID' :'PID',
0458 'run_number': 'Run Number',
0459 'event_number': 'Event Number',
0460 }
0461 procinfoframe = ttk.Frame(eventinfoframe)
0462 procinfoframe.grid( row=0, column=0, sticky=N+S+E+W, padx=30 )
0463 for i,(varname,label) in enumerate(labels.items()):
0464 self.labmap[varname] = StringVar()
0465 ttk.Label(procinfoframe, anchor='e', text=label+': ', font=self.labelsFont).grid(row=i, column=0, sticky=E+W)
0466 ttk.Label(procinfoframe, anchor='w', textvariable=self.labmap[varname] ).grid(row=i, column=1, sticky=E+W)
0467
0468
0469 for key in labels.keys(): self.labmap[key].set('---')
0470
0471
0472 infoframe = ttk.Frame(self)
0473 infoframe.grid(row=2, column=0, sticky=N+S+E+W, ipadx=5)
0474 infoframe.rowconfigure(0, weight=1)
0475 infoframe.columnconfigure(0, weight=1)
0476 infoframe.columnconfigure(1, weight=1)
0477 infoframe.columnconfigure(2, weight=1)
0478
0479 facinfoframe = ttk.Frame(infoframe, style='FrameYellow.TFrame')
0480 facinfoframe.grid( row=0, column=0, sticky=N+S+E+W)
0481 self.facinfo_columns = ['FactoryName', 'FactoryTag', 'DataType', 'plugin', 'Num. Objects']
0482 self.factory_info = MultiColumnListbox(facinfoframe, columns=self.facinfo_columns, title='Factories')
0483 self.factory_info.tree.bind("<<TreeviewSelect>>", self.OnSelectFactory)
0484
0485
0486 objinfoframe = ttk.Frame(infoframe)
0487 objinfoframe.grid( row=0, column=1, sticky=N+S+E+W)
0488 self.labmap['object_type'] = StringVar()
0489 self.objinfo_columns = ['address']
0490 self.object_info = MultiColumnListbox(objinfoframe, columns=self.objinfo_columns, titlevar=self.labmap['object_type'])
0491 self.object_info.tree.bind("<<TreeviewSelect>>", self.OnSelectObject)
0492
0493
0494 objfieldsframe = ttk.Frame(infoframe)
0495 objfieldsframe.grid( row=0, column=2, sticky=N+S+E+W)
0496 self.labmap['field_object_addr'] = StringVar()
0497 self.objfields_columns = ['name','value', 'type']
0498 self.object_fields = MultiColumnListbox(objfieldsframe, columns=self.objfields_columns, titlevar=self.labmap['field_object_addr'])
0499 self.object_fields.tree.column(0, anchor=E)
0500 self.object_fields.tree.column(1, anchor=E)
0501
0502
0503 controlframe = ttk.Frame(self)
0504 controlframe.grid( row=3, column=0, sticky=N+S+E+W)
0505 controlframe.columnconfigure(0, weight=1)
0506
0507
0508 runstopframe = ttk.Frame(controlframe)
0509 runstopframe.grid( row=0, column=0, sticky=E+W)
0510 ttk.Label(runstopframe, anchor='center', text='Run/Stop', background='white').grid(row=0, column=0, columnspan=2, sticky=E+W)
0511 self.labmap['runstop'] = StringVar()
0512 self.runstoplab = ttk.Label(runstopframe, anchor='center', textvariable=self.labmap['runstop'], background='#FF0000')
0513 self.runstoplab.grid(row=1, column=0, columnspan=2, sticky=E+W)
0514 ttk.Button(runstopframe, text='Stop', command=self.Stop).grid(row=2, column=0)
0515 ttk.Button(runstopframe, text='Run', command=self.Run ).grid(row=2, column=1)
0516 ttk.Button(runstopframe, text='Next Event', command=self.NextEvent ).grid(row=3, column=0, columnspan=2)
0517
0518
0519 guicontrolframe = ttk.Frame(self)
0520 guicontrolframe.grid( row=10, column=0, sticky=E+W )
0521 guicontrolframe.columnconfigure(0, weight=1)
0522
0523 closeButton = ttk.Button(guicontrolframe, text="Close",command=self.HideWindow)
0524 closeButton.grid( row=0, column=0, sticky=E)
0525 closeButton.columnconfigure(0, weight=1)
0526
0527
0528
0529 def HideWindow(self):
0530 self.parent.cmd_queue.append( ('debug_mode 0', self.parent.PrintResult) )
0531 self.master.withdraw()
0532
0533
0534
0535 def RaiseToTop(self):
0536 self.master.deiconify()
0537 self.master.focus_force()
0538 self.master.attributes('-topmost', True)
0539 self.after_idle(self.master.attributes,'-topmost',False)
0540
0541
0542
0543 def Run(self):
0544 self.parent.cmd_queue.append( ('debug_mode 0', self.parent.PrintResult) )
0545 self.running = True
0546 self.labmap['runstop'].set('running')
0547 self.runstoplab.config(background='#00FF00')
0548
0549
0550
0551 def Stop(self):
0552 self.parent.cmd_queue.append( ('debug_mode 1', self.parent.PrintResult) )
0553 self.running = False
0554 self.labmap['runstop'].set('stopped')
0555 self.runstoplab.config(background='#FF0000')
0556
0557
0558
0559 def NextEvent(self):
0560 self.parent.cmd_queue.append( ('next_event', self.parent.PrintResult) )
0561
0562
0563
0564 def OnSelectFactory(self, event):
0565 for item in self.factory_info.tree.selection():
0566 row = self.factory_info.tree.item(item)
0567 if row :
0568 vals = row['values']
0569 self.labmap['object_type'].set(vals[2])
0570 cmd = 'get_objects %s %s %s' % (vals[2], vals[0], vals[1])
0571 print('cmd='+cmd)
0572 self.parent.cmd_queue.append( (cmd, self.SetFactoryObjectList) )
0573 self.object_fields.clear()
0574
0575
0576
0577 def OnSelectObject(self, event):
0578 for item in self.object_info.tree.selection():
0579 row = self.object_info.tree.item(item)
0580 if row:
0581 addr = row['values'][0]
0582 label = addr + ' (' + self.labmap['object_type'].get() + ')'
0583 self.labmap['field_object_addr'].set(label)
0584 s = self.last_object_list
0585 if addr in s['objects'].keys():
0586 fields = s['objects'][addr]
0587 self.object_fields.clear()
0588 for row in fields:
0589 self.object_fields._upsrt_row(row)
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601 def SetFactoryObjectCountList(self, cmd, result):
0602 s = json.loads( result )
0603
0604
0605 labkeys = self.labmap.keys()
0606 run_changed = False
0607 event_changed = False
0608 procid_changed = False
0609 for k,v in s.items():
0610 if k == 'run_number': run_changed = (v != self.labmap[k].get())
0611 if k == 'event_number': event_changed = (v != self.labmap[k].get())
0612 if k == 'procid': procid_changed = (v != self.labmap[k].get())
0613 if k in labkeys: self.labmap[k].set(v)
0614
0615 if 'factories' in s :
0616 for finfo in s['factories']:
0617
0618 finfo['FactoryName'] = finfo['factory_name']
0619 finfo['FactoryTag'] = finfo['factory_tag']
0620 finfo['plugin'] = finfo['plugin_name']
0621 finfo['DataType'] = finfo['object_name']
0622 finfo['Num. Objects'] = finfo['nobjects']
0623 self.factory_info._upsrt_row(finfo)
0624
0625
0626 if run_changed or event_changed or procid_changed: self.UpdateNewEvent()
0627
0628
0629
0630
0631
0632
0633 def UpdateNewEvent(self):
0634
0635 self.object_fields.clear()
0636 self.last_object_list = None
0637
0638
0639
0640
0641
0642
0643 self.object_info.clear()
0644
0645
0646
0647
0648
0649 for item in self.factory_info.tree.selection():
0650 self.factory_info.tree.selection_set(item)
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660 def SetFactoryObjectList(self, cmd, result):
0661
0662 addr = None
0663 items = self.object_info.tree.selection()
0664 if items:
0665 addr = self.object_info.tree.item(items[0])['values'][0]
0666
0667 try:
0668 s = json.loads( result )
0669 except json.decoder.JSONDecodeError as e:
0670 print('ERROR decoding JSON: ' + e.msg)
0671 self.last_object_list = s
0672 self.object_info.clear()
0673 for a in s['objects'].keys():
0674 row = {'address':a}
0675 self.object_info._upsrt_row(row)
0676 if a == addr:
0677
0678 item_to_select = self.object_info.tree.get_children()[-1]
0679 if item_to_select: self.object_info.tree.selection_set(item_to_select)
0680
0681
0682
0683 def Usage():
0684 mess='''
0685 Usage:
0686 jana-control.py [--help] [--host HOST] [--port PORT]
0687
0688 This script will open a GUI window that will monitor a running JANA process.
0689 The process can be running on either the local node or a remote node. For
0690 this to work, the following criteria must be met:
0691
0692 1. JANA must have been compiled with ZEROMQ support. (This relies
0693 on cmake find_package(ZEROMQ) successfully finding it when camke
0694 is run.)
0695
0696 2. The python3 environment must me present and have zmq installed.
0697 (e.g. pip3 install zmq)
0698
0699 3. The JANA process must have been started with the janacontrol plugin.
0700 This should generally be added to the *end* of the plugin list
0701 like this:
0702
0703 -Pplugins=myplugin1,myplugin2,janacontrol
0704
0705 By default, it will try to attach to port 11238 on the localhost. It
0706 does not matter whether the JANA process is already running or not.
0707 It will automatically connect when it does and reconnect if the process
0708 is restarted.
0709
0710 The following command line options are available:
0711
0712 -h, --help Print this Usage statement and exit
0713 --host HOST Set the host of the JANA process to monitor
0714 --port PORT Set the port on the host to connect to
0715
0716 n.b. To change the port used by the remote JANA process set the
0717 jana:zmq_port configuration parameter.
0718
0719 Debugger
0720 --------------
0721 The GUI can be used to step through events in the JANA process and
0722 view the objects, with some limitations. If the data object inherits
0723 from JObject then it will display fields obtained from the subclass'
0724 Summarize method. (See JObject::Summarize for details). If the data
0725 object inherits from ROOT's TObject then an attempt is made to extract
0726 the data members via the dictionary. Note that this relies on the
0727 dictionary being available in the plugin and there are limitations
0728 to the complexity of the objects that can be displayed.
0729
0730 When the debugger window is opened (by pushing the "Debugger" button
0731 on the main GUI window), it will stall event processing so that single
0732 events can be examined and stepped through. To stall processing on the
0733 very first event, the JANA process should have the jana:debug_mode
0734 config. parameter set to a non-zero value when it is started. e.g.
0735
0736 jana -Pplugins=myplugin1,myplugin2,janacontrol -Pjana:debug_mode=1 file1.dat
0737
0738 Once an event is loaded, click on a factory to display a list of
0739 objects it created for this event (displayed as the object's hexadecimal
0740 address). Click on an object to display its content summary (if they
0741 are accessible). n.b. clicking on a factory will NOT cause the factory
0742 algorithm to activate and create objects for the event. It will only
0743 display objects created by other plugins having activated the algorithm.
0744 '''
0745 return mess
0746
0747
0748
0749
0750
0751
0752
0753 if any(item in ['-h', '-help', '--help'] for item in sys.argv):
0754 print( Usage() )
0755 sys.exit()
0756 Nargs = len(sys.argv)
0757 for i,arg in enumerate(sys.argv):
0758 if i==0 : continue
0759 if (arg=='--host') and (i+1<Nargs): HOST = sys.argv[i+1]
0760 if (arg=='--port') and (i+1<Nargs): PORT = sys.argv[i+1]
0761
0762 print('\nAttempting connection on host="'+HOST+'" port='+str(PORT))
0763 print('For help, run "jana-control.py --help"\n')
0764
0765 os.environ['TK_SILENCE_DEPRECATION'] = '1'
0766
0767
0768 root = Tk()
0769 style = ttk.Style()
0770 style.theme_use('classic')
0771 style.configure('FrameRed.TFrame', background='red' )
0772 style.configure('FrameGreen.TFrame', background='green')
0773 style.configure('FrameBlue.TFrame', background='blue' )
0774 style.configure('FrameCyan.TFrame', background='cyan' )
0775 style.configure('FrameYellow.TFrame', background='yellow' )
0776 style.configure('FrameViolet.TFrame', background='violet' )
0777 root.geometry("900x700+2500+0")
0778 Grid.rowconfigure(root, 0, weight=1)
0779 Grid.columnconfigure(root, 0, weight=1)
0780 app = MyWindow(root)
0781
0782
0783 context = zmq.Context()
0784 connstr = "tcp://" + HOST + ":" + str(PORT)
0785 print('Connecting to ' + connstr )
0786 SOCKET = context.socket( zmq.REQ )
0787 SOCKET.connect(connstr)
0788
0789
0790 threads = []
0791 t = threading.Thread(target=app.TimerUpdate)
0792 t.start()
0793 threads.append(t)
0794
0795
0796 root.mainloop()
0797 root.destroy()
0798
0799
0800 print('GUI finished. Cleaning up ...')
0801
0802 print(' - joining threads ...')
0803 for t in threads: t.join()
0804
0805 print('\nFinished\n')