11import logging
2- import dash_bootstrap_components as dbc
3- from dash import html , dcc
4- from server import redisUtil
5- import dash_daq as daq
6- import numpy as np
7- import plotly .express as px
8- import pandas as pd
2+ from dash import dcc
3+ import dash
4+ from server import app , redisUtil
5+ from dash import Input , Output , html , State
6+ from dash .exceptions import PreventUpdate
97
108logger = logging .getLogger (__name__ )
9+ INTERPRETATION_ANALYSIS = ["DataVisualization" ]
10+ prefix = "data_"
1111
12- def get_data_summary_page ():
13- return html .Div ([
14- html .H4 (children = 'Data Summary' ),
15- get_summary ()
16- ])
12+
13+ def get_available_options (options ):
14+ result = [option for option in options if option in INTERPRETATION_ANALYSIS ]
15+ return result
1716
1817
19- def get_label_str (labels , label_name_dict ):
20- if label_name_dict == None or label_name_dict == "" :
21- labels_str = "," .join (str (i ) for i in labels )
22- else :
23- label_str = ""
24- for i , label in enumerate (label_name_dict ):
25- label_str += f"{ label } ({ label_name_dict [label ]} )"
26- if i < len (label_name_dict ) - 1 :
27- label_str += ", "
28- return label_str
18+ def get_data_summary_page ():
19+ redisUtil .request_available_analysis ()
20+ options = redisUtil .get_available_analysis ()
21+ options = get_available_options (options )
22+ choice = options [0 ] if (options is not None and len (options ) > 0 ) else None
23+ result = html .Div ([
24+ html .H4 ("Run analysis" ),
25+ dcc .Interval (
26+ id = prefix + 'interval-component' ,
27+ interval = 1 * 3000 , # in milliseconds
28+ n_intervals = 0 ),
29+ dcc .Dropdown (
30+ id = prefix + "analysis_selector" ,
31+ options = options ,
32+ value = choice ,
33+ persistence = True ),
34+ html .Button ("Run Analysis" , id = prefix + "run_analysis_button" , style = {"margin-top" : "20px" }),
35+ html .Div ([], id = prefix + "analysis_display" , style = {"margin-top" : "20px" })
36+ ], style = {})
37+ return result
2938
3039
31- def get_summary ():
32- data_summary = redisUtil .get_data_summary ()
40+ @app .callback (
41+ Output (prefix + 'analysis_selector' , 'options' ),
42+ Output (prefix + 'analysis_display' , 'children' ),
43+ Output (prefix + 'analysis_selector' , 'value' ),
44+ Input (prefix + 'interval-component' , 'n_intervals' ),
45+ Input (prefix + 'run_analysis_button' , 'n_clicks' ),
46+ Input (prefix + 'analysis_selector' , 'value' ),
47+ State (prefix + 'analysis_selector' , 'options' ),
48+ State (prefix + 'analysis_display' , 'children' ),
49+ )
50+ def get_analysis_updates (timer , btn , analysis_choice , analysis_choices , analysis_display ):
51+ ctx = dash .callback_context
52+ is_time_update = any (prefix + 'interval-component.n_intervals' in i ['prop_id' ] for i in ctx .triggered )
53+ is_button = any (prefix + 'run_analysis_button.n_clicks' in i ['prop_id' ] for i in ctx .triggered )
54+ is_value = any (prefix + 'analysis_selector.value' == i ['prop_id' ] for i in ctx .triggered )
55+ should_update = False
56+ force_new_display = False
3357
34- label_name = data_summary ["label_name" ]
35- target = data_summary ["pred_target" ]
36- labels = data_summary ["labels" ]
58+ if analysis_choices != get_available_options (redisUtil .get_available_analysis ()):
59+ analysis_choices = get_available_options (redisUtil .get_available_analysis ())
60+ should_update = True
61+ if analysis_choice is None and (analysis_choices is not None and len (analysis_choices ) > 0 ):
62+ analysis_choice = analysis_choices [0 ]
63+ force_new_display = True
3764
38- label_str = get_label_str ( labels , label_name )
39-
40- train_label_dist = data_summary [ "label_dist" ][ "train" ]
41- test_label_dist = data_summary [ "label_dist" ][ "test" ]
42- train_label_df = pd . DataFrame ({
43- "label" : train_label_dist . keys (),
44- "freq" : train_label_dist . values ()
45- })
46- test_label_df = pd . DataFrame ({
47- "label" : test_label_dist . keys (),
48- "freq" : test_label_dist . values ( )
49- })
65+ if is_time_update and analysis_choice is not None :
66+ if redisUtil . has_analysis_update ( analysis_choice , reset = True ):
67+ print ( "Analysis update: " )
68+ analysis_display = [ redisUtil . get_analysis ( analysis_choice ),
69+ html . P ( analysis_choice , style = { "display" : "none" })]
70+ return analysis_choices , analysis_display
71+ if is_button :
72+ if analysis_choice is None or analysis_choice == "" :
73+ return analysis_choices , [ html . P ( "Please select an analysis" )]
74+ else :
75+ redisUtil . request_start_analysis ( analysis_choice )
76+ return redisUtil . get_available_analysis (), [ html . P ( "Requesting Analysis.." )]
5077
51- train_hist = px .bar (train_label_df , x = "label" , y = "freq" , labels = {})
52- test_hist = px .bar (test_label_df , x = "label" , y = "freq" , labels = {})
53- train_hist .update_layout ({"margin" :{"l" :0 , "r" :0 , "t" :0 , "b" :0 }})
54- train_hist .update_layout (xaxis = {"visible" : True , "showticklabels" : True , "title" : None }, yaxis = {"visible" : False , "showticklabels" : False })
55- test_hist .update_layout ({"margin" :{"l" :0 , "r" :0 , "t" :0 , "b" :0 }})
56- test_hist .update_layout (xaxis = {"visible" : True , "showticklabels" : True , "title" : None }, yaxis = {"visible" : False , "showticklabels" : False })
78+ # Extra condition was added because dash would not always update when changing to/from a large analysis
79+ if force_new_display or is_value or (analysis_choice and analysis_display == []) \
80+ or ((len (analysis_display ) > 1 and analysis_choice != analysis_display [1 ].get ("props" , {}).get ("children" , {}))):
81+ print ("Value triggered" )
82+ analysis_display = [redisUtil .get_analysis (analysis_choice ),
83+ html .P (analysis_choice , style = {"display" : "none" })]
84+ should_update = True
5785
58- row_target = html .Tr ([
59- html .Td ("Target" , className = "data-summary-title" ),
60- html .Td (target , className = "data-summary-content" ),
61- ], className = "data-summary-main-row" )
62- row_label = html .Tr ([
63- html .Td ("Labels" , className = "data-summary-title" ),
64- html .Td (label_str , className = "data-summary-content" )
65- ], className = "data-summary-main-row" )
66-
67- row_histogram = html .Tr ([
68- html .Td ("Label Distribution" , className = "data-summary-title" ),
69- html .Td (get_histogram_cell (train_hist , test_hist ))
70- ], className = "data-summary-main-row" )
86+ if not should_update :
87+ raise PreventUpdate
7188
72- return dbc .Table (
73- [row_target , row_label , row_histogram ],
74- striped = True ,
75- borderless = True ,
76- )
89+ return analysis_choices , analysis_display , analysis_choice
7790
78- def get_histogram_cell (train_hist , test_hist ):
79- return dbc .Table ([
80- html .Tr ([
81- html .Td ("Train Data" , className = "data-summary-content-hist-title" ),
82- html .Td ("Test Data" , className = "data-summary-content-hist-title" )
83- ]),
84- html .Tr ([
85- html .Td ([
86- dcc .Graph (figure = train_hist , className = "data-summary-content-hist" , config = {"responsive" : True })
87- ], className = "data-summary-content-half" ),
88- html .Td ([
89- dcc .Graph (figure = test_hist , className = "data-summary-content-hist" , config = {"responsive" : True })
90- ], className = "data-summary-content-half" )
91- ])
92- ], borderless = True , style = {"margin" : 0 })
0 commit comments