armanddemasson commited on
Commit
1700186
·
1 Parent(s): 4df74e4

feat: added 2 new talk to data plots

Browse files
app.py CHANGED
@@ -152,20 +152,17 @@ def create_drias_tab():
152
  prev_button = gr.Button("Previous")
153
  next_button = gr.Button("Next")
154
 
155
- # Initialisation des données
156
  sql_queries_state = gr.State([])
157
  dataframes_state = gr.State([])
158
  plots_state = gr.State([])
159
  index_state = gr.State(0) # To track the current position
160
 
161
- # Action sur la soumission du texte
162
  drias_direct_question.submit(
163
  ask_drias_query,
164
  inputs=[drias_direct_question, index_state],
165
  outputs=[drias_sql_query, drias_table, drias_display, sql_queries_state, dataframes_state, plots_state, index_state]
166
  )
167
 
168
- # Define functions to navigate history
169
  def show_previous(index, sql_queries, dataframes, plots):
170
  if index > 0:
171
  index -= 1
 
152
  prev_button = gr.Button("Previous")
153
  next_button = gr.Button("Next")
154
 
 
155
  sql_queries_state = gr.State([])
156
  dataframes_state = gr.State([])
157
  plots_state = gr.State([])
158
  index_state = gr.State(0) # To track the current position
159
 
 
160
  drias_direct_question.submit(
161
  ask_drias_query,
162
  inputs=[drias_direct_question, index_state],
163
  outputs=[drias_sql_query, drias_table, drias_display, sql_queries_state, dataframes_state, plots_state, index_state]
164
  )
165
 
 
166
  def show_previous(index, sql_queries, dataframes, plots):
167
  if index > 0:
168
  index -= 1
climateqa/engine/talk_to_data/main.py CHANGED
@@ -19,16 +19,17 @@ def ask_drias(db_drias_path:str, query:str , index_state: int):
19
  result_dataframes = []
20
  figures = []
21
 
 
22
  for plot_state in final_state['plot_states'].values():
23
  for table_state in plot_state['table_states'].values():
24
-
25
- if 'ql_query' in table_state and table_state['sql_query'] is not None:
26
- sql_queries.append(table_state['sql_query'])
27
-
28
- if 'dataframe' in table_state and table_state['dataframe'] is not None:
29
- result_dataframes.append(table_state['dataframe'])
30
- if 'figure' in table_state and table_state['figure'] is not None:
31
- figures.append(table_state['figure'](table_state['dataframe']))
32
 
33
  return sql_queries[index_state], result_dataframes[index_state], figures[index_state], sql_queries, result_dataframes, figures, index_state
34
 
 
19
  result_dataframes = []
20
  figures = []
21
 
22
+
23
  for plot_state in final_state['plot_states'].values():
24
  for table_state in plot_state['table_states'].values():
25
+ if table_state['status'] == 'OK':
26
+ if 'sql_query' in table_state and table_state['sql_query'] is not None:
27
+ sql_queries.append(table_state['sql_query'])
28
+
29
+ if 'dataframe' in table_state and table_state['dataframe'] is not None:
30
+ result_dataframes.append(table_state['dataframe'])
31
+ if 'figure' in table_state and table_state['figure'] is not None:
32
+ figures.append(table_state['figure'](table_state['dataframe']))
33
 
34
  return sql_queries[index_state], result_dataframes[index_state], figures[index_state], sql_queries, result_dataframes, figures, index_state
35
 
climateqa/engine/talk_to_data/plot.py CHANGED
@@ -1,9 +1,14 @@
1
  from typing import Callable, TypedDict
 
2
  import pandas as pd
3
  from plotly.graph_objects import Figure
4
  import plotly.graph_objects as go
 
5
 
6
- from climateqa.engine.talk_to_data.sql_query import indicator_per_year_at_location_query
 
 
 
7
 
8
 
9
  class Plot(TypedDict):
@@ -14,7 +19,7 @@ class Plot(TypedDict):
14
  sql_query: Callable[..., str]
15
 
16
 
