diff --git a/src/pages/dashboard.py b/src/pages/dashboard.py index 602f4f8791813e9b23658862987d0b5e9e93b9b0..3d390b69a1848ebdb7c12b704241236a9d218dea 100644 --- a/src/pages/dashboard.py +++ b/src/pages/dashboard.py @@ -28,6 +28,7 @@ from mlair.time_series import plot as plot_ml_time_series import pages.dashboard_translations as guitr import pages.dashboard_constants as guiconst + # the following should be done with static files! APP_HOME = Path.cwd() IMAGE_PATH = APP_HOME.joinpath("static", "images") @@ -171,7 +172,10 @@ def generate_ml_fcast_body(language_id=0): dbc.Col(dbc.Label(guitr.state_label[language_id]), width=3), dbc.Col( dcc.Dropdown(value=0, - options=[{'label': guitr.region_text[language_id][i], 'value': i} for i in range(len(guitr.region_text[language_id]))], + options=[{'label': guitr.region_text[language_id][i], + 'value': i, + 'disabled': True if i > 1 else False + } for i in range(len(guitr.region_text[language_id]))], id="ml_fcast_body_region"), width=6 ), ], class_name="row mt-3"), @@ -193,14 +197,20 @@ def generate_ml_fcast_body(language_id=0): dbc.Col(dbc.Label(guitr.species_label[language_id]), width=3), dbc.Col( dcc.Dropdown(value=0, - options=[{'label': guitr.species_options[language_id][i], 'value': i} for i in range(len(guitr.species_options[language_id]))], + options=[{'label': guitr.species_options[language_id][i], + 'value': i, + 'disabled': True + } for i in range(len(guitr.species_options[language_id]))], id="ml_fcast_body_species"), width=6 ) ], class_name="row mt-3"), dbc.Row([ dbc.Col(dbc.Label(guitr.output_metrics_label[language_id]), width=3), dbc.Col(dcc.Dropdown(value=0, - options=[{'label': metrics_info[language_id][' Name'][i], 'value': i} for i in range(len(metrics_info[language_id][' Name']))], + options=[{'label': metrics_info[language_id][' Name'][i], + 'value': i, + 'disabled': True + } for i in range(len(metrics_info[language_id][' Name']))], id="ml_fcast_body_metrics")), dbc.Col(dbc.Button(f"{guitr.help_metrics_label[language_id]}", id="help_metrics_open", class_name="fzj_style_btn"), width=3), dbc.Modal([ @@ -345,7 +355,7 @@ def generate_eurad_im_body(language_id=0): ) def update_image(selected_time_step, selected_variable, selected_station, users_dict, jobs_dict): plotinfo_dict = {} - if selected_time_step and selected_variable: + if selected_time_step and selected_variable and selected_variable != 'NoneAvailable': jobnr = json.loads(jobs_dict)["jobnr"] try: @@ -372,14 +382,13 @@ def update_image(selected_time_step, selected_variable, selected_station, users_ def generate_eurad_im_output_body(language_id, context, jobnr): - if jobnr and (jobnr != 'bla'): infile = str(DATA_PATH.joinpath(f'{jobnr}.nc')) job_props = get_db_job_entry(jobnr) start_date = job_props['start_date'] if not os.path.isfile(infile): - trans_filename = transfer_results_from_HPC(jobnr, start_date, DATA_PATH) + trans_filename = transfer_results_from_HPC(jobnr, start_date, 0, DATA_PATH) os.symlink(trans_filename, infile) timestep_list = info.get_available_time_stamps(infile) @@ -396,10 +405,10 @@ def generate_eurad_im_output_body(language_id, context, jobnr): stations_list = sorted(stations_list) else: start_date = '2018-07-19T00:00' - timestep_strings = '2018-07-19 00:00' + timestep_strings = [ '2018-07-19 00:00' ] fc_length_str = '1' - variables_list = 'o3' - stations_list = "XX, XX" + variables_list = [ 'NoneAvailable' ] + stations_list = [ "XX, XX" ] return [ dbc.Row([dbc.Label(f"{guitr.start_date_label[language_id]}: {start_date}, {guitr.forecast_length_label[language_id]}: {fc_length_str}")]), dbc.Row([ @@ -471,31 +480,82 @@ eurad_im_result_modal = html.Div([ generate_eurad_im_result_modal() ], id="eurad_im_result_modal_container") -def generate_eurad_scen_output_body(language_id): +def generate_eurad_scen_output_body(language_id, context, jobnr): + + if jobnr and (jobnr != 'bla'): + infile = str(DATA_PATH.joinpath(f'{jobnr}.nc')) + job_props = get_db_job_entry(jobnr) + start_date = job_props['start_date'] + iscen = job_props['emis_scen'] + + if not os.path.isfile(infile): + trans_filename = transfer_results_from_HPC(jobnr, start_date, iscen, DATA_PATH) + os.symlink(trans_filename, infile) + + timestep_list = info.get_available_time_stamps(infile) + timestep_strings = [np.datetime_as_string(ts, unit="m") for ts in timestep_list] + # TODO: Zeit in Stunden seit Start + + start_date = pd.to_datetime(timestep_list[0]).strftime(guitr.date_format2[language_id]) + fc_length = (len(timestep_list)-1) // 24 + fc_length_str = "{} {}{}".format(fc_length, guitr.day_label[language_id], guitr.day_plural_label[language_id] if fc_length > 1 else "") + + variables_list = info.get_available_variables(infile) + + stations_list = info.get_available_stations() + stations_list = sorted(stations_list) + else: + start_date = '2018-07-19T00:00' + timestep_strings = [ '2018-07-19 00:00' ] + fc_length_str = '1' + variables_list = [ 'NoneAvailable' ] + stations_list = [ "XX, XX" ] + iscen = 0 return [ - dbc.Row([ - dbc.Col([ - dbc.Checklist(options=[ - {"label": f"{guitr.downscaling_label[language_id]}", "value": 1}, - ]) - ], style={"display": "flex"}), - ], class_name="row mt-3"), - dbc.Row([ - dbc.Col(dbc.Label(f"{guitr.out_option_label[language_id]}"), width=3), - dbc.Col(dcc.Dropdown(value=guitr.output_format_options[language_id][0], - options=guitr.output_format_options[language_id]), width=6) - ], class_name="row mt-3"), -] + dbc.Row([dbc.Label(f"{guitr.start_date_label[language_id]}: {start_date},\ + {guitr.forecast_length_label[language_id]}: {fc_length_str},\ + {guitr.emis_scen_label[language_id]} {emis_info[language_id][' Name'][iscen]}")]), + dbc.Row([ + dbc.Col(dbc.Label(f"{guitr.time_step_label[language_id]}:"), width=3), + dbc.Col(dcc.Dropdown(value=timestep_strings[0], options=timestep_strings, id='time-step-dropdown-{}'.format(context)), width=3) + ], class_name="row mt-3"), + dbc.Row([ + dbc.Col(dbc.Label("Variable:"), width=3), + dbc.Col(dcc.Dropdown(value=variables_list[0], options=variables_list, id='variable-dropdown-{}'.format(context)), width=3), + dbc.Col(dbc.Label(f"{guitr.location_label[language_id]}:"), width=1), + dbc.Col(dcc.Dropdown(value=stations_list[0], options=stations_list, id='station-dropdown-{}'.format(context)), width=5) + ], class_name="row mt-3"), + dbc.Row([ + dbc.Col(html.Div(id='image-container-{}'.format(context)), width=6), + dbc.Col([html.Div(id='image-container-timeseries-{}'.format(context)), + dbc.Col(dbc.Button(f"{guitr.save_label[language_id]}", class_name="fzj_style_btn"), width=6), + dbc.Col(html.Br()), + html.Div([dbc.Button(f"{guitr.download_label[language_id]}", id="eurad_scen_output_download", + class_name="fzj_style_btn"), + dcc.Download(id="eurad_scen_download_result")]), + dbc.Col(html.Br()), + html.Div([dbc.Button(f"{guitr.im_download_label[language_id]}", id="eurad_scen_plots_download", + class_name="fzj_style_btn"), + dcc.Download(id="eurad_scen_download_plots")])], width=6), + ], class_name="row mt-3"), + dbc.Row([ + dbc.Col(html.Br(), width=12), + dbc.Col([ + dbc.Checkbox(label=f"{guitr.show_downscaling_label[language_id]}", value=0) + ], style={"display": "flex"}), + ], class_name="row mt-3f"), + ] + def generate_eurad_scen_body(language_id): return [ dbc.Row([ dbc.Col(dbc.Label(f"{guitr.date_label[language_id]}"), width=3), dbc.Col(dcc.DatePickerSingle(id="eurad_scen_start_date", - date=dt.date(2018, 7, 22), + date=dt.date(2018, 7, 18), 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), + min_date_allowed=dt.date(2018, 7, 18), 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]}:")), @@ -542,7 +602,7 @@ def generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_conta [ dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}), dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][2])), - dbc.ModalBody(generate_eurad_scen_output_body(language_id)), + dbc.ModalBody(generate_eurad_scen_output_body(language_id, "output", jobnr)), dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id="eurad_scen_output_close", class_name="fzj_style_btn", n_clicks=0) ]), @@ -560,7 +620,7 @@ def generate_eurad_scen_result_modal(container_id="eurad_scen_result_modal_conta [ dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}), dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][2])), - dbc.ModalBody(generate_eurad_scen_output_body(language_id)), + dbc.ModalBody(generate_eurad_scen_output_body(language_id, "result", jobnr)), dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id="eurad_scen_result_modal_close", class_name="fzj_style_btn", n_clicks=0) ]), @@ -866,7 +926,7 @@ layout = html.Div([ @callback( - Output("login", "children"), + Output("login-background", "children"), Output("user-info", "data"), Output("layout_tabs", "children"), Output("login_modal", "is_open", allow_duplicate=True), @@ -899,7 +959,7 @@ def login_open(lb_click, lc_click, name, password): else: return no_update, no_update, no_update, no_update, dbc.Alert(["Wrong password given!"], color="danger") else: - return create_login_button(), '{"user_id": 1, "language_id": 0}', \ + return create_login_button(), '{"user_id": -1, "language_id": 0}', \ create_tabs_layout() , True, no_update @@ -1260,7 +1320,7 @@ def postprocess_job(rows, derived_virtual_selected_rows, users_dict): eurad_im_output_modal_isopen = False ml_fcast_output_modal_isopen = False eurad_scen_output_modal_isopen = False - if derived_virtual_selected_rows != []: + if ((derived_virtual_selected_rows != []) and (not derived_virtual_selected_rows)): status = rows[derived_virtual_selected_rows[0]][guitr.jobs_columns[language_id][1]] application = rows[derived_virtual_selected_rows[0]][guitr.jobs_columns[language_id][0]] jobnr = rows[derived_virtual_selected_rows[0]][guitr.jobs_columns[language_id][9]] @@ -1295,10 +1355,19 @@ def get_jobs(jobs_dict, users_dict): eurad_im_output_modal_isopen = json.loads(jobs_dict)["eurad_im_output_modal_isopen"] ml_fcast_output_modal_isopen = json.loads(jobs_dict)["ml_fcast_output_modal_isopen"] eurad_scen_output_modal_isopen = json.loads(jobs_dict)["eurad_scen_output_modal_isopen"] - eurad_im_output_modal = generate_eurad_im_output_modal(jobnr, eurad_im_output_modal_isopen, language_id) - ml_fcast_output_modal = generate_ml_fcast_output_modal(jobnr, ml_fcast_output_modal_isopen, language_id) - eurad_scen_output_modal = generate_eurad_scen_output_modal("eurad_scen_output_modal_container", jobnr, + if eurad_im_output_modal_isopen: + eurad_im_output_modal = generate_eurad_im_output_modal(jobnr, eurad_im_output_modal_isopen, language_id) + else: + eurad_im_output_modal = dash.no_update + if ml_fcast_output_modal_isopen: + ml_fcast_output_modal = generate_ml_fcast_output_modal(jobnr, ml_fcast_output_modal_isopen, language_id) + else: + ml_fcast_output_modal = dash.no_update + if eurad_scen_output_modal_isopen: + eurad_scen_output_modal = generate_eurad_scen_output_modal("eurad_scen_output_modal_container", jobnr, eurad_scen_output_modal_isopen, language_id) + else: + eurad_scen_output_modal = dash.no_update return eurad_im_output_modal, ml_fcast_output_modal, eurad_scen_output_modal @@ -1321,10 +1390,19 @@ def get_results(results_dict, users_dict): eurad_im_result_modal_isopen = json.loads(results_dict)["eurad_im_output_modal_isopen"] ml_fcast_result_modal_isopen = json.loads(results_dict)["ml_fcast_output_modal_isopen"] eurad_scen_result_modal_isopen = json.loads(results_dict)["eurad_scen_output_modal_isopen"] - eurad_im_result_modal = generate_eurad_im_output_modal(jobnr, eurad_im_result_modal_isopen, language_id) - ml_fcast_result_modal = generate_ml_fcast_output_modal(jobnr, ml_fcast_result_modal_isopen, language_id) - eurad_scen_result_modal = generate_eurad_scen_result_modal("eurad_scene_result_modal_container", jobnr, + if eurad_im_result_modal_isopen: + eurad_im_result_modal = generate_eurad_im_output_modal(jobnr, eurad_im_result_modal_isopen, language_id) + else: + eurad_im_result_modal = dash.no_update + if ml_fcast_result_modal_isopen: + ml_fcast_result_modal = generate_ml_fcast_output_modal(jobnr, ml_fcast_result_modal_isopen, language_id) + else: + ml_fcast_result_modal = dash.no_update + if eurad_scen_result_modal_isopen: + eurad_scen_result_modal = generate_eurad_scen_result_modal("eurad_scene_result_modal_container", jobnr, eurad_scen_result_modal_isopen, language_id) + else: + eurad_scen_result_modal = dash.no_update return eurad_im_result_modal, ml_fcast_result_modal, eurad_scen_result_modal diff --git a/utils/utils.py b/utils/utils.py index 80606e83a35a62269c8296a0b2dd23bce3f7dc78..dee1753d40e0175becb4ef89e834cfb06be1ffb6 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -12,7 +12,7 @@ from deployment_settings import ( base_url = f"{UNICORE_BASE}JURECA/rest/core" -def transfer_results_from_HPC(jobnr, model_date, data_path): +def transfer_results_from_HPC(jobnr, model_date, iscen, data_path): # Authentification/Authorization credentials = uc_credentials.UsernamePassword(UNICORE_USER, UNICORE_PASSWORD) @@ -21,7 +21,10 @@ def transfer_results_from_HPC(jobnr, model_date, data_path): dd=dd.split(' ')[0] timestep_date = date(int(yy), int(mm), int(dd)) base_directory = f"{UNICORE_USER}/{jobnr.upper()}/CTM/{yy}{mm}/{dd}" - download_filename = f"ctmout_wrf_cutcropped_{timestep_date.strftime('%j')}_h09.nc" + if iscen == 0: + download_filename = f"ctmout_wrf_cutcropped_{timestep_date.strftime('%j')}_h09.nc" + else: + download_filename = f"ctmout_wrf{iscen:03}_cutcropped_{timestep_date.strftime('%j')}_h09.nc" # only transfer file if results are not already there (from another jobnr); # in the latter case, a link to the already downloaded data is sufficient