diff --git a/prepare_userdb.py b/prepare_userdb.py index 5db8628447f737a469e23bbd5b2a4f55ab3cb6f9..0c1224bb0d94811676e3accb1d77a8a6a93ea86c 100644 --- a/prepare_userdb.py +++ b/prepare_userdb.py @@ -230,19 +230,19 @@ conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecas conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ VALUES ('a89uj20gxybb', 1, 2, 2, '2017-01-25 00:00', 4, 0, Null, Null, 5, '2024-01-02 14:35')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('832tgjhingj1', 2, 0, 1, '2018-07-18 00:00', 4, 1, Null, Null, Null, '2024-01-12 16:03')") + VALUES ('832tgjhingj2', 2, 0, 1, '2018-07-18 00:00', 4, 1, Null, Null, Null, '2024-01-12 16:03')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('jjkl7t3li97m', 2, 1, 0, '2017-01-25 00:00', 3, 0, 0, 0, Null, '2024-01-09 10:14')") + VALUES ('jjkl7t3li97n', 2, 1, 0, '2017-01-25 00:00', 3, 0, 0, 0, Null, '2024-01-09 10:14')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('7zhtglaza8ah', 2, 2, 1, '2018-07-18 00:00', 4, 1, Null, Null, 1, '2024-01-15 08:01')") + VALUES ('7zhtglaza8ih', 2, 2, 1, '2018-07-18 00:00', 4, 1, Null, Null, 1, '2024-01-15 08:01')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('ji54Fdr0z99m', 2, 0, 0, '2018-07-18 00:00', 1, 0, Null, Null, Null, '2023-12-18 13:57')") + VALUES ('ji54Fdr0z99n', 2, 0, 0, '2018-07-18 00:00', 1, 0, Null, Null, Null, '2023-12-18 13:57')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('7zknt6702rx5', 2, 0, 3, '2017-01-25 00:00', 3, 0, Null, Null, Null, '2023-12-12 11:27')") + VALUES ('7zknt6702rx6', 2, 0, 3, '2017-01-25 00:00', 3, 0, Null, Null, Null, '2023-12-12 11:27')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('klj836kahg2l', 2, 2, 0, '2018-07-18 00:00', 1, 0, Null, Null, 2, '2023-12-21 17:59')") + VALUES ('klj836kahg2m', 2, 2, 0, '2018-07-18 00:00', 1, 0, Null, Null, 2, '2023-12-21 17:59')") conn.execute("INSERT INTO jobs (id,user_id,application,status,start_date,forecast_length, region, species, metric, emis_scen, creation_date) \ - VALUES ('a89uj20gxybb', 2, 2, 2, '2017-01-25 00:00', 4, 0, Null, Null, 5, '2024-01-02 14:35')") + VALUES ('a89uj20gxybc', 2, 2, 2, '2017-01-25 00:00', 4, 0, Null, Null, 5, '2024-01-02 14:35')") conn.commit() diff --git a/src/eurad_plot.py b/src/eurad_plot.py index 1ec179339ac420ed2f1b7011374c4f135418c98b..f4ea0f2c842dbd1ab7a94eb41a352137e5306e4b 100644 --- a/src/eurad_plot.py +++ b/src/eurad_plot.py @@ -9,7 +9,7 @@ def get_euradim_plot(jobnr, timestep, species, station): # just to make it run APP_HOME = Path.cwd() DATA_PATH = APP_HOME.joinpath("static", "data") - ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots") + ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots", "eurad") # Output file is linked to jobnr infile = str(DATA_PATH.joinpath(f'{jobnr}.nc')) @@ -25,7 +25,7 @@ def get_euradim_plot(jobnr, timestep, species, station): # print("plotting map:", jobnr, timestep, species, station) generate_plot(filename, output_path, species, timestep, station) - return os.path.join("assets", "generated_plots", output_file) + return os.path.join("assets", "generated_plots", "eurad", output_file) # path relative to website root (src) @@ -34,7 +34,7 @@ def get_timeseries_plot(jobnr, station, species, timestep): # just to make it run APP_HOME = Path.cwd() DATA_PATH = APP_HOME.joinpath("static", "data") - ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots") + ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots", "eurad") # Output file is linked to jobnr infile = str(DATA_PATH.joinpath(f'{jobnr}.nc')) @@ -51,5 +51,5 @@ def get_timeseries_plot(jobnr, station, species, timestep): # print("plotting time series:", jobnr, timestep, species, station) generate_time_series_plot(filename, output_path, station, species, timestamp=timestep, figsize=(5,3)) - return os.path.join("assets", "generated_plots", output_file) + return os.path.join("assets", "generated_plots", "eurad", output_file) # path relative to website root (src) diff --git a/src/mlair/time_series.py b/src/mlair/time_series.py index c04160ee70f0c0ebcf7ee05126313fcabd8d40e3..1f5b6a60420b7857ff505a73674f17b9d8c4c2f7 100644 --- a/src/mlair/time_series.py +++ b/src/mlair/time_series.py @@ -1,26 +1,32 @@ +import os import matplotlib.pyplot as plt import xarray as xr import pandas as pd import datetime as dt +import pages.dashboard_translations as guitr -def plot(figsize=(6, 3), input_dir="static/data/MLAIR", output_dir="mlair/assets/generated_plots"): +def plot(station, language_id=0, species=0, start_date = "2018-07-18 00:00", forecast_length = 4, input_dir="static/data/MLAIR", output_dir=None, figsize=(6, 3)): - # get all these from outside!!! - species = "O3" - station_label = "Bielefeld-Ost" - station_code = "DENW067" - start_date = "2018-07-18" - forecast_length = "4days" + # get this from outside!!! units = "ppb" + # still needed: translation table from indices to MLAIR abbreviations of species + # now a quick hack: + if species == 0: + species = "O3" + # prepare input and output - hourly_start_date = (dt.datetime.strptime(start_date, '%Y-%m-%d') - dt.timedelta(days=4)).strftime('%Y-%m-%d') + station_code, station_label = station.split(',') + station_code = station_code.strip() + station_label = station_label.strip() + start_date = start_date[0:10] + hourly_start_date = (dt.datetime.strptime(start_date, '%Y-%m-%d') - dt.timedelta(days=forecast_length)).strftime('%Y-%m-%d') hourly_end_date = (dt.datetime.strptime(start_date, '%Y-%m-%d') - dt.timedelta(days=1)).strftime('%Y-%m-%d') file_s = f"{input_dir}/forecasts_{station_code}_test.nc" dataset = xr.open_dataset(file_s) - d4_fc = dataset['__xarray_dataarray_variable__'].sel(index=start_date,type='nn').data + d4_fc = dataset['__xarray_dataarray_variable__'].sel(index=start_date,type='nn').data[:forecast_length] # plot the values at the middle of the day --> offset 12:00 - d4_fc_times = [ (dt.datetime.strptime(start_date, '%Y-%m-%d') + dt.timedelta(days=i)).strftime('%Y-%m-%d 12:00') for i in range(4) ] + d4_fc_times = [ (dt.datetime.strptime(start_date, '%Y-%m-%d') + dt.timedelta(days=i)).strftime('%Y-%m-%d 12:00') for i in range(forecast_length) ] df_fc = pd.DataFrame({'fc_time': d4_fc_times, 'value': d4_fc}) # plot the values at the middle of the day --> give an hourly period df_fc['fc_time'] = pd.to_datetime(df_fc['fc_time']).dt.to_period('H') @@ -30,7 +36,8 @@ def plot(figsize=(6, 3), input_dir="static/data/MLAIR", output_dir="mlair/assets d4_hourly_times = dataset['datetime'].sel(datetime=slice(hourly_start_date,hourly_end_date)).data df_hourly = pd.DataFrame({'hourly_time': d4_hourly_times, 'value': d4_hourly}) df_hourly['hourly_time'] = pd.to_datetime(df_hourly['hourly_time']) - output_file_name = f"mlair_{species}_{station_code}_{start_date}_{forecast_length}.png" + fc_length_str = "{}{}{}".format(forecast_length, guitr.day_label[language_id], guitr.day_plural_label[language_id] if forecast_length > 1 else "") + output_file_name = f"mlair_{species}_{station_code}_{start_date}_{fc_length_str}.png" # plot plt.figure(figsize=figsize) @@ -45,11 +52,14 @@ def plot(figsize=(6, 3), input_dir="static/data/MLAIR", output_dir="mlair/assets plt.ylabel(f'Konzentration ({units})') ax.grid(True) plt.tight_layout() + if not output_dir: + output_dir = str(os.path.join("assets", "generated_plots", "mlair")) plt.savefig(f"{output_dir}/{output_file_name}") - return output_file_name + return os.path.join("assets", "generated_plots", "mlair", output_file_name) if __name__ == "__main__": - plot(input_dir = "/home/s.schroeder/mlworkflowinterface/src/static/data/MLAIR", + plot(station = "DENW067, Bielefeld Ost", + input_dir = "/home/s.schroeder/mlworkflowinterface/src/static/data/MLAIR", output_dir = "/home/s.schroeder/mlworkflowinterface/src/mlair/assets/generated_plots") diff --git a/src/pages/dashboard.py b/src/pages/dashboard.py index f47286e9864f8693c7b81e0e1b3ff7550781deb7..7547f864f92701324df585284e47017713a4172a 100644 --- a/src/pages/dashboard.py +++ b/src/pages/dashboard.py @@ -35,15 +35,7 @@ ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots") dash.register_page(__name__, title="DestinE Air Quality Use Case", path="/") -# placeholder for time series and map -image_path = IMAGE_PATH.joinpath('placeholder_timeseries.png') -pil_series = Image.open(image_path) -image_path = IMAGE_PATH.joinpath('placeholder_pure_timeseries.png') -pil_pure_series = Image.open(image_path) -image_path = IMAGE_PATH.joinpath('placeholder_O3_NRW.png') -pil_img = Image.open(image_path) -station_info = pd.read_csv(DATA_PATH.joinpath("stations_NRW.csv")) -station_info = [f"{station[0]} {station[1]}" for station in station_info.values] +# to be put to correct source code file! metrics_info_tmp = pd.read_csv(DATA_PATH.joinpath("mlair_metrics.csv"), delimiter=';') len_met = len(metrics_info_tmp) metrics_info = [metrics_info_tmp.iloc[:int(len_met/2),:], @@ -80,6 +72,28 @@ def create_db_job_entry(user_id, job_dict): conn.close() +def get_db_job_entry(jobid): + conn = sqlite3.connect(DATA_PATH.joinpath('destine_de370c_users.db')) + cur = conn.cursor() + cur.execute(f"SELECT application, status, start_date, forecast_length, region, species, metric, emis_scen FROM jobs \ + WHERE id = '{jobid}'") +# application, status, start_date, forecast_length, region, species, metric, emis_scen = cur.fetchall()[0] + jobs = cur.fetchall() + conn.close() + for job in jobs: + application, status, start_date, forecast_length, region, species, metric, emis_scen = job + job_dict = {} + job_dict['id'] = jobid + job_dict['application'] = application + job_dict['status'] = status + job_dict['start_date'] = start_date + job_dict['forecast_length'] = forecast_length + job_dict['region'] = region + job_dict['species'] = species + job_dict['metric'] = metric + job_dict['emis_scen'] = emis_scen + return job_dict + def create_login_button(title="login"): return html.Div([ @@ -205,28 +219,52 @@ def generate_ml_fcast_body(language_id=0): ] def generate_ml_fcast_output_body(language_id): - ts_plot_name = plot_ml_time_series() - ts_plot_path = str(APP_HOME.joinpath("assets", "generated_plots", ts_plot_name)) + stations_list = info.get_available_stations(infile="mlair_stations.csv") + stations_list = sorted(stations_list) return [ dbc.Row(dbc.Label(f"{guitr.start_date_label[language_id]}: 18.07.2018, Ozon, Nordrhein Westfalen")), dbc.Row([ dbc.Col(dbc.Label("station:"), width=3), dbc.Col( - dcc.Dropdown(value=station_info[87], - options=station_info, + dcc.Dropdown(id="station-dropdown-ml-output", + value=stations_list[0], + options=stations_list, ), width=6 ), dbc.Col(dbc.Button(f"{guitr.map_select_label[language_id]}", class_name="fzj_style_btn"), width=2) ], class_name="row mt-3"), dbc.Row([ - dbc.Col([html.Img(src=pil_pure_series, width=550), - dbc.Col(dbc.Button(f"{guitr.save_label[language_id]}", class_name="fzj_style_btn"), width=6), - dbc.Col(html.Td([])), - dbc.Button(f"{guitr.download_label[language_id]}", class_name="fzj_style_btn")], width=6), + dbc.Col(html.Div(id='image-container-ml-output'), width=12), + dbc.Col(dbc.Button(f"{guitr.save_label[language_id]}", class_name="fzj_style_btn"), width=6), + dbc.Col(html.Td([])), + dbc.Col(dbc.Button(f"{guitr.download_label[language_id]}", class_name="fzj_style_btn"), width=6) ], class_name="row mt-3"), ] +@callback( + Output('image-container-ml-output', 'children'), + Input('station-dropdown-ml-output', 'value'), + [State("user-info", "data"), + State("job-info", "data")], + prevent_initial_call=True +) +def update_mlair_image(selected_station, users_dict, job_dict): + try: + language_id = json.loads(users_dict)["language_id"] + except: + language_id = 0 + jobid = json.loads(job_dict)["jobnr"] + job_props = get_db_job_entry(jobid) + + image_path = plot_ml_time_series(selected_station, language_id, + species=job_props['species'], + start_date=job_props['start_date'], + forecast_length=job_props['forecast_length']) + image = html.Img(src=image_path, className='image-fit-container') + + return image + def generate_ml_fcast_output_modal(jobnr=None, lisopen=False, language_id=0): return html.Div([ @@ -272,8 +310,8 @@ def generate_eurad_im_body(language_id=0): dbc.Col(dcc.DatePickerSingle(date=dt.date(2018, 7, 22), display_format=guitr.date_format[language_id], first_day_of_week=guitr.first_day_of_week[language_id], - min_date_allowed=dt.date(2018, 7, 22) - max_date_allowed=dt.date(2018, 7, 31) + min_date_allowed=dt.date(2018, 7, 22), + max_date_allowed=dt.date(2018, 7, 31), initial_visible_month=dt.date(2018, 7, 1))), dbc.Col(dbc.Label(f"{guitr.forecast_length_label[language_id]}:")), dbc.Col(dcc.Dropdown(value=guitr.forecast_length_options[language_id][0], options=guitr.forecast_length_options[language_id])) @@ -288,12 +326,13 @@ def generate_eurad_im_body(language_id=0): @callback( [Output('image-container-output', 'children'), Output('image-container-timeseries-output', 'children'), - Output("plot-info", "data")], + Output("plot-info", "data", allow_duplicate=True)], [Input('time-step-dropdown-output', 'value'), Input('variable-dropdown-output', 'value'), Input('station-dropdown-output', 'value')], [State("user-info", "data"), - State("job-info", "data")] + State("job-info", "data")], + prevent_initial_call=True ) def update_image(selected_time_step, selected_variable, selected_station, users_dict, jobs_dict): plotinfo_dict = {} @@ -898,11 +937,11 @@ def eurad_im_plots_download(download_button, job_dict, plot_dict): infile1 = f'job_{jobid}_station_{station}_species_{species}_time_{timestamp}.png' infile2 = f'job_{jobid}_time_{timestamp}_species_{species}_station_{station}.png' files = [infile1, infile2] - zipname = str(ASSETS_PATH.joinpath(f'job_{jobid}_time_{timestamp}_species_{species}_station_{station}.zip')) + zipname = str(ASSETS_PATH.joinpath('eurad', f'job_{jobid}_time_{timestamp}_species_{species}_station_{station}.zip')) zipf = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) for file in files: - zipf.write(str(ASSETS_PATH.joinpath(file)),file) + zipf.write(str(ASSETS_PATH.joinpath('eurad', file)),file) zipf.close() return dcc.send_file( zipname diff --git a/src/static/images/placeholder_pure_timeseries.png b/src/static/images/placeholder_pure_timeseries.png deleted file mode 100644 index c9fba795c2d84ebfbd5c1bf07a5ce032141fc740..0000000000000000000000000000000000000000 Binary files a/src/static/images/placeholder_pure_timeseries.png and /dev/null differ