From fa72472ff5ec88795eae174e448596623cddba00 Mon Sep 17 00:00:00 2001 From: Juri Date: Thu, 9 Mar 2023 00:37:20 +0100 Subject: [PATCH 1/7] ENH: Convert int raw data to float measurement --- dashboard/callbacks.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dashboard/callbacks.py b/dashboard/callbacks.py index de1768c..1a95b6d 100644 --- a/dashboard/callbacks.py +++ b/dashboard/callbacks.py @@ -6,6 +6,7 @@ from aerosense_tools.plots import plot_connection_statistic, plot_pressure_bar_chart, plot_sensors from aerosense_tools.queries import ROW_LIMIT, BigQuery +from aerosense_tools.preprocess import RawSignal from aerosense_tools.utils import generate_time_range, get_cleaned_sensor_column_names @@ -192,7 +193,14 @@ def plot_sensors_graph( finish=finish, ) - figure = plot_sensors(df, line_descriptions=sensor_types[sensor_name]["variable"]) + data_columns = df.columns[df.columns.str.startswith('f')].tolist() + sensor_data = df[["datetime"] + data_columns].set_index('datetime') + raw_data = RawSignal(sensor_data, sensor_name) + raw_data.measurement_to_variable() + plot_df = raw_data.dataframe.reset_index() + + figure = plot_sensors(plot_df, line_descriptions=sensor_types[sensor_name]["variable"]) + figure.update_layout(height=800) if data_limit_applied: return (figure, f"Large amount of data - the query has been limited to the latest {ROW_LIMIT} datapoints.") From eff6f3f930b6d307823c177964627a3de06ee935 Mon Sep 17 00:00:00 2001 From: Juri Date: Thu, 9 Mar 2023 01:10:16 +0100 Subject: [PATCH 2/7] ENH: Improve custom time selection layout --- dashboard/layouts.py | 71 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/dashboard/layouts.py b/dashboard/layouts.py index bb54887..2544e90 100644 --- a/dashboard/layouts.py +++ b/dashboard/layouts.py @@ -39,38 +39,45 @@ def create_sensors_tab_layout(app, tab_name, sensor_names, graph_id, data_limit_ html.Label(html.B("Time range")), TimeRangeSelect(), html.Br(), - html.Label(html.B("Custom time range")), - html.Label("Start datetime"), - dcc.DatePickerSingle( - id="start-date", - date=datetime.datetime.now().date().isoformat(), - display_format="Do MMM Y", - persistence=True, - disabled=True, - ), - html.Br(), - html.Label("Hour"), - dash_daq.NumericInput(id="start-hour", value=0, min=0, max=23, persistence=True), - html.Label("Minute"), - dash_daq.NumericInput(id="start-minute", value=0, min=0, max=59, persistence=True), - html.Label("Second"), - dash_daq.NumericInput(id="start-second", value=0, min=0, max=59, persistence=True), - html.Br(), - html.Label("End datetime"), - dcc.DatePickerSingle( - id="end-date", - display_format="Do MMM Y", - persistence=True, - disabled=True, - ), - html.Br(), - html.Label("Hour"), - dash_daq.NumericInput(id="end-hour", value=0, min=0, max=23, persistence=True), - html.Label("Minute"), - dash_daq.NumericInput(id="end-minute", value=0, min=0, max=59, persistence=True), - html.Label("Second"), - dash_daq.NumericInput(id="end-second", value=0, min=0, max=59, persistence=True), - html.Br(), + html.Label("Custom time range"), + html.Div([html.Div([html.Label("Start datetime"), + dcc.DatePickerSingle(id="start-date", + date=datetime.datetime.now().date().isoformat(), + display_format="Do MMM Y", + persistence=True, + disabled=True, ), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Hour"), + dash_daq.NumericInput(id="start-hour", value=0, min=0, max=23, + persistence=True), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Minute"), + dash_daq.NumericInput(id="start-minute", value=0, min=0, max=59, + persistence=True), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Second"), + dash_daq.NumericInput(id="start-second", value=0, min=0, max=59, + persistence=True), ], + style={'display': 'inline-block'}), + ], style={'margin': '10px 0'}), + + html.Div([html.Div([html.Label("End datetime"), + dcc.DatePickerSingle(id="end-date", display_format="Do MMM Y", + persistence=True, disabled=True, ), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Hour"), + dash_daq.NumericInput(id="end-hour", value=0, min=0, max=23, + persistence=True), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Minute"), + dash_daq.NumericInput(id="end-minute", value=0, min=0, max=59, + persistence=True), ], + style={'display': 'inline-block'}), + html.Div([html.Label("Second"), + dash_daq.NumericInput(id="end-second", value=0, min=0, max=59, + persistence=True), ], + style={'display': 'inline-block'}), + ], style={'margin': '10px 0'}), html.Br(), html.Button("Plot", id="refresh-button", n_clicks=0), html.Button("Check for new installations", id="installation-check-button", n_clicks=0), From 5c79c41f818a6c47d261a276574c57b15089ec8f Mon Sep 17 00:00:00 2001 From: Juri Date: Mon, 13 Mar 2023 17:32:51 +0100 Subject: [PATCH 3/7] OPS: Version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f0b3eb2..01903d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "aerosense-dashboard" -version = "0.4.4" +version = "0.5.0" description = "High-level visualisation for aerosense" authors = ["Tom Clark", "Marcus Lugg", "Yuriy Marykovsky"] license = "BSD-3" From 27545dd3ce3ff52fe3ce9e96a0581f255d0b2d9e Mon Sep 17 00:00:00 2001 From: cortadocodes Date: Mon, 13 Mar 2023 16:54:05 +0000 Subject: [PATCH 4/7] STY: Run pre-commit hooks --- dashboard/callbacks.py | 6 +- dashboard/layouts.py | 125 +++++++++++++++++------- docs/source/deploying_the_dashboard.rst | 1 - docs/source/index.rst | 2 +- 4 files changed, 91 insertions(+), 43 deletions(-) diff --git a/dashboard/callbacks.py b/dashboard/callbacks.py index 1a95b6d..6c9d870 100644 --- a/dashboard/callbacks.py +++ b/dashboard/callbacks.py @@ -5,8 +5,8 @@ from dash import Input, Output, State from aerosense_tools.plots import plot_connection_statistic, plot_pressure_bar_chart, plot_sensors -from aerosense_tools.queries import ROW_LIMIT, BigQuery from aerosense_tools.preprocess import RawSignal +from aerosense_tools.queries import ROW_LIMIT, BigQuery from aerosense_tools.utils import generate_time_range, get_cleaned_sensor_column_names @@ -193,8 +193,8 @@ def plot_sensors_graph( finish=finish, ) - data_columns = df.columns[df.columns.str.startswith('f')].tolist() - sensor_data = df[["datetime"] + data_columns].set_index('datetime') + data_columns = df.columns[df.columns.str.startswith("f")].tolist() + sensor_data = df[["datetime"] + data_columns].set_index("datetime") raw_data = RawSignal(sensor_data, sensor_name) raw_data.measurement_to_variable() plot_df = raw_data.dataframe.reset_index() diff --git a/dashboard/layouts.py b/dashboard/layouts.py index 2544e90..64e2fca 100644 --- a/dashboard/layouts.py +++ b/dashboard/layouts.py @@ -40,44 +40,93 @@ def create_sensors_tab_layout(app, tab_name, sensor_names, graph_id, data_limit_ TimeRangeSelect(), html.Br(), html.Label("Custom time range"), - html.Div([html.Div([html.Label("Start datetime"), - dcc.DatePickerSingle(id="start-date", - date=datetime.datetime.now().date().isoformat(), - display_format="Do MMM Y", - persistence=True, - disabled=True, ), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Hour"), - dash_daq.NumericInput(id="start-hour", value=0, min=0, max=23, - persistence=True), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Minute"), - dash_daq.NumericInput(id="start-minute", value=0, min=0, max=59, - persistence=True), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Second"), - dash_daq.NumericInput(id="start-second", value=0, min=0, max=59, - persistence=True), ], - style={'display': 'inline-block'}), - ], style={'margin': '10px 0'}), - - html.Div([html.Div([html.Label("End datetime"), - dcc.DatePickerSingle(id="end-date", display_format="Do MMM Y", - persistence=True, disabled=True, ), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Hour"), - dash_daq.NumericInput(id="end-hour", value=0, min=0, max=23, - persistence=True), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Minute"), - dash_daq.NumericInput(id="end-minute", value=0, min=0, max=59, - persistence=True), ], - style={'display': 'inline-block'}), - html.Div([html.Label("Second"), - dash_daq.NumericInput(id="end-second", value=0, min=0, max=59, - persistence=True), ], - style={'display': 'inline-block'}), - ], style={'margin': '10px 0'}), + html.Div( + [ + html.Div( + [ + html.Label("Start datetime"), + dcc.DatePickerSingle( + id="start-date", + date=datetime.datetime.now().date().isoformat(), + display_format="Do MMM Y", + persistence=True, + disabled=True, + ), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Hour"), + dash_daq.NumericInput( + id="start-hour", value=0, min=0, max=23, persistence=True + ), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Minute"), + dash_daq.NumericInput( + id="start-minute", value=0, min=0, max=59, persistence=True + ), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Second"), + dash_daq.NumericInput( + id="start-second", value=0, min=0, max=59, persistence=True + ), + ], + style={"display": "inline-block"}, + ), + ], + style={"margin": "10px 0"}, + ), + html.Div( + [ + html.Div( + [ + html.Label("End datetime"), + dcc.DatePickerSingle( + id="end-date", + display_format="Do MMM Y", + persistence=True, + disabled=True, + ), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Hour"), + dash_daq.NumericInput(id="end-hour", value=0, min=0, max=23, persistence=True), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Minute"), + dash_daq.NumericInput( + id="end-minute", value=0, min=0, max=59, persistence=True + ), + ], + style={"display": "inline-block"}, + ), + html.Div( + [ + html.Label("Second"), + dash_daq.NumericInput( + id="end-second", value=0, min=0, max=59, persistence=True + ), + ], + style={"display": "inline-block"}, + ), + ], + style={"margin": "10px 0"}, + ), html.Br(), html.Button("Plot", id="refresh-button", n_clicks=0), html.Button("Check for new installations", id="installation-check-button", n_clicks=0), diff --git a/docs/source/deploying_the_dashboard.rst b/docs/source/deploying_the_dashboard.rst index f2f8050..2e7527a 100644 --- a/docs/source/deploying_the_dashboard.rst +++ b/docs/source/deploying_the_dashboard.rst @@ -2,4 +2,3 @@ Deployment ========== - diff --git a/docs/source/index.rst b/docs/source/index.rst index 1fd3c5f..c673601 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -4,7 +4,7 @@ Aerosense Dashboard ``aerosense-dashboard`` is a data dashboard allowing high-level visualisation of data from the aerosense system. - - The ``data-gateway`` library is responsible for the data collection and ingress to GretaDB and GretaStore. + - The ``data-gateway`` library is responsible for the data collection and ingress to GretaDB and GretaStore. - The ``aerosense-tools`` library can access and manipulate data from GretaDB or the GretaStore by any python client. This dashboard uses a combination of its own code and ``aerosense-tools`` to access and visualise data from GretaDB. From 80076ed644192cc1b141f084cd8fce5f816204dd Mon Sep 17 00:00:00 2001 From: cortadocodes Date: Mon, 13 Mar 2023 16:54:17 +0000 Subject: [PATCH 5/7] OPS: Set version to correct number --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 01903d1..6f869bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "aerosense-dashboard" -version = "0.5.0" +version = "0.4.5" description = "High-level visualisation for aerosense" authors = ["Tom Clark", "Marcus Lugg", "Yuriy Marykovsky"] license = "BSD-3" From 040059487fabcbc5f6ed461181ab3166e16ad7c4 Mon Sep 17 00:00:00 2001 From: cortadocodes Date: Mon, 13 Mar 2023 16:55:13 +0000 Subject: [PATCH 6/7] REV: Add bold tag back to subtitle --- dashboard/layouts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dashboard/layouts.py b/dashboard/layouts.py index 64e2fca..f283172 100644 --- a/dashboard/layouts.py +++ b/dashboard/layouts.py @@ -39,7 +39,7 @@ def create_sensors_tab_layout(app, tab_name, sensor_names, graph_id, data_limit_ html.Label(html.B("Time range")), TimeRangeSelect(), html.Br(), - html.Label("Custom time range"), + html.Label(html.B("Custom time range")), html.Div( [ html.Div( From 1776f622287dae80e61a8721bde7653c84778d19 Mon Sep 17 00:00:00 2001 From: Juri Date: Mon, 13 Mar 2023 22:35:00 +0100 Subject: [PATCH 7/7] OPS: Add code comment --- dashboard/callbacks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dashboard/callbacks.py b/dashboard/callbacks.py index 1a95b6d..f10eae5 100644 --- a/dashboard/callbacks.py +++ b/dashboard/callbacks.py @@ -193,11 +193,12 @@ def plot_sensors_graph( finish=finish, ) + # Extract only data columns and set index to 'datetime', so that DataFrame is accepted by RawSignal class data_columns = df.columns[df.columns.str.startswith('f')].tolist() sensor_data = df[["datetime"] + data_columns].set_index('datetime') raw_data = RawSignal(sensor_data, sensor_name) - raw_data.measurement_to_variable() - plot_df = raw_data.dataframe.reset_index() + raw_data.measurement_to_variable() # Convert raw data int to float value in SI units + plot_df = raw_data.dataframe.reset_index() # reset index to pass DataFrame to plot_sensors function figure = plot_sensors(plot_df, line_descriptions=sensor_types[sensor_name]["variable"]) figure.update_layout(height=800)