17
- def plot_indicator_per_year_at_location(params: dict) -> Callable[..., Figure]:
18
  """Generate the function to plot a line plot of an indicator per year at a certain location
19
 
20
  Args:
@@ -25,6 +30,7 @@ def plot_indicator_per_year_at_location(params: dict) -> Callable[..., Figure]:
25
  """
26
  indicator = params["indicator_column"]
27
  model = params["model"]
 
28
  indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
29
 
30
  def plot_data(df: pd.DataFrame) -> Figure:
@@ -74,6 +80,7 @@ def plot_indicator_per_year_at_location(params: dict) -> Callable[..., Figure]:
74
  y=indicators,
75
  name=f"Yearly {indicator_label}",
76
  mode="lines",
 
77
  )
78
 
79
  # Sliding average dashed line
@@ -83,10 +90,10 @@ def plot_indicator_per_year_at_location(params: dict) -> Callable[..., Figure]:
83
  mode="lines",
84
  name="10 years rolling average",
85
  line=dict(dash="dash"),
86
- marker=dict(color="#1f77b4"),
87
  )
88
  fig.update_layout(
89
- title=f"Plot of {indicator_label} in {params['location']} (Model Average)",
90
  xaxis_title="Year",
91
  yaxis_title=indicator_label,
92
  template="plotly_white",
@@ -96,16 +103,18 @@ def plot_indicator_per_year_at_location(params: dict) -> Callable[..., Figure]:
96
  return plot_data
97
 
98
 
99
- indicator_per_year_at_location: Plot = {
100
- "name": "Indicator per year at location",
101
- "description": "Plot an evolution of the indicator at a certain location over the years",
102
  "params": ["indicator_column", "location", "model"],
103
- "plot_function": plot_indicator_per_year_at_location,
104
  "sql_query": indicator_per_year_at_location_query,
105
  }
106
 
107
 
108
- def plot_indicator_number_of_days_per_year_at_location(params) -> Callable[..., Figure]:
 
 
109
  """Generate the function to plot a line plot of an indicator per year at a certain location
110
 
111
  Args:
@@ -117,10 +126,19 @@ def plot_indicator_number_of_days_per_year_at_location(params) -> Callable[...,
117
 
118
  indicator = params["indicator_column"]
119
  model = params["model"]
 
 
 
 
 
 
 
120
 
121
- def plot_data(df) -> Figure:
 
 
122
  fig = go.Figure()
123
- if params["model"] == "ALL":
124
  df_avg = df.groupby("year", as_index=False)[indicator].mean()
125
 
126
  # Transform to list to avoid pandas encoding
@@ -147,10 +165,10 @@ def plot_indicator_number_of_days_per_year_at_location(params) -> Callable[...,
147
  indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
148
 
149
  fig.update_layout(
150
- title=f"{indicator_label} in {params['location']} (Model Average)",
151
  xaxis_title="Year",
152
  yaxis_title=indicator,
153
- yaxis=dict(range=[0, 366]),
154
  bargap=0.5,
155
  template="plotly_white",
156
  )
@@ -169,4 +187,152 @@ indicator_number_of_days_per_year_at_location: Plot = {
169
  }
170
 
171
 
172
- PLOTS = [indicator_per_year_at_location, indicator_number_of_days_per_year_at_location]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from typing import Callable, TypedDict
2
+ from matplotlib.figure import figaspect
3
  import pandas as pd
4
  from plotly.graph_objects import Figure
5
  import plotly.graph_objects as go
6
+ import plotly.express as px
7
 
8
+ from climateqa.engine.talk_to_data.sql_query import (
9
+ indicator_for_given_year_query,
10
+ indicator_per_year_at_location_query,
11
+ )
12
 
13
 
14
  class Plot(TypedDict):
 
19
  sql_query: Callable[..., str]
20
 
21
 
22
+ def plot_indicator_evolution_at_location(params: dict) -> Callable[..., Figure]:
23
  """Generate the function to plot a line plot of an indicator per year at a certain location
24
 
25
  Args:
 
30
  """
31
  indicator = params["indicator_column"]
32
  model = params["model"]
33
+ location = params["location"]
34
  indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
35
 
36
  def plot_data(df: pd.DataFrame) -> Figure:
 
80
  y=indicators,
81
  name=f"Yearly {indicator_label}",
82
  mode="lines",
83
+ marker=dict(color="#1f77b4"),
84
  )
85
 
86
  # Sliding average dashed line
 
90
  mode="lines",
91
  name="10 years rolling average",
92
  line=dict(dash="dash"),
93
+ marker=dict(color="#d62728"),
94
  )
95
  fig.update_layout(
96
+ title=f"Plot of {indicator_label} in {location} {'(Model Average)' if model == 'ALL' else '(Model : ' + model + ')'}",
97
  xaxis_title="Year",
98
  yaxis_title=indicator_label,
99
  template="plotly_white",
 
103
  return plot_data
104
 
105
 
106
+ indicator_evolution_at_location: Plot = {
107
+ "name": "Indicator evolution at location",
108
+ "description": "Plot an evolution of the indicator at a certain location",
109
  "params": ["indicator_column", "location", "model"],
110
+ "plot_function": plot_indicator_evolution_at_location,
111
  "sql_query": indicator_per_year_at_location_query,
112
  }
113
 
114
 
115
+ def plot_indicator_number_of_days_per_year_at_location(
116
+ params: dict,
117
+ ) -> Callable[..., Figure]:
118
  """Generate the function to plot a line plot of an indicator per year at a certain location
119
 
120
  Args:
 
126
 
127
  indicator = params["indicator_column"]
128
  model = params["model"]
129
+ location = params["location"]
130
+
131
+ def plot_data(df: pd.DataFrame) -> Figure:
132
+ """Generate the figure thanks to the dataframe
133
+
134
+ Args:
135
+ df (pd.DataFrame): pandas dataframe with the required data
136
 
137
+ Returns:
138
+ Figure: Plotly figure
139
+ """
140
  fig = go.Figure()
141
+ if model == "ALL":
142
  df_avg = df.groupby("year", as_index=False)[indicator].mean()
143
 
144
  # Transform to list to avoid pandas encoding
 
165
  indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
166
 
167
  fig.update_layout(
168
+ title=f"{indicator_label} in {location} {'(Model Average)' if model == 'ALL' else '(Model : ' + model + ')'}",
169
  xaxis_title="Year",
170
  yaxis_title=indicator,
171
+ yaxis=dict(range=[0, max(indicators)]),
172
  bargap=0.5,
173
  template="plotly_white",
174
  )
 
187
  }
