mriusero commited on
Commit
1ee80e7
·
1 Parent(s): 3273528

feat: perf2

Browse files
Files changed (1) hide show
  1. src/ui/dashboard.py +39 -25
src/ui/dashboard.py CHANGED
@@ -1,24 +1,28 @@
1
  import gradio as gr
2
  import pandas as pd
3
  import asyncio
 
4
 
5
  from src.production.flow import generate_data
6
  from src.production.metrics.tools import tools_metrics
7
  from src.production.metrics.machine import machine_metrics, fetch_issues
8
  from src.ui.graphs.tools_graphs import ToolMetricsDisplay
9
 
 
 
 
 
 
10
 
11
  async def dataflow(state):
12
  """
13
- Main dataflow function that processes raw production data and updates the state with tool metrics, machine efficiency, and issues.
 
14
  """
15
- if 'tools' not in state['data']:
16
- state['data']['tools'] = {}
17
-
18
- if 'issues' not in state['data']:
19
- state['data']['issues'] = {}
20
 
21
- if state['running']:
22
  if 'gen_task' not in state or state['gen_task'] is None or state['gen_task'].done():
23
  state['gen_task'] = asyncio.create_task(generate_data(state))
24
 
@@ -26,6 +30,17 @@ async def dataflow(state):
26
  if raw_data.empty:
27
  return [pd.DataFrame()] * 4
28
 
 
 
 
 
 
 
 
 
 
 
 
29
  tools_data = await tools_metrics(raw_data)
30
  tools_data = {tool: df for tool, df in tools_data.items() if not df.empty}
31
  for tool, df in tools_data.items():
@@ -42,13 +57,11 @@ async def dataflow(state):
42
  for i in range(1, 5)
43
  ]
44
 
45
-
46
- def create_display_and_plots(df):
47
  """
48
- Create a ToolMetricsDisplay instance and generate plots for the provided DataFrame.
49
  """
50
- display = ToolMetricsDisplay()
51
- plots = [
52
  display.normal_curve(df, cote='pos'),
53
  display.gauge(df, type='cp', cote='pos'),
54
  display.gauge(df, type='cpk', cote='pos'),
@@ -57,12 +70,10 @@ def create_display_and_plots(df):
57
  display.gauge(df, type='cpk', cote='ori'),
58
  display.control_graph(df),
59
  ]
60
- return display, plots
61
-
62
 
63
  def init_displays_and_blocks(n=4):
64
  """
65
- Initialize a list of ToolMetricsDisplay instances and their corresponding blocks.
66
  """
67
  displays = []
68
  blocks = []
@@ -72,24 +83,27 @@ def init_displays_and_blocks(n=4):
72
  blocks.extend(display.tool_block(df=pd.DataFrame(), id=i))
73
  return displays, blocks
74
 
75
-
76
- def dashboard_ui(state):
77
  """
78
- Create the Gradio UI for the dashboard, initializing displays and setting up the dataflow.
 
79
  """
80
- displays, initial_plots = init_displays_and_blocks()
81
-
82
- async def on_tick(state):
83
  dfs = await dataflow(state)
84
  all_plots = []
85
- for df in dfs:
86
- _, plots = create_display_and_plots(df)
87
  all_plots.extend(plots)
88
  return all_plots + [state]
89
 
90
- timer = gr.Timer(0.1)
 
 
 
 
 
91
  timer.tick(
92
- fn=on_tick,
93
  inputs=[state],
94
  outputs=initial_plots + [state]
95
  )
 
1
  import gradio as gr
2
  import pandas as pd
3
  import asyncio
4
+ from functools import partial
5
 
6
  from src.production.flow import generate_data
7
  from src.production.metrics.tools import tools_metrics
8
  from src.production.metrics.machine import machine_metrics, fetch_issues
9
  from src.ui.graphs.tools_graphs import ToolMetricsDisplay
10
 
11
+ MAX_ROWS = 1000
12
+
13
+ def hash_dataframe(df):
14
+ """Computes a simple hash to detect changes in the DataFrame."""
15
+ return pd.util.hash_pandas_object(df).sum()
16
 
17
  async def dataflow(state):
18
  """
19
+ Main function that updates data if necessary.
20
+ Avoids processing if the raw data hasn't changed.
21
  """
22
+ state.setdefault('data', {}).setdefault('tools', {})
23
+ state['data'].setdefault('issues', {})
 
 
 
24
 
25
+ if state.get('running'):
26
  if 'gen_task' not in state or state['gen_task'] is None or state['gen_task'].done():
27
  state['gen_task'] = asyncio.create_task(generate_data(state))
28
 
 
30
  if raw_data.empty:
31
  return [pd.DataFrame()] * 4
32
 
33
+ if len(raw_data) > MAX_ROWS:
34
+ raw_data = raw_data.tail(MAX_ROWS)
35
+
36
+ current_hash = hash_dataframe(raw_data)
37
+ if state.get('last_hash') == current_hash:
38
+ return [
39
+ pd.DataFrame(state['data']['tools'].get(f'tool_{i}', pd.DataFrame()))
40
+ for i in range(1, 5)
41
+ ]
42
+ state['last_hash'] = current_hash
43
+
44
  tools_data = await tools_metrics(raw_data)
45
  tools_data = {tool: df for tool, df in tools_data.items() if not df.empty}
46
  for tool, df in tools_data.items():
 
57
  for i in range(1, 5)
58
  ]
59
 
60
+ def update_display_and_plots(df, display):
 
61
  """
62
+ Uses an existing instance of ToolMetricsDisplay to generate plots.
63
  """
64
+ return [
 
65
  display.normal_curve(df, cote='pos'),
66
  display.gauge(df, type='cp', cote='pos'),
67
  display.gauge(df, type='cpk', cote='pos'),
 
70
  display.gauge(df, type='cpk', cote='ori'),
71
  display.control_graph(df),
72
  ]
 
 
73
 
74
  def init_displays_and_blocks(n=4):
75
  """
76
+ Initializes the graphical objects (ToolMetricsDisplay) and their associated blocks.
77
  """
78
  displays = []
79
  blocks = []
 
83
  blocks.extend(display.tool_block(df=pd.DataFrame(), id=i))
84
  return displays, blocks
85
 
86
+ async def on_tick(state, displays):
 
87
  """
88
+ Tick function called periodically: updates plots only if data has changed.
89
+ Uses a lock to prevent concurrent execution.
90
  """
91
+ async with state.setdefault('lock', asyncio.Lock()):
 
 
92
  dfs = await dataflow(state)
93
  all_plots = []
94
+ for df, display in zip(dfs, displays):
95
+ plots = update_display_and_plots(df, display)
96
  all_plots.extend(plots)
97
  return all_plots + [state]
98
 
99
+ def dashboard_ui(state):
100
+ """
101
+ Creates the Gradio interface and sets a refresh every second.
102
+ """
103
+ displays, initial_plots = init_displays_and_blocks()
104
+ timer = gr.Timer(1.0)
105
  timer.tick(
106
+ fn=partial(on_tick, displays=displays),
107
  inputs=[state],
108
  outputs=initial_plots + [state]
109
  )