diff --git a/config/phytobsdash_config.toml b/config/phytobsdash_config.toml index 5b6b9f1be4ea5e881d7fcb430e32608c10b0bee8..7189ca01cd7500befce6fb15a8ac0088739de204 100644 --- a/config/phytobsdash_config.toml +++ b/config/phytobsdash_config.toml @@ -1,16 +1,16 @@ [analyst] url='https://data.phytobs.fr/files/latest/all_sites/Analyst.csv' separator=";" -file='data/analyst.pickle' +file='../data/analyst.pickle' [hydro] -file='data/hydro.pickle' +file='../data/hydro.pickle' [phytobs] url='https://data.phytobs.fr/files/latest/all_sites/Phytobs.csv' separator=";" -file='data/phytobs.pickle' +file='../data/phytobs.pickle' [webapp] diff --git a/src/pages/about.py b/src/pages/about.py index a7e5f807726f765aa048050979c2c3a835b2bd3d..4e61666ea9ad7ceb6100f5ca22cf8a5401b7d096 100644 --- a/src/pages/about.py +++ b/src/pages/about.py @@ -1,7 +1,7 @@ import dash from dash import html, dcc -dash.register_page(__name__) +dash.register_page(__name__, order=2) layout = html.Div( dcc.Markdown(''' diff --git a/src/pages/help.py b/src/pages/help.py index 8dc730e61551e06ecb961625d21c69742b7c410a..064845e9bee0fce87b85593a9fa35f80391d49fb 100644 --- a/src/pages/help.py +++ b/src/pages/help.py @@ -1,7 +1,7 @@ import dash from dash import html, dcc -dash.register_page(__name__) +dash.register_page(__name__, order=3) layout = html.Div( dcc.Markdown(''' diff --git a/src/pages/phytobsdash.py b/src/pages/phytobsdash.py index 573357e03858108fa58835f941186e750b7cb4db..28d583a688fddbbe75e2625bbf6fcd2557267e45 100644 --- a/src/pages/phytobsdash.py +++ b/src/pages/phytobsdash.py @@ -22,7 +22,7 @@ LOGGER.setLevel(logging.DEBUG) controls_by_index = {} taxon_layers_by_index = {} -dash.register_page(__name__, path="/", name="Home") +dash.register_page(__name__, path="/", name="Home", order=0) def _build_taxon_group_dropdown_options(survey_df): @@ -34,86 +34,6 @@ def _build_taxon_group_dropdown_options(survey_df): return options -def analyst_table_info(): - """ - Create and return a data table displaying analyst information. - - :return: The Dash Ag-Grid table for analyst information. - :rtype: dag.AgGrid - """ - # Calcul des statistiques pour chaque étude - df_analyst_table_info = pdt.analyst_df.groupby('Survey').agg({'Sampling date': ['nunique', 'min', 'max'], - 'Accepted taxon name': ['count', 'nunique'], - 'Latitude': 'first', 'Longitude': 'first'}) - df_analyst_table_info.columns = ['Samples', 'First sample', 'Latest sample', 'Total occurrences', - 'Distinct Taxa', 'Latitude', 'Longitude'] - - df_analyst_table_info.reset_index(inplace=True) - - # Création du tableau Ag-Grid - analyst_table = dag.AgGrid( - id='analyst-data-table', - columnDefs=[{"field": col, "headerName": col} for col in df_analyst_table_info.columns], - rowData=df_analyst_table_info.to_dict('records'), - defaultColDef={"resizable": True, "sortable": True, "filter": True}, - columnSize="sizeToFit", - csvExportParams={ - "fileName": "analyst_table.csv", - }, - ) - - return analyst_table - - -def phytobs_table_info(): - """ - Create and return a data table displaying phytobs information. - - :return: The Dash Ag-Grid table for phytobs information. - :rtype: dag.AgGrid - """ - df_phytobs_table_info = pdt.phytobs_df.groupby('Survey').agg({'Sampling date': ['nunique', 'min', 'max'], - 'Taxonomic group': ['count', 'nunique'], - 'Latitude': 'first', 'Longitude': 'first'}) - df_phytobs_table_info.columns = ['Samples', 'First sample', 'Latest sample', 'Total Grouped Occurrences', - 'Distinct Groups', 'Latitude', 'Longitude'] - - df_phytobs_table_info.reset_index(inplace=True) - - # Création du tableau Ag-Grid - phytobs_table = dag.AgGrid( - id='phytobs-data-table', - columnDefs=[{"field": col, "headerName": col} for col in df_phytobs_table_info.columns], - rowData=df_phytobs_table_info.to_dict('records'), - defaultColDef={"resizable": True, "sortable": True, "filter": True}, - columnSize="sizeToFit", - csvExportParams={ - "fileName": "phytobs_table.csv", - }, - ) - - return phytobs_table - - -@callback( - Output("analyst-data-table", "exportDataAsCsv"), - Input("a-csv-button", "n_clicks"), -) -def export_analyst_data_as_csv(n_clicks): - if n_clicks: - return True - return False - - -@callback( - Output("phytobs-data-table", "exportDataAsCsv"), - Input("p-csv-button", "n_clicks"), -) -def export_phytobs_data_as_csv(n_clicks): - if n_clicks: - return True - return False - @callback( Output('survey-info-layer', 'children'), @@ -2203,37 +2123,6 @@ layout = html.Div([ style={'max-width': '100%', 'height': '400px', 'position': 'center'}, zoom=5, )]), - html.Details( - open=False, - children=[ - html.Summary("PHYTOBS SNO Summary Tables"), - dbc.Alert([ - "Data for the SNO Dashboard is provided by the ", - html.A( - 'PHYTOBS file download area', - href='https://data.phytobs.fr/files/latest/', - target='_blank', - className="alert-link", - )], - color="light"), - html.Details( - open=True, - children=[ - html.Summary(f"Analyst table ({(pdt.analyst_df['Survey'].nunique())} surveys)"), - analyst_table_info(), - html.Button("Download CSV", id="a-csv-button", n_clicks=0), - ] - ), - html.Details( - open=True, - children=[ - html.Summary(f"PHYTOBS table ({pdt.phytobs_df['Survey'].nunique()} surveys)"), - phytobs_table_info(), - html.Button("Download CSV", id="p-csv-button", n_clicks=0), - ] - ), - ], - ), html.Hr(className='bd-hr'), html.Div(id="graph-panels", children=[]), html.Div(id='marker-popup', style={'display': 'none'}), diff --git a/src/pages/summary.py b/src/pages/summary.py new file mode 100644 index 0000000000000000000000000000000000000000..a1a0d7692769b062029da55c00609b0ea2aca297 --- /dev/null +++ b/src/pages/summary.py @@ -0,0 +1,153 @@ +import logging + +import dash +import pandas as pd +from dash import Dash, html, dcc, callback, Output, Input, ALL, MATCH, State, Patch, ctx +import dash_ag_grid as dag +import plotly.figure_factory as ff + +import phytobs_data_tools as pdt + +dash.register_page(__name__,order=1) + +logging.basicConfig() +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + + +def analyst_table_info(): + """ + Create and return a data table displaying analyst information. + + :return: The Dash Ag-Grid table for analyst information. + :rtype: dag.AgGrid + """ + # Calcul des statistiques pour chaque étude + df_analyst_table_info = pdt.analyst_df.groupby('Survey').agg({'Sampling date': ['nunique', 'min', 'max'], + 'Accepted taxon name': ['count', 'nunique'], + 'Latitude': 'first', 'Longitude': 'first'}) + df_analyst_table_info.columns = ['Samples', 'First sample', 'Latest sample', 'Total occurrences', + 'Distinct Taxa', 'Latitude', 'Longitude'] + + df_analyst_table_info.reset_index(inplace=True) + + # Création du tableau Ag-Grid + analyst_table = dag.AgGrid( + id='analyst-data-table', + columnDefs=[{"field": col, "headerName": col} for col in df_analyst_table_info.columns], + rowData=df_analyst_table_info.to_dict('records'), + defaultColDef={"resizable": True, "sortable": True, "filter": True}, + columnSize="sizeToFit", + csvExportParams={ + "fileName": "analyst_table.csv", + }, + ) + + return analyst_table + + +def phytobs_table_info(): + """ + Create and return a data table displaying phytobs information. + + :return: The Dash Ag-Grid table for phytobs information. + :rtype: dag.AgGrid + """ + df_phytobs_table_info = pdt.phytobs_df.groupby('Survey').agg({'Sampling date': ['nunique', 'min', 'max'], + 'Taxonomic group': ['count', 'nunique'], + 'Latitude': 'first', 'Longitude': 'first'}) + df_phytobs_table_info.columns = ['Samples', 'First sample', 'Latest sample', 'Total Grouped Occurrences', + 'Distinct Groups', 'Latitude', 'Longitude'] + + df_phytobs_table_info.reset_index(inplace=True) + + # Création du tableau Ag-Grid + phytobs_table = dag.AgGrid( + id='phytobs-data-table', + columnDefs=[{"field": col, "headerName": col} for col in df_phytobs_table_info.columns], + rowData=df_phytobs_table_info.to_dict('records'), + defaultColDef={"resizable": True, "sortable": True, "filter": True}, + columnSize="sizeToFit", + csvExportParams={ + "fileName": "phytobs_table.csv", + }, + ) + + return phytobs_table + + +@callback( + Output("analyst-data-table", "exportDataAsCsv"), + Input("a-csv-button", "n_clicks"), +) +def export_analyst_data_as_csv(n_clicks): + if n_clicks: + return True + return False + + +@callback( + Output("phytobs-data-table", "exportDataAsCsv"), + Input("p-csv-button", "n_clicks"), +) +def export_phytobs_data_as_csv(n_clicks): + if n_clicks: + return True + return False + + + +def summary_table_info(): + + summary_info = pdt.phytobs_df[['Survey','Sampling date']] + + summary_info["Sampling date"] = pd.to_datetime(summary_info["Sampling date"]) + summary_info["Start"] = summary_info["Sampling date"].apply(lambda x: pd.offsets.MonthBegin().rollback(x)) + summary_info["Start"] = summary_info["Start"].apply(lambda x: x.replace(hour=0, minute=0, second=0)) + summary_info["Finish"] =summary_info['Sampling date'].apply(lambda x: pd.offsets.MonthEnd().rollforward(x)) + summary_info["Finish"] = summary_info["Finish"].apply(lambda x: x.replace(hour=0, minute=0, second=0)) + summary_info.drop('Sampling date', axis=1, inplace=True) + summary_info=summary_info.drop_duplicates(keep='first') + summary_info["Task"] = summary_info["Survey"] + summary_info["Resource"] = "Samples" + + summary_info.sort_values(['Task'], inplace=True) + + summary_info.rename(columns={'Task': 'Task', "Start" : "Start", "Finish" : 'Finish'}, inplace=True) + + colors = { + 'Samples' : 'rgb(47,164,90)', + } + + fig = ff.create_gantt(summary_info, colors=colors, index_col="Resource", show_colorbar=False, title="Overview of Sampling Timespan", group_tasks=True) + + return dcc.Graph(figure=fig) + + + +layout = html.Div( +html.Div( + children=[ + html.Div( + children=[ + html.H4(f"Overview of Available Samples"), + summary_table_info(), + ] + ), + html.Div( + children=[ + html.H4(f"PHYTOBS taxon groups table ({pdt.phytobs_df['Survey'].nunique()} surveys)"), + phytobs_table_info(), + html.Button("Download CSV", id="p-csv-button", n_clicks=0), + ] + ), + html.Div( + children=[ + html.H4(f"PHYTOBS analyst taxon table ({pdt.analyst_df['Survey'].nunique()} surveys)"), + analyst_table_info(), + html.Button("Download CSV", id="a-csv-button", n_clicks=0), + ] + ), + ], className="bd-content-full" + ), +)