188
 
189
 
190
+ def plot_distribution_of_indicator_for_given_year(
191
+ params: dict,
192
+ ) -> Callable[..., Figure]:
193
+ """Generate an histogram of the distribution of an indicator for a given year
194
+
195
+ Args:
196
+ params (dict): dictionnary with the required params : model, indicator_column, year
197
+
198
+ Returns:
199
+ Callable[..., Figure]: Function which can be call to create the figure with the associated dataframe
200
+ """
201
+ indicator = params["indicator_column"]
202
+ model = params["model"]
203
+ year = params["year"]
204
+ indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
205
+
206
+ def plot_data(df: pd.DataFrame) -> Figure:
207
+ """Generate the figure thanks to the dataframe
208
+
209
+ Args:
210
+ df (pd.DataFrame): pandas dataframe with the required data
211
+
212
+ Returns:
213
+ Figure: Plotly figure
214
+ """
215
+ fig = go.Figure()
216
+ if params["model"] == "ALL":
217
+ df_avg = df.groupby(["latitude", "longitude"], as_index=False)[
218
+ indicator
219
+ ].mean()
220
+
221
+ # Transform to list to avoid pandas encoding
222
+ indicators = df_avg[indicator].astype(float).tolist()
223
+ else:
224
+ df_model = df[df["model"] == model]
225
+
226
+ # Transform to list to avoid pandas encoding
227
+ indicators = df_model[indicator].astype(float).tolist()
228
+
229
+ fig.add_trace(
230
+ go.Histogram(
231
+ x=indicators,
232
+ opacity=0.8,
233
+ histnorm="percent",
234
+ marker=dict(color="#1f77b4"),
235
+ )
236
+ )
237
+
238
+ fig.update_layout(
239
+ title=f"Distribution of {indicator_label} in {year} {'(Model Average)' if model == 'ALL' else '(Model : ' + model + ')'}",
240
+ xaxis_title=indicator_label,
241
+ yaxis_title="Frequency",
242
+ plot_bgcolor="rgba(0, 0, 0, 0)",
243
+ showlegend=False,
244
+ )
245
+
246
+ return fig
247
+
248
+ return plot_data
249
+
250
+
251
+ distribution_of_indicator_for_given_year: Plot = {
252
+ "name": "Distribution of an indicator for a given year",
253
+ "description": "Plot an histogram of the distribution for a given year of the values of an indicator ",
254
+ "params": ["indicator_column", "model", "year"],
255
+ "plot_function": plot_distribution_of_indicator_for_given_year,
256
+ "sql_query": indicator_for_given_year_query,
257
+ }
258
+
259
+
260
+ def plot_map_of_france_of_indicator_for_given_year(
261
+ params: dict,
262
+ ) -> Callable[..., Figure]:
263
+ """Generate a plot of the map of France for an indicator at a given year
264
+
265
+ Args:
266
+ params (dict): dictionnary with the required params : model, indicator_column, year
267
+
268
+ Returns:
269
+ Callable[..., Figure]: Function which can be call to create the figure with the associated dataframe
270
+ """
271
+
272
+ indicator = params["indicator_column"]
273
+ model = params["model"]
274
+ year = params["year"]
275
+ indicator_label = " ".join([word.capitalize() for word in indicator.split("_")])
276
+
277
+ def plot_data(df: pd.DataFrame) -> Figure:
278
+ fig = go.Figure()
279
+ if model == "ALL":
280
+ df_avg = df.groupby(["latitude", "longitude"], as_index=False)[
281
+ indicator
282
+ ].mean()
283
+
284
+ indicators = df_avg[indicator].astype(float).tolist()
285
+ latitudes = df_avg["latitude"].astype(float).tolist()
286
+ longitudes = df_avg["longitude"].astype(float).tolist()
287
+
288
+ else:
289
+ df_model = df[df["model"] == model]
290
+
291
+ # Transform to list to avoid pandas encoding
292
+ indicators = df_model[indicator].astype(float).tolist()
293
+ latitudes = df_model["latitude"].astype(float).tolist()
294
+ longitudes = df_model["longitude"].astype(float).tolist()
295
+
296
+ fig.add_trace(
297
+ go.Scattermapbox(
298
+ lat=latitudes,
299
+ lon=longitudes,
300
+ mode="markers",
301
+ marker=dict(
302
+ size=10,
303
+ color=indicators, # Color mapped to values
304
+ colorscale="Turbo", # Color scale (can be 'Plasma', 'Jet', etc.)
305
+ cmin=min(indicators), # Minimum color range
306
+ cmax=max(indicators), # Maximum color range
307
+ showscale=True, # Show colorbar
308
+ ),
309
+ )
310
+ )
311
+
312
+ fig.update_layout(
313
+ mapbox_style="open-street-map", # Use OpenStreetMap
314
+ mapbox_zoom=3,
315
+ mapbox_center={"lat": 46.6, "lon": 2.0},
316
+ coloraxis_colorbar=dict(title=f"{indicator_label}"), # Add legend
317
+ title=f"{indicator_label} in {year} in France", # Title
318
+ )
319
+ return fig
320
+
321
+ return plot_data
322
+
323
+
324
+ map_of_france_of_indicator_for_given_year: Plot = {
325
+ "name": "Map of France of an indicator for a given year",
326
+ "description": "Heatmap on the map of France of the values of an in indicator for a given year",
327
+ "params": ["indicator_column", "year", "model"],
328
+ "plot_function": plot_map_of_france_of_indicator_for_given_year,
329
+ "sql_query": indicator_for_given_year_query,
330
+ }
331
+
332
+
333
+ PLOTS = [
334
+ indicator_evolution_at_location,
335
+ indicator_number_of_days_per_year_at_location,
336
+ distribution_of_indicator_for_given_year,
337
+ map_of_france_of_indicator_for_given_year,
338
+ ]
climateqa/engine/talk_to_data/sql_query.py CHANGED
@@ -39,10 +39,10 @@ def execute_sql_query(db_path: str, sql_query: str) -> SqlQueryOutput:
39
 
