1- import  re 
2- 
3- import  numpy  as  np 
4- from  app_hooks  import  TEST_PATTERN , get_rundata , make_camera_displays 
1+ from  app_hooks  import  (
2+     get_rundata ,
3+     make_camera_displays ,
4+     make_timelines ,
5+     update_camera_displays ,
6+     update_timelines ,
7+ )
58
69# bokeh imports 
7- from  bokeh .layouts  import  layout , row 
8- from  bokeh .models  import  Select    # , NumericInput 
10+ from  bokeh .layouts  import  column ,  gridplot , row 
11+ from  bokeh .models  import  Select ,  TabPanel ,  Tabs 
912from  bokeh .plotting  import  curdoc 
1013
1114# ctapipe imports 
1215from  ctapipe .coordinates  import  EngineeringCameraFrame 
1316from  ctapipe .instrument  import  CameraGeometry 
14- from  ctapipe_io_nectarcam  import  constants 
1517
1618from  nectarchain .dqm .db_utils  import  DQMDB 
1719
1820geom  =  CameraGeometry .from_name ("NectarCam-003" )
1921geom  =  geom .transform_to (EngineeringCameraFrame ())
2022
2123
22- def  update_camera_displays (attr , old , new ):
24+ def  update (attr , old , new ):
2325    runid  =  run_select .value 
24-     new_rundata  =  get_rundata (db , runid )
25- 
26-     # Reset each display 
27-     for  k  in  displays .keys ():
28-         for  kk  in  displays [k ].keys ():
29-             displays [k ][kk ].image  =  np .zeros (shape = constants .N_PIXELS )
30- 
31-     for  parentkey  in  db [runid ].keys ():
32-         if  not  re .match (TEST_PATTERN , parentkey ):
33-             for  childkey  in  db [runid ][parentkey ].keys ():
34-                 print (f"Run id { runid } { parentkey } { childkey }  )
35- 
36-                 image  =  new_rundata [parentkey ][childkey ]
37-                 image  =  np .nan_to_num (image , nan = 0.0 )
38-                 try :
39-                     displays [parentkey ][childkey ].image  =  image 
40-                 except  ValueError  as  e :
41-                     print (
42-                         f"Caught { type (e ).__name__ } { childkey }  
43-                         f"with zeros. Details: { e }  
44-                     )
45-                     image  =  np .zeros (shape = displays [parentkey ][childkey ].image .shape )
46-                     displays [parentkey ][childkey ].image  =  image 
47-                 except  KeyError  as  e :
48-                     print (
49-                         f"Caught { type (e ).__name__ } { childkey }  
50-                         f"with zeros. Details: { e }  
51-                     )
52-                     image  =  np .zeros (shape = constants .N_PIXELS )
53-                     displays [parentkey ][childkey ].image  =  image 
54-                 # TODO: TRY TO USE `stream` INSTEAD, ON UPDATES: 
55-                 # display.datasource.stream(new_data) 
56-                 # displays[parentkey][childkey].datasource.stream(image) 
26+     source  =  get_rundata (db , runid )
27+ 
28+     tab_camera_displays  =  update_camera_displays (source , displays , runid )
29+     tab_timelines  =  update_timelines (source , timelines , runid )
30+ 
31+     # Combine panels into tabs 
32+     tabs  =  Tabs (
33+         tabs = [tab_camera_displays , tab_timelines ],
34+         sizing_mode = "scale_width" ,
35+     )
36+ 
37+     page_layout .children [1 ] =  tabs 
5738
5839
5940print ("Opening connection to ZODB" )
@@ -71,13 +52,13 @@ def update_camera_displays(attr, old, new):
7152
7253print ("Defining Select" )
7354# runid_input = NumericInput(value=db.root.keys()[-1], title="NectarCAM run number") 
55+ # run_select = Select(value=runid, title="NectarCAM run number", options=runids) 
7456run_select  =  Select (value = runid , title = "NectarCAM run number" , options = runids )
7557
7658print (f"Getting data for run { run_select .value }  )
7759source  =  get_rundata (db , run_select .value )
78- displays  =  make_camera_displays (db , source , runid )
79- 
80- run_select .on_change ("value" , update_camera_displays )
60+ displays  =  make_camera_displays (source , runid )
61+ timelines  =  make_timelines (source , runid )
8162
8263controls  =  row (run_select )
8364
@@ -88,15 +69,40 @@ def update_camera_displays(attr, old, new):
8869# update_camera_displays(attr, old, new) 
8970
9071ncols  =  3 
91- plots  =  [
72+ camera_displays  =  [
9273    displays [parentkey ][childkey ].figure 
9374    for  parentkey  in  displays .keys ()
9475    for  childkey  in  displays [parentkey ].keys ()
9576]
96- curdoc ().add_root (
97-     layout (
98-         [[controls ], [[plots [x  : x  +  ncols ] for  x  in  range (0 , len (plots ), ncols )]]],
99-         sizing_mode = "scale_width" ,
100-     )
77+ list_timelines  =  [
78+     timelines [parentkey ][childkey ]
79+     for  parentkey  in  timelines .keys ()
80+     for  childkey  in  timelines [parentkey ].keys ()
81+ ]
82+ 
83+ layout_camera_displays  =  gridplot (
84+     camera_displays ,
85+     ncols = ncols ,
86+ )
87+ 
88+ layout_timelines  =  gridplot (
89+     list_timelines ,
90+     ncols = 2 ,
91+ )
92+ 
93+ # Create different tabs 
94+ tab_camera_displays  =  TabPanel (child = layout_camera_displays , title = "Camera displays" )
95+ tab_timelines  =  TabPanel (child = layout_timelines , title = "Timelines" )
96+ 
97+ # Combine panels into tabs 
98+ tabs  =  Tabs (
99+     tabs = [tab_camera_displays , tab_timelines ],
101100)
101+ 
102+ page_layout  =  column ([controls , tabs ], sizing_mode = "scale_width" )
103+ 
104+ run_select .on_change ("value" , update )
105+ 
106+ # Add to the Bokeh document 
107+ curdoc ().add_root (page_layout )
102108curdoc ().title  =  "NectarCAM Data Quality Monitoring web app" 
0 commit comments