40
 
41
  class IndicatorPerYearAtLocationQueryParams(TypedDict, total=False):
42
- table: str
43
- indicator_column: list[str]
44
  latitude: str
45
  longitude: str
 
46
 
47
 
48
  def indicator_per_year_at_location_query(
@@ -60,5 +60,34 @@ def indicator_per_year_at_location_query(
60
  indicator_column = params.get("indicator_column")
61
  latitude = params.get("latitude")
62
  longitude = params.get("longitude")
63
- sql_query = f"SELECT year, {indicator_column}, model FROM {table} WHERE latitude = {latitude} and longitude={longitude} Order by Year"
 
 
 
64
  return sql_query
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
 
41
  class IndicatorPerYearAtLocationQueryParams(TypedDict, total=False):
42
+ indicator_column: str
 
43
  latitude: str
44
  longitude: str
45
+ model: str
46
 
47
 
48
  def indicator_per_year_at_location_query(
 
60
  indicator_column = params.get("indicator_column")
61
  latitude = params.get("latitude")
62
  longitude = params.get("longitude")
63
+
64
+ if indicator_column is None or latitude is None or longitude is None: # If one parameter is missing, returns an empty query
65
+ return ""
66
+ sql_query = f"SELECT year, {indicator_column}, model\nFROM {table}\nWHERE latitude = {latitude} \nand longitude={longitude} \nOrder by Year"
67
  return sql_query
68
+
69
+ class IndicatorForGivenYearQueryParams(TypedDict, total=False):
70
+ indicator_column: str
71
+ year: str
72
+ model: str
73
+
74
+ def indicator_for_given_year_query(
75
+ table:str, params: IndicatorForGivenYearQueryParams
76
+ ) -> str:
77
+ """SQL Query to get the values of an indicator with their latitudes, longitudes and models for a given year
78
+
79
+ Args:
80
+ table (str): sql table of the indicator
81
+ params (IndicatorForGivenYearQueryParams): dictionarry with the required params for the query
82
+
83
+ Returns:
84
+ str: the sql query
85
+ """
86
+ indicator_column = params.get("indicator_column")
87
+ year = params.get('year')
88
+
89
+ if year is None or indicator_column is None: # If one parameter is missing, returns an empty query
90
+ return ""
91
+
92
+ sql_query = f"Select {indicator_column}, latitude, longitude, model\nFrom {table}\nWhere year = {year}"
93
+ return sql_query
climateqa/engine/talk_to_data/workflow.py CHANGED
@@ -9,6 +9,7 @@ from climateqa.engine.talk_to_data.plot import PLOTS, Plot
9
  from climateqa.engine.talk_to_data.sql_query import execute_sql_query
10
  from climateqa.engine.talk_to_data.utils import (
11
  detect_relevant_plots,
 
12
  loc2coords,
13
  detect_location_with_openai,
14
  nearestNeighbourSQL,
@@ -25,6 +26,7 @@ class TableState(TypedDict):
25
  sql_query: NotRequired[str]
26
  dataframe: NotRequired[pd.DataFrame | None]
27
  figure: NotRequired[Callable[..., Figure]]
 
28
 
29
  class PlotState(TypedDict):
30
  plot_name: str
@@ -82,6 +84,7 @@ def drias_workflow(db_drias_path: str, user_input: str) -> State:
82
  table_state: TableState = {
83
  'table_name': table,
84
  'params': {},
 
85
  }
86
  table_state['params'] = {
87
  'model': 'ALL'
@@ -92,6 +95,11 @@ def drias_workflow(db_drias_path: str, user_input: str) -> State:
92
  table_state['params'].update(param)
93
 
94
  sql_query = plot['sql_query'](table, table_state['params'])
 
 
 
 
 
95
  table_state['sql_query'] = sql_query
96
  results = execute_sql_query(db_drias_path, sql_query)
97
 
@@ -134,6 +142,9 @@ def find_param(state: State, param_name:str, table: str, db_path: str) -> dict[s
134
  if param_name == 'indicator_column':
135
  indicator_column = find_indicator_column(table)
136
  return {'indicator_column': indicator_column}
 
 
 
137
  return None
138
 
139
 
@@ -155,6 +166,11 @@ def find_location(user_input: str, table: str, db_path: str) -> Location:
155
  })
156
  return output
157
 
 
 
 
 
 
158
  def find_indicator_column(table: str) -> str:
159
  """Retrieve the name of the indicator column within the table in the database
160
 
@@ -178,12 +194,13 @@ def find_indicator_column(table: str) -> str:
178
  "mean_annual_temperature": "mean_annual_temperature",
179
  "number_of_tropical_nights": "number_tropical_nights",
180
  "maximum_summer_temperature": "maximum_summer_temperature",
181
- "number_of_days_with_TX_above_30": "number_of_days_with_tx_above_30",
182
- "number_of_days_with_TX_above_35": "number_of_days_with_tx_above_35",
183
  "number_of_days_with_a_dry_ground": "number_of_days_with_dry_ground"
184
  }
185
  return indicator_columns_per_table[table]
186
 
 
187
  # def make_write_query_node():
188
 
189
  # def write_query(state):
@@ -230,4 +247,4 @@ def find_indicator_column(table: str) -> str:
230
  # output.update(fetch_data_from_sql_query(db_path, sql_query))
231
  # return output
232
 
233
- # return fetch_data
 
9
  from climateqa.engine.talk_to_data.sql_query import execute_sql_query
10
  from climateqa.engine.talk_to_data.utils import (
11
  detect_relevant_plots,
12
+ detect_year_with_openai,
13
  loc2coords,
14
  detect_location_with_openai,
15
  nearestNeighbourSQL,
 
26
  sql_query: NotRequired[str]
27
  dataframe: NotRequired[pd.DataFrame | None]
28
  figure: NotRequired[Callable[..., Figure]]
29
+ status: str
30
 
31
  class PlotState(TypedDict):
32
  plot_name: str
 
84
  table_state: TableState = {
85
  'table_name': table,
86
  'params': {},
87
+ 'status': 'OK'
88
  }
89
  table_state['params'] = {
90
  'model': 'ALL'
 
95
  table_state['params'].update(param)
96
 
97
  sql_query = plot['sql_query'](table, table_state['params'])
98
+
99
+ if sql_query == "":
100
+ table_state['status'] = 'ERROR'
101
+ continue
102
+
103
  table_state['sql_query'] = sql_query
104
  results = execute_sql_query(db_drias_path, sql_query)
105
 
 
142
  if param_name == 'indicator_column':
143
  indicator_column = find_indicator_column(table)
144
  return {'indicator_column': indicator_column}
145
+ if param_name == 'year':
146
+ year = find_year(state['user_input'])
147
+ return {'year': year}
148
  return None
149
 
150
 
 
166
  })
167
  return output
168
 
169
+ def find_year(user_input: str) -> str:
170
+ print(f"---- Find year ---")
171
+ year = detect_year_with_openai(user_input)
172
+ return year
173
+
174
  def find_indicator_column(table: str) -> str:
175
  """Retrieve the name of the indicator column within the table in the database
176
 
 
194
  "mean_annual_temperature": "mean_annual_temperature",
195
  "number_of_tropical_nights": "number_tropical_nights",
196
  "maximum_summer_temperature": "maximum_summer_temperature",
197
+ "number_of_days_with_tx_above_30": "number_of_days_with_tx_above_30",
198
+ "number_of_days_with_tx_above_35": "number_of_days_with_tx_above_35",
199
  "number_of_days_with_a_dry_ground": "number_of_days_with_dry_ground"
200
  }
201
  return indicator_columns_per_table[table]
202
 
203
+
204
  # def make_write_query_node():
205
 
206
  # def write_query(state):
 
247
  # output.update(fetch_data_from_sql_query(db_path, sql_query))
248
  # return output
249
 
250
+ # return fetch_data