Select Git revision
test_advanced_paddings.py
dashboard.py 65.54 KiB
from email.mime import image
import json
import pandas as pd
import dash
from dash import html, Output, Input, State, ctx, Dash, dcc, dash_table, no_update, callback
import dash_bootstrap_components as dbc
import sqlite3
import datetime as dt
from PIL import Image
from pathlib import Path
import eurad.info as info
import numpy as np
from eurad_plot import get_euradim_plot, get_timeseries_plot
from eurad.eurad_netcdf import EURAD_netCDF
import os
import zipfile
from cryptography.fernet import Fernet
import pyunicore.client as uc_client
import pyunicore.credentials as uc_credentials
from string import ascii_lowercase, digits
from random import choice
from time import sleep
from deployment_settings import (
KEY,
UNICORE_BASE, UFTP_BASE,
UNICORE_USER, UNICORE_PASSWORD
)
from utils import transfer_results_from_HPC
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")
DATA_PATH = APP_HOME.joinpath("static", "data")
ASSETS_PATH = APP_HOME.joinpath("assets", "generated_plots")
dash.register_page(__name__, title="DestinE Air Quality Use Case", path="/")
# 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),:],
metrics_info_tmp.iloc[int(len_met/2):,:].reset_index(drop=True).rename(columns={" Description": " Beschreibung"})]
emis_info_tmp = pd.read_csv(DATA_PATH.joinpath("eurad_emission_scenarios.csv"), delimiter=';')
len_em = len(emis_info_tmp)
emis_info = [emis_info_tmp.iloc[:int(len_em/2),:],
emis_info_tmp.iloc[int(len_em/2):,:].reset_index(drop=True).rename(columns={" Description": " Beschreibung"})]
def get_random_string(length):
# choose from all lowercase letter
allowed_char = ascii_lowercase + digits
return ''.join(choice(allowed_char) for i in range(length))
def create_db_job_entry(user_id, job_dict):
creation_date = dt.datetime.now().strftime('%Y-%m-%d %H:%M')
conn = sqlite3.connect(DATA_PATH.joinpath('destine_de370c_users.db'))
conn.execute("INSERT INTO jobs (id, user_id, application, status, start_date, forecast_length, region, species, metric, emis_scen, creation_date) \
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(job_dict['id'],
user_id,
job_dict['application'],
job_dict['status'],
job_dict['start_date'],
job_dict['forecast_length'],
job_dict['region'],
job_dict['species'],
job_dict['metric'],
job_dict['emis_scen'],
creation_date))
conn.commit()
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}'")
jobs = cur.fetchall()
conn.close()
job_dict = {}
for job in jobs:
application, status, start_date, forecast_length, region, species, metric, emis_scen = job
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([
html.Span(style={"flex": "1"}),
html.Span([
dbc.Button(f"{title}", id="login_button", class_name="fzj_style_btn"),
dbc.Modal([
dbc.ModalHeader("Login"),
dbc.ModalBody([
dbc.Row([
dbc.Col(dbc.Label("Name:"), width=3),
dbc.Col(dbc.Input(id='login_name', type="text"))
]),
dbc.Row([
dbc.Col(dbc.Label("Password:"), width=3),
dbc.Col(dbc.Input(id='login_password', type="password"))
])
]),
html.Div(id="alert_nouser", children=[]),
dbc.ModalFooter(
[dbc.Button("login", id="login_close", class_name="fzj_style_btn", n_clicks=0),
dbc.Button("register", id="register_open", class_name="fzj_style_btn", n_clicks=0)]),
],
id="login_modal",
is_open=False,
size="lg")
]),
html.Span(style={"flex": "1"}),
], id="login")
# TODO: take language ids from the controlled vocabulary!
register_modal = html.Div(
[
dbc.Modal(
[
dbc.ModalHeader("Register for Destination Earch Use Case for Air Quality"),
dbc.ModalBody(
[
dbc.Row([
dbc.Col(dbc.Label("Name:"), width=3),
dbc.Col(dbc.Input(id='register_name', type="text"))
]),
dcc.Dropdown(
id='language_dropdown',
options=[
{'label': 'English', 'value': 0},
{'label': 'Deutsch', 'value': 1}
],
value=0
)
]
),
dbc.ModalFooter(
[
dbc.Button("OK", id="register_ok_button", class_name="fzj_style_btn"),
dbc.Button("Close", id="register_close_button", class_name="fzj_style_btn"),
]
),
],
id="register_modal",
),
]
)
aai_login = dbc.Row([
create_login_button()
], id="login-background", style={"height": "70px"})
def generate_ml_fcast_body(language_id=0):
return [
dbc.Row([
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,
'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"),
dbc.Row([
dbc.Col(dbc.Label(guitr.date_label[language_id]), width=3),
dbc.Col(dcc.DatePickerSingle(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, 18),
max_date_allowed=dt.date(2018, 7, 31),
initial_visible_month=dt.date(2018, 7, 1),
id="ml_fcast_body_startdate")),
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],
id="ml_fcast_body_forecast_length"))
], class_name="row mt-3"),
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.species_label[language_id]}:"), width=3),
dbc.Col(
dcc.Dropdown(value=0,
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(f"{guitr.output_metrics_label[language_id]}:"), width=3),
dbc.Col(dcc.Dropdown(value=0,
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([
dbc.ModalHeader(f"{guitr.help_metrics_label[language_id]}"),
dbc.ModalBody(dash_table.DataTable(metrics_info[language_id].to_dict('records'),
[{"name": i, "id": i} for i in metrics_info[language_id].columns],
style_table={"width": "100%"},
style_cell={"textAlign": "left",
"whiteSpace": "pre-line"})),
dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id=f"help_metrics_close", class_name="fzj_style_btn", n_clicks=0)]),
],
id="help_metrics_modal",
is_open=False,
size="lg")
], class_name="row mt-3")
]
def generate_ml_fcast_output_body(language_id, jobnr):
stations_list = info.get_available_stations(infile="mlair_stations.csv")
# stations_list = sorted(stations_list)
if jobnr and (jobnr != 'bla'):
job_props = get_db_job_entry(jobnr)
start_date = job_props['start_date']
ireg = job_props['region']
region = guitr.region_text[language_id][ireg]
ispec = job_props['species']
species = guitr.species_options[language_id][ispec]
imetric = job_props['metric']
metric = guitr.metrics_options[language_id][imetric]
fc_length = job_props['forecast_length']
fc_length_str = "{} {}{}".format(fc_length, guitr.day_label[language_id], guitr.day_plural_label[language_id] if fc_length > 1 else "")
else:
start_date = "2018-07-18"
region = "X"
species = "X"
metric = "X"
fc_length_str = "X"
return [
dbc.Row(dbc.Label(f"""{guitr.region_label[language_id]}: {region},
{guitr.species_label[language_id]}: {species},
{guitr.output_metrics_label[language_id]}: {metric},
{guitr.start_date_label[language_id]}: {start_date},
{guitr.forecast_length_label[language_id]}: {fc_length_str}""")),
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.station_label[language_id]}:"), width=3),
dbc.Col(
dcc.Dropdown(id="station-dropdown-ml-output",
value=stations_list[0],
options= [{'label': stations_list[i],
'value': stations_list[i],
'disabled': True
} for i in range(len(stations_list))],
), width=6
),
dbc.Col(dbc.Button(f"{guitr.map_select_label[language_id]}", disabled=True, class_name="fzj_style_btn"), width=2)
], class_name="row mt-3"),
dbc.Row([
dbc.Col([html.Div(id='image-container-ml-output'),
html.Div([dbc.Button(f"{guitr.download_label[language_id]}", id="mlair_download",
class_name="fzj_style_btn"),
dcc.Download(id="mlair_download_result")]),
dbc.Col(html.Br()),
html.Div([dbc.Button(f"{guitr.im_download_label[language_id]}", id="mlair_plot_download",
class_name="fzj_style_btn"),
dcc.Download(id="mlair_download_plot")])], width=12),
], class_name="row mt-3"),
]
@callback(
[Output('image-container-ml-output', 'children'),
Output("plot-info", "data", allow_duplicate=True)],
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):
jobid = json.loads(job_dict)["jobnr"]
if jobid != "bla":
try:
language_id = json.loads(users_dict)["language_id"]
except:
language_id = 0
job_props = get_db_job_entry(jobid)
station_code, station_label = selected_station.split(',')
station_code = station_code.strip()
plotinfo_dict = {}
plotinfo_dict["station"] = station_code
ispec = job_props['species']
species = guitr.species_options[0][ispec]
ml_species = guiconst.ml_names[species]
plotinfo_dict["species"] = ml_species
plotinfo_dict["start_date"] = job_props['start_date'][0:10]
forecast_length = job_props['forecast_length']
fc_length_str = "{}{}{}".format(forecast_length, guitr.day_label[language_id], guitr.day_plural_label[language_id] if forecast_length > 1 else "")
plotinfo_dict["fc_length"] = fc_length_str
plotinfo_json = json.dumps(plotinfo_dict)
image_path = plot_ml_time_series(selected_station, language_id,
ispec=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, plotinfo_json
else:
return None, None
def generate_ml_fcast_output_modal(jobnr=None, lisopen=False, language_id=0):
return html.Div([
dbc.Modal(
[
dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}),
dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][1])),
dbc.ModalBody(generate_ml_fcast_output_body(language_id, jobnr)),
dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id="ml_fcast_output_close",
class_name="fzj_style_btn", n_clicks=0)
]),
],
id="ml_fcast_output_modal",
is_open=lisopen,
size="lg"
)
], id="ml_fcast_output_modal_container")
def generate_ml_fcast_result_modal(jobnr=None, lisopen=False, language_id=0):
return dbc.Modal(
[
dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}),
dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][1])),
dbc.ModalBody(generate_ml_fcast_output_body(language_id, jobnr)),
dbc.ModalFooter(dbc.Button(f"{guitr.close_label[language_id]}", id="ml_fcast_result_close",
class_name="fzj_style_btn", n_clicks=0)),
],
id="ml_fcast_result_modal",
is_open=lisopen,
size="lg"
)
ml_fcast_result_modal = html.Div([
generate_ml_fcast_result_modal()
], id="ml_fcast_result_modal_container")
def generate_eurad_im_body(language_id=0):
disabled_days = [ dt.datetime.strptime('2017-01-27','%Y-%m-%d') + dt.timedelta(days=i) for i in range(14) ]
disabled_days += [ dt.datetime.strptime('2017-02-16','%Y-%m-%d') + dt.timedelta(days=i) for i in range(523) ]
return [
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.date_label[language_id]}:"), width=3),
dbc.Col(dcc.DatePickerSingle(id="eurad_im_start_date",
date=guiconst.min_date_allowed,
display_format=guitr.date_format[language_id],
first_day_of_week=guitr.first_day_of_week[language_id],
min_date_allowed=guiconst.min_date_allowed,
max_date_allowed=guiconst.max_date_allowed,
disabled_days=disabled_days,
initial_visible_month=guiconst.initial_visible_month)),
dbc.Col(dbc.Label(f"{guitr.forecast_length_label[language_id]}:")),
dbc.Col(dcc.Dropdown(value=guitr.forecast_length_options[language_id][-1],
options=[{'label': guitr.forecast_length_options[language_id][i],
'value': guitr.forecast_length_options[language_id][i],
} for i in range(len(guitr.forecast_length_options[language_id]))],
id="eurad_im_forecast_length"))
], class_name="row mt-3"),
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.region_label[language_id]}:"), width=3),
dbc.Col(dcc.RadioItems(options={
0: guitr.region_text[language_id][0],
1: guitr.region_text[language_id][1]},
value=0, id="eurad_im_region_choice")),
], class_name="row mt-3"),
]
@callback(
[Output('image-container-output', 'children'),
Output('image-container-timeseries-output', 'children'),
Output("plot-info", "data", allow_duplicate=True)],
[Input('time-step-dropdown-output', 'value'),
Input('variable-dropdown-output', 'value'),
Input('station-dropdown-output', 'value'),
Input('eurad_im_target', 'value'),
Input('eurad_scen_diff', 'value')],
[State("user-info", "data"),
State("job-info", "data")],
prevent_initial_call=True
)
def update_image(selected_time_step, selected_variable, selected_station, ltarget, ldiff, users_dict, jobs_dict):
plotinfo_dict = {}
if selected_time_step and selected_variable and selected_variable != 'NoneAvailable':
jobnr = json.loads(jobs_dict)["jobnr"]
try:
language_id = json.loads(users_dict)["language_id"]
except:
language_id = 0
job_props = get_db_job_entry(jobnr)
application = job_props['application']
lltarget = True if ((application == 0) and ltarget) else False
lldiff = True if ((application == 2) and ldiff) else False
image_path = get_euradim_plot(language_id, jobnr, selected_time_step, selected_variable, selected_station, lldiff, lltarget)
timeseries_image_path = get_timeseries_plot(language_id, jobnr, selected_station, selected_variable, selected_time_step)
first_image = html.Img(src=image_path, className='image-fit-container')
second_image = html.Img(src=timeseries_image_path, className='image-fit-container')
plotinfo_dict["time_step"] = selected_time_step
plotinfo_dict["variable"] = selected_variable
plotinfo_dict["station"] = selected_station.split(',')[0]
plotinfo_dict["language_id"] = language_id
plotinfo_dict["ldiff"] = lldiff
plotinfo_dict["ltarget"] = lltarget
plotinfo_json = json.dumps(plotinfo_dict)
return first_image, second_image, plotinfo_json
plotinfo_json = json.dumps(plotinfo_dict)
return None, None, plotinfo_json
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']
region = job_props['region']
fc_length = job_props['forecast_length']
if not os.path.isfile(infile):
filenames = transfer_results_from_HPC(jobnr, start_date, 0, fc_length, DATA_PATH)
os.symlink(filenames['download_filename'], infile)
nc_file = EURAD_netCDF(infile)
timestep_list = nc_file.get_time_stamps()
timestep_strings = [np.datetime_as_string(ts)[:16] for ts in timestep_list['time'].values]
start_date = pd.to_datetime(timestep_strings[0]).strftime(guitr.date_format3[language_id])
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)
# for unit conversion, PRS and TEM were added
variables_list.remove('PRS')
variables_list.remove('TEM')
stations_list = info.get_available_stations()
stations_list = sorted(stations_list)
else:
start_date = '2018-07-19T00:00'
region = 0
timestep_strings = [ '2018-07-19 00:00' ]
fc_length_str = '1'
variables_list = [ 'NoneAvailable' ]
stations_list = [ "XX, XX" ]
return [
dbc.Row([dbc.Label(f"""{guitr.region_label[language_id]}: {guitr.region_text[language_id][region]},
{guitr.start_date_label[language_id]}: {start_date},
{guitr.forecast_length_label[language_id]}: {fc_length_str}""")]),
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)),
html.Div([dbc.Button(f"{guitr.download_label[language_id]}", id="eurad_im_output_download",
class_name="fzj_style_btn"),
dcc.Download(id="eurad_im_download_result")]),
dbc.Col(html.Br()),
html.Div([dbc.Button(f"{guitr.im_download_label[language_id]}", id="eurad_im_plots_download",
class_name="fzj_style_btn"),
dcc.Download(id="eurad_im_download_plots")])], width=6),
], class_name="row mt-3"),
dbc.Row([
dbc.Col(html.Br(), width=12),
dbc.Col([
dbc.Checkbox(id="eurad_im_target", label=f"{guitr.show_target_plot_label[language_id]}", value=False)
], width=12),
dbc.Col([
dbc.Checkbox(id="eurad_im_downscaling", label=f"{guitr.show_downscaling_label[language_id]}", value=0, disabled=True)
], width=12)
], class_name="row mt-3f"),
dbc.Row([
dbc.Col(html.Br(), width=12),
dbc.Col([
dbc.Button(f"{guitr.ml_download_label[language_id]}", id="ml_downscaling_data_download",
n_clicks=0, class_name="fzj_style_btn"),
], width=12),
dbc.Col([
dbc.Label(f"{guitr.ml_download_explanation[language_id]}", id="ml_download_explanation",
style={'font-size': '12px'}),
], width=12)
], class_name="row mt-3f"),
]
@callback(
Output('ml_downscaling_data_download', 'disabled'),
[Input('variable-dropdown-output', 'value')]
)
def update_button_disabled(selected_option):
if selected_option == 'O3' or selected_option == 'NO2':
return False
else:
return True
def generate_eurad_im_output_modal(jobnr=None, lisopen=False, language_id=0):
return html.Div([
dbc.Modal(
[
dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}, id="eurad_im_output_modal_title"),
dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][0])),
dbc.ModalBody(generate_eurad_im_output_body(language_id, "output", jobnr)),
dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id="eurad_im_output_close",
class_name="fzj_style_btn", n_clicks=0)
]),
],
id="eurad_im_output_modal",
is_open=lisopen,
size="xl"
)
], id="eurad_im_output_modal_container")
def generate_eurad_im_result_modal(jobnr=None, lisopen=False, language_id=0):
return dbc.Modal(
[
dbc.ModalTitle(f"{guitr.run2_label[language_id]} {jobnr}", style={"fontSize": 15}),
dbc.ModalHeader(dbc.ModalTitle(guitr.application_text[language_id][0])),
dbc.ModalBody(generate_eurad_im_output_body(language_id, "result", jobnr)),
dbc.ModalFooter(dbc.Button(f"{guitr.close_label[language_id]}", id="eurad_im_result_close",
class_name="fzj_style_btn", n_clicks=0)),
],
id="eurad_im_result_modal",
is_open=lisopen,
size="xl"
)
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, context, jobnr):
if jobnr and (jobnr != 'bla'):
infile = str(DATA_PATH.joinpath(f'{jobnr}.nc'))
basefile = str(DATA_PATH.joinpath(f'base_{jobnr}.nc'))
job_props = get_db_job_entry(jobnr)
start_date = job_props['start_date']
iscen = job_props['emis_scen']
ireg = job_props['region']
region = guitr.region_text[language_id][ireg]
fc_length = job_props['forecast_length']
if not os.path.isfile(infile):
filenames = transfer_results_from_HPC(jobnr, start_date, iscen, fc_length, DATA_PATH)
os.symlink(filenames['download_filename'], infile)
os.symlink(filenames['base_download_filename'], basefile)
nc_file = EURAD_netCDF(infile)
timestep_list = nc_file.get_time_stamps()
timestep_strings = [np.datetime_as_string(ts)[:16] for ts in timestep_list['time'].values]
start_date = pd.to_datetime(timestep_strings[0]).strftime(guitr.date_format3[language_id])
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)
# for unit conversion, PRS and TEM were added
variables_list.remove('PRS')
variables_list.remove('TEM')
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
region = "X"
return [
dbc.Row([dbc.Label(f"""{guitr.region_label[language_id]}: {region},
{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)),
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_im_plots_download",
class_name="fzj_style_btn"),
dcc.Download(id="eurad_im_download_plots")])], width=6),
], class_name="row mt-3"),
dbc.Row([
dbc.Col(html.Br(), width=12),
dbc.Col([
dbc.Checkbox(id="eurad_scen_diff", label=f"{guitr.show_diff_plot_label[language_id]}", value=False)
], width=12),
dbc.Col([
dbc.Checkbox(id="eurad_scen_downscaling", label=f"{guitr.show_downscaling_label[language_id]}", value=0, disabled=True)
], style={"display": "flex"}),
], class_name="row mt-3f"),
]
def generate_eurad_scen_body(language_id):
disabled_days = [ dt.datetime.strptime('2017-01-27','%Y-%m-%d') + dt.timedelta(days=i) for i in range(14) ]
disabled_days += [ dt.datetime.strptime('2017-02-16','%Y-%m-%d') + dt.timedelta(days=i) for i in range(523) ]
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=guiconst.min_date_allowed,
display_format=guitr.date_format[language_id],
first_day_of_week=guitr.first_day_of_week[language_id],
min_date_allowed=guiconst.min_date_allowed,
max_date_allowed=guiconst.max_date_allowed,
disabled_days=disabled_days,
initial_visible_month=guiconst.initial_visible_month)),
dbc.Col(dbc.Label(f"{guitr.forecast_length_label[language_id]}:")),
dbc.Col(dcc.Dropdown(value=guitr.forecast_length_options[language_id][-1],
options=[{'label': guitr.forecast_length_options[language_id][i],
'value': guitr.forecast_length_options[language_id][i],
} for i in range(len(guitr.forecast_length_options[language_id]))],
id="eurad_scen_forecast_length"))
], class_name="row mt-3"),
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.region_label[language_id]}:"), width=3),
dbc.Col(dcc.RadioItems(options={
0: guitr.region_text[language_id][0],
1: guitr.region_text[language_id][1]},
value=0, id="eurad_scen_region_choice")),
], class_name="row mt-3"),
dbc.Row([
dbc.Col(dbc.Label(f"{guitr.emis_scen_label[language_id]}:"), width=3),
dbc.Col(
dcc.Dropdown(value=0,
options=[{'label': emis_info[language_id][" Name"][i],
'value': i,
'disabled': True if i == len(emis_info[language_id][" Name"])-1 else False
} for i in range(len(emis_info[language_id][" Name"]))],
id="eurad_scen_emi"), width=6
),
dbc.Col(dbc.Button(f"{guitr.help_emissions_label[language_id]}", id="help_emis_open", class_name="fzj_style_btn"), width=3),
dbc.Modal([
dbc.ModalHeader(f"{guitr.help_emissions_label[language_id]}"),
dbc.ModalBody(dash_table.DataTable(emis_info[language_id].to_dict('records'),
[{"name": i, "id": i} for i in emis_info[language_id].columns],
style_table={"width": "100%"},
style_cell={"textAlign": "left",
"whiteSpace": "pre-line"
})),
dbc.ModalFooter([dbc.Button(f"{guitr.close_label[language_id]}", id=f"help_emis_close", class_name="fzj_style_btn", n_clicks=0)]),
],
id="help_emis_modal",
is_open=False,
size="lg")
], class_name="row mt-3"),
]
def generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container",
jobnr=None, lisopen=False, language_id=0):
return html.Div([
dbc.Modal(
[
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, "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)
]),
],
id=container_id[:-10],
is_open=lisopen,
size="lg"
)
], id=container_id)
def generate_eurad_scen_result_modal(container_id="eurad_scen_result_modal_container",
jobnr=None, lisopen=False, language_id=0):
return html.Div([
dbc.Modal(
[
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, "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)
]),
],
id=container_id[:-10],
is_open=lisopen,
size="lg"
)
], id=container_id)
def create_jobs_tab(language_id=0):
modal_list = [
{"name": guitr.application_text[language_id][0], "id": "eurad_im", "body": generate_eurad_im_body(language_id),
"description": guitr.description_text[language_id][0], "icon": "Icon1_FieldForecasting_small.png"},
{"name": guitr.application_text[language_id][1], "id": "ml_fcast", "body": generate_ml_fcast_body(language_id),
"description": guitr.description_text[language_id][1], "icon": "Icon2_PointForecasting_small.png"},
{"name": guitr.application_text[language_id][2], "id": "eurad_scen", "body": generate_eurad_scen_body(language_id),
"description": guitr.description_text[language_id][2], "icon": "Icon3_EmissionScenarios_small.png"},
]
return html.Div([
html.P([]),
html.Div([
html.Div(
[
html.Div([
dbc.Tooltip(modal["description"], target=f"{modal['id']}_open",
style={"opacity": 1.0}),
dbc.Button([
#html.Div(html.H1(modal["name"],style={"line-height": "500px", "color": "black", "bgcolor": "white"}), style={"align-self": "center",
# "width": "760px",
# "height": "500px",
# "background-image": f"url(../static/logos/{modal['icon']})"})
html.Div(html.H1(modal["name"],style={"line-height": "1100px", "vertical-align": "bottom"}), style={"align-self": "center",
"width": "760px",
"height": "600px",
"background-image": f"url(static/logos/{modal['icon']})",
"background-repeat": "no-repeat"})
], id=f"{modal['id']}_open", style={"flex": "auto"}, class_name="fzj_style_btn")
], className="modal_button")
for modal in modal_list
], className="button_row"
),
html.Div([
dbc.Modal(
[
dbc.ModalHeader(dbc.ModalTitle(modal["name"])),
dbc.ModalBody(
modal["body"]
),
dbc.ModalFooter([
dbc.Button(
f"{guitr.run_label[language_id]}", id=f"{modal['id']}_run", class_name="fzj_style_btn", n_clicks=0
),
dbc.Button(
f"{guitr.close_label[language_id]}", id=f"{modal['id']}_close", class_name="fzj_style_btn", n_clicks=0
)
]),
],
id=f"{modal['id']}_modal",
is_open=False,
size="lg"
)
for modal in modal_list
]),
html.P([
], id="outp_id"),
])
], id="create_jobs")
# Define the layout of the first tab
def create_description_content(language_id):
return dbc.Card(
dbc.CardBody(
guitr.description[language_id]
),
class_name="mt-3",
)
def get_job_status(jobid, application, convoc_status_dict):
application_settings = { 0 : { "ecf_host": "jrlogin05.jureca",
"ecf_port": 4960 },
1 : { "ecf_host": "jrlogin09.jureca",
"ecf_port": 20932 },
2 : { "ecf_host": "jrlogin05.jureca",
"ecf_port": 4960 } }
base_url = f"{UNICORE_BASE}JURECA/rest/core"
# Authentification/Authorization
credentials = uc_credentials.UsernamePassword(UNICORE_USER, UNICORE_PASSWORD)
client = uc_client.Client(credentials, base_url)
# query status of ecflow jobs
executable = "ecflow_client"
environment = [ "PYTHONPATH=$PYTHONPATH:/p/project/cjicg21/jicg2126/ecflow/ecFlow-5.11.0-Source/lib/python3.8/site-packages/ecflow",
"PATH=$PATH:/p/project/cjicg21/jicg2126/ecflow/ecFlow-5.11.0-Source/bin/",
"ECFLOW_DIR=/p/project/cjicg21/jicg2126/ecflow/ecFlow-5.11.0-Source",
f"ECF_HOST={application_settings[application]['ecf_host']}",
f"ECF_PORT={application_settings[application]['ecf_port']}" ]
arguments = [ f"--query dstate /{jobid}" ]
job_description = {"Executable": executable,
"Job type": "ON_LOGIN_NODE",
"Environment": environment,
"Arguments": arguments, }
job = client.new_job(job_description)
# job.poll() takes up to one minute! Let's try after 2 seconds
sleep(3)
try:
working_dir = job.working_dir
stdout_content = working_dir.stat("stdout").raw().readlines()
new_status = stdout_content[0].decode('utf-8').strip()
except:
new_status = 'queued'
# translate response from UNICORE to controlled vocabulary
if new_status == 'complete':
new_status_code = convoc_status_dict['finished']
elif new_status == 'active':
new_status_code = convoc_status_dict['active']
elif new_status == 'queued':
new_status_code = convoc_status_dict['waiting']
elif new_status == 'aborted' or new_status == 'suspended':
new_status_code = convoc_status_dict['aborted']
else:
new_status_code = -1
return new_status_code
def change_status_of_job(jobid, new_status):
conn = sqlite3.connect(DATA_PATH.joinpath('destine_de370c_users.db'))
cur = conn.cursor()
cur.execute(f"UPDATE jobs SET status={new_status} WHERE id='{jobid}'")
conn.commit()
conn.close()
def get_my_jobs_from_db(user_id=None, language_id=0):
data_from_db = []
if user_id:
conn = sqlite3.connect(DATA_PATH.joinpath('destine_de370c_users.db'))
cur = conn.cursor()
cmd = f"SELECT {', '.join(guiconst.job_fields)} FROM jobs WHERE user_id={user_id}"
cur.execute(cmd)
data_rows_from_db = cur.fetchall()
cur.execute("SELECT job_status, id FROM convoc_status")
convoc_status_from_db = cur.fetchall()
conn.close()
convoc_status_dict = dict(convoc_status_from_db)
# if status != 'finished':
# use /p/project/cjicg21/schroeder5/Destine_AQ/SCRIPTS/ECFLOW/query_status.bash jobnr
# to determine the actual status
# ==> there should be a refresh, whenever this tab is reloaded!
for job in data_rows_from_db:
job_dict = {}
for i, field in enumerate(guiconst.job_fields):
job_dict[field] = job[i]
job_status = job_dict['status']
if (job_status == convoc_status_dict['active']) or (job_status == convoc_status_dict['waiting']):
new_status = get_job_status(job_dict['id'].upper(), job_dict['application'], convoc_status_dict)
if job_status != new_status:
change_status_of_job(job_dict['id'], new_status)
job_status = new_status
data_from_db.append({guitr.jobs_columns[language_id][0]: guitr.application_text[language_id][job_dict['application']],
guitr.jobs_columns[language_id][1]: guitr.status_text[language_id][job_status],
guitr.jobs_columns[language_id][2]: dt.datetime.strptime(job_dict['start_date'],'%Y-%m-%d %H:%M').strftime(guitr.date_format2[language_id]),
guitr.jobs_columns[language_id][3]: "{} {}{}".format(job_dict['forecast_length'], guitr.day_label[language_id], guitr.day_plural_label[language_id] if job_dict['forecast_length'] > 1 else ""),
guitr.jobs_columns[language_id][4]: guitr.region_text[language_id][job_dict['region']],
guitr.jobs_columns[language_id][5]: "{}".format(guitr.species_options[language_id][job_dict['species']] if job_dict['species'] is not None \
else ",".join(guitr.species_options[language_id])),
guitr.jobs_columns[language_id][6]: "{}".format(guitr.metrics_options[language_id][job_dict['metric']] if job_dict['metric'] is not None else ""),
guitr.jobs_columns[language_id][7]: "{}".format(emis_info[language_id][" Name"][job_dict['emis_scen']] if job_dict['emis_scen'] is not None \
else (guitr.default_text[language_id] if job_dict['application'] == 0 else "")),
guitr.jobs_columns[language_id][8]: dt.datetime.strptime(job_dict['creation_date'],'%Y-%m-%d %H:%M').strftime(guitr.date_format2[language_id]),
guitr.jobs_columns[language_id][9]: job_dict['id']})
return data_from_db
def generate_jobs_table(user_id=None, language_id=0):
data_from_db = get_my_jobs_from_db(user_id, language_id)
return html.Div([
dash_table.DataTable(
id='tbl-interactive',
columns=[
{"name": i, "id": i} for i in guitr.jobs_columns[language_id]
],
data=data_from_db,
filter_action="native",
sort_action="native",
sort_mode="multi",
row_selectable="single",
style_header={"fontWeight": "bold"},
style_data_conditional=[
{
'if': {
'filter_query': '{Status} = "abgebrochen" or {Status} = "aborted"',
},
'color': 'tomato'
},
{
'if': {
'filter_query': '{Status} = "aktiv" or {Status} = "active"',
},
'color': '#528aae'
},
{
'if': {
'filter_query': '{Status} = "in der Warteschlange" or {Status} = "waiting"',
},
'color': '#bcd2e8'
},
]
),
html.Div(id='tbl'),
], style={'border': '1px solid black', 'border-width': '1px'})
def create_tabs_layout(user_id=None, language_id=0):
lhide = True
if user_id:
lhide = False
return dbc.Tabs([
# tab for "Description"
dbc.Tab(label=guitr.layout_cards[language_id][0], id="description_tab", children=[
create_description_content(language_id)
], tab_style={"font-size":"40px"}),
# tab for "Create Jobs"
dbc.Tab(label=guitr.layout_cards[language_id][1], id="create_jobs_tab", children=[
create_jobs_tab(language_id)
], tab_style={"font-size":"40px"}, disabled=lhide),
# tab for "My Jobs"
dbc.Tab(label=guitr.layout_cards[language_id][2], id="my_jobs_tab", children=[
generate_jobs_table(user_id=user_id, language_id=language_id),
generate_eurad_im_output_modal(language_id=language_id),
generate_ml_fcast_output_modal(language_id=language_id),
generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container", language_id=language_id)
], tab_style={"font-size":"40px"}, disabled=lhide),
], id='layout_tabs')
layout = html.Div([
aai_login,
register_modal,
create_tabs_layout(user_id=None, language_id=0),
# dcc.Store stores the user information
dcc.Store(id='user-info'),
# dcc.Store stores the jobs information
dcc.Store(id='job-info'),
# dcc.Store stores the plots information
dcc.Store(id='plot-info'),
])
@callback(
Output("login-background", "children"),
Output("user-info", "data"),
Output("layout_tabs", "children"),
Output("login_modal", "is_open", allow_duplicate=True),
Output("alert_nouser", "children"),
Input("login_button", "n_clicks"),
Input("login_close", "n_clicks"),
State("login_name", "value"),
State("login_password", "value"),
background=True,
running=[
(Output("login_close", "disabled"), True, False),
],
prevent_initial_call=True
)
def login_open(lb_click, lc_click, name, password):
if ctx.triggered_id == "login_close":
conn = sqlite3.connect(DATA_PATH.joinpath('destine_de370c_users.db'))
cur = conn.cursor()
cur.execute(f"SELECT id, password, language FROM users WHERE name ='{name}'")
user = cur.fetchone()
conn.close()
if not user:
return no_update, no_update, no_update, no_update, dbc.Alert(["No such user!"], color="danger")
else:
fernet = Fernet(KEY)
db_password = fernet.decrypt(user[1]).decode()
if db_password == password:
language_id=user[2]
return create_login_button(f"{guitr.user_label[language_id]} {name}"), \
'{"user_id": ' + f'{user[0]}, "language_id": {user[2]}' +'}', \
create_tabs_layout(user_id=user[0], language_id=language_id),\
False, no_update
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}', \
create_tabs_layout() , True, no_update
@callback(
[Output("register_modal", "is_open"),
Output("login_modal", "is_open", allow_duplicate=True)],
[Input("register_open", "n_clicks"),
Input("register_ok_button", "n_clicks"),
Input("register_close_button", "n_clicks")],
State("login_modal", "is_open"),
prevent_initial_call=True
)
def register_open(n1, n2, n3, login_is_open):
if n2 or n3:
return [False, False]
if n1:
return [True, False]
return [False, login_is_open]
@callback(
Output("tbl-interactive", "data"),
Output("my_jobs_tab", "children", allow_duplicate=True),
Input("user-info", "data"),
prevent_initial_call=True
)
def get_user_id(user_dict):
user_id = json.loads(user_dict)["user_id"]
language_id = json.loads(user_dict)["language_id"]
return get_my_jobs_from_db(user_id, language_id), \
[generate_jobs_table(user_id=user_id, language_id=language_id),
generate_eurad_im_output_modal(language_id=language_id),
generate_ml_fcast_output_modal(language_id=language_id),
generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container", language_id=language_id)]
@callback(
Output("eurad_im_modal", "is_open", allow_duplicate=True),
Input("eurad_im_open", "n_clicks"),
Input("eurad_im_close", "n_clicks"),
prevent_initial_call=True
)
def eurad_im_modal(open_button, close_button):
if ctx.triggered_id == "eurad_im_open":
return True
else:
return False
@callback(
[Output("eurad_im_modal", "is_open", allow_duplicate=True),
Output("my_jobs_tab", "children", allow_duplicate=True)],
Input("eurad_im_run", "n_clicks"),
[State("eurad_im_region_choice", "value"),
State('eurad_im_start_date', 'date'),
State('eurad_im_forecast_length', 'value'),
State("user-info", "data")],
background=True,
running=[
(Output("eurad_im_run", "disabled"), True, False),
],
prevent_initial_call=True
)
def eurad_im_job_run(run_button, region, startdate, forecast_length, user_dict):
# add job to user's job list
user_id = json.loads(user_dict)["user_id"]
language_id = json.loads(user_dict)["language_id"]
new_job_dict = {}
jobnr = get_random_string(12)
new_job_dict['id'] = jobnr
# application is EURAD-IM -- should be taken from the controlled vocabulary!
new_job_dict['application'] = 0
new_job_dict['region'] = region
new_job_dict['start_date'] = startdate + ' 00:00'
new_job_dict['forecast_length'] = int(forecast_length.split()[0])
forecast_hours = new_job_dict['forecast_length'] * 24
# take the coding for the status from the controlled vocabulary!
# set it to "waiting" since it will just be submitted
new_job_dict['status'] = 2
# EURAD-IM does not have any species to be chosen
new_job_dict['species'] = None
# EURAD-IM does not have any metrics to be chosen
new_job_dict['metric'] = None
# EURAD-IM does not have any emission scenario
new_job_dict['emis_scen'] = None
# submit job
base_url = f"{UNICORE_BASE}JURECA/rest/core"
credentials = uc_credentials.UsernamePassword(UNICORE_USER, UNICORE_PASSWORD)
client = uc_client.Client(credentials, base_url)
job_description = {'Executable': "/p/project/cjicg21/schroeder5/Destine_AQ/start_destine_demonstrator.sh",
'Job type': "ON_LOGIN_NODE",
'Arguments': [jobnr, "0", startdate, str(forecast_hours)], }
job = client.new_job(job_description)
# now create job in db (otherwise the status cannot be determined!)
create_db_job_entry(user_id, new_job_dict)
# return updated values
retval = ctx.triggered_id == "eurad_im_open"
return retval,\
[generate_jobs_table(user_id=user_id, language_id=language_id),
generate_eurad_im_output_modal(language_id=language_id),
generate_ml_fcast_output_modal(language_id=language_id),
generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container", language_id=language_id)]
@callback(
Output("ml_fcast_modal", "is_open", allow_duplicate=True),
Output("my_jobs_tab", "children", allow_duplicate=True),
Input("ml_fcast_run", "n_clicks"),
[State('ml_fcast_body_region', 'value'),
State('ml_fcast_body_startdate', 'date'),
State('ml_fcast_body_forecast_length', 'value'),
State('ml_fcast_body_species', 'value'),
State('ml_fcast_body_metrics', 'value'),
State("user-info", "data")],
prevent_initial_call=True
)
def ml_fcast_job_run(run_button, region, startdate, forecast_length, species, metrics, user_dict):
user_id = json.loads(user_dict)["user_id"]
language_id = json.loads(user_dict)["language_id"]
new_job_dict = {}
jobnr = get_random_string(12)
new_job_dict['id'] = jobnr
# application is MLAir -- should be taken from the controlled vocabulary!
new_job_dict['application'] = 1
new_job_dict['region'] = region
new_job_dict['start_date'] = startdate + ' 00:00'
new_job_dict['forecast_length'] = int(forecast_length.split()[0])
# also take the coding from the controlled vocabulary!
# set it to "waiting" since it will just be submitted
# job is not submitted --> job is already finished
# new_job_dict['status'] = 2
new_job_dict['status'] = 0
# at the moment only ozone is available!
new_job_dict['species'] = species
# at the moment only dma8eu is available!
new_job_dict['metric'] = metrics
# MLAir does not have any emission scenario
new_job_dict['emis_scen'] = None
# do not submit the job
# # submit job
# base_url = f"{UNICORE_BASE}JURECA/rest/core"
# credentials = uc_credentials.UsernamePassword(UNICORE_USER, UNICORE_PASSWORD)
# client = uc_client.Client(credentials, base_url)
# job_description = {'Executable': "/p/project/deepacf/intelliaq/schroeder5/ecflow_mlair/start_destine_mlair_demonstrator.sh", "Job type": "ON_LOGIN_NODE", 'Arguments':[jobnr], }
# job = client.new_job(job_description)
# now create job in db (otherwise the status cannot be determined!)
create_db_job_entry(user_id, new_job_dict)
retval = ctx.triggered_id == "ml_fcast_open"
return retval,\
[generate_jobs_table(user_id=user_id, language_id=language_id),
generate_eurad_im_output_modal(language_id=language_id),
generate_ml_fcast_output_modal(language_id=language_id),
generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container", language_id=language_id)]
@callback(
[Output("eurad_scen_modal", "is_open", allow_duplicate=True),
Output("my_jobs_tab", "children", allow_duplicate=True)],
Input("eurad_scen_run", "n_clicks"),
[State("eurad_scen_region_choice", "value"),
State('eurad_scen_start_date', 'date'),
State('eurad_scen_forecast_length', 'value'),
State('eurad_scen_emi', 'value'),
State("user-info", "data")],
background=True,
running=[
(Output("eurad_scen_run", "disabled"), True, False),
],
prevent_initial_call=True
)
def eurad_scen_job_run(run_button, region, startdate, forecast_length, emi_scen, user_dict):
# add job to user's job list
user_id = json.loads(user_dict)["user_id"]
language_id = json.loads(user_dict)["language_id"]
new_job_dict = {}
jobnr = get_random_string(12)
new_job_dict['id'] = jobnr
# application is EURAD-IM -- should be taken from the controlled vocabulary!
new_job_dict['application'] = 2
new_job_dict['region'] = region
new_job_dict['start_date'] = startdate + ' 00:00'
new_job_dict['forecast_length'] = int(forecast_length.split()[0])
new_job_dict['emis_scen'] = emi_scen
forecast_hours = new_job_dict['forecast_length'] * 24
# take the coding for the status from the controlled vocabulary!
# set it to "waiting" since it will just be submitted
new_job_dict['status'] = 2
# EURAD-IM does not have any species to be chosen
new_job_dict['species'] = None
# EURAD-IM does not have any metrics to be chosen
new_job_dict['metric'] = None
# submit job
base_url = f"{UNICORE_BASE}JURECA/rest/core"
credentials = uc_credentials.UsernamePassword(UNICORE_USER, UNICORE_PASSWORD)
client = uc_client.Client(credentials, base_url)
job_description = {'Executable': "/p/project/cjicg21/schroeder5/Destine_AQ/start_destine_demonstrator.sh",
'Job type': "ON_LOGIN_NODE",
'Arguments': [jobnr, str(emi_scen), startdate, str(forecast_hours)], }
job = client.new_job(job_description)
# now create job in db (otherwise the status cannot be determined!)
create_db_job_entry(user_id, new_job_dict)
# return updated values
retval = ctx.triggered_id == "eurad_scen_open"
return retval,\
[generate_jobs_table(user_id=user_id, language_id=language_id),
generate_eurad_im_output_modal(language_id=language_id),
generate_ml_fcast_output_modal(language_id=language_id),
generate_eurad_scen_output_modal(container_id="eurad_scen_output_modal_container", language_id=language_id)]
@callback(
Output("mlair_download_result", "data"),
Input("mlair_output_download", "n_clicks"),
State("job-info", "data"),
prevent_initial_call=True
)
def mlair_output_download(download_button, job_dict):
# jobid = json.loads(job_dict)["jobnr"]
# infile = str(DATA_PATH.joinpath('MLAIR', f'{jobid}.nc'))
# demonstrator
infile = str(DATA_PATH.joinpath('MLAIR', 'forecasts_DENW067_test.nc'))
return dcc.send_file(
infile
)
@callback(
Output("mlair_download_plot", "data"),
Input("mlair_plot_download", "n_clicks"),
[State("job-info", "data"),
State("plot-info", "data")],
prevent_initial_call=True
)
def mlair_plots_download(download_button, job_dict, plot_dict):
species = json.loads(plot_dict)["species"]
station = json.loads(plot_dict)["station"]
start_date = json.loads(plot_dict)["start_date"]
fc_length = json.loads(plot_dict)["fc_length"]
# file name according to users selection
output_file_name = f"mlair_{species}_{station}_{start_date}_{fc_length}.png"
infile = str(ASSETS_PATH.joinpath('mlair', output_file_name))
return dcc.send_file(
infile
)
@callback(
Output("eurad_im_download_result", "data"),
Input("eurad_im_output_download", "n_clicks"),
State("job-info", "data"),
prevent_initial_call=True
)
def eurad_im_output_download(download_button, job_dict):
jobid = json.loads(job_dict)["jobnr"]
infile = str(DATA_PATH.joinpath(f'{jobid}.nc'))
return dcc.send_file(
infile
)
@callback(
Output("eurad_im_download_plots", "data"),
Input("eurad_im_plots_download", "n_clicks"),
[State("job-info", "data"),
State("plot-info", "data")],
prevent_initial_call=True
)
def eurad_im_plots_download(download_button, job_dict, plot_dict):
jobid = json.loads(job_dict)["jobnr"]
station = json.loads(plot_dict)["station"]
species = json.loads(plot_dict)["variable"]
timestamp = json.loads(plot_dict)["time_step"]
language_id = json.loads(plot_dict)["language_id"]
ldiff = json.loads(plot_dict)["ldiff"]
ltarget = json.loads(plot_dict)["ltarget"]
# file names according to users selection
infile1 = f'job_{jobid}_station_{station}_species_{species}_time_{timestamp}_{language_id}.png'
if ltarget:
infile2 = "job_{}_time_{}_species_{}_station_{}_target_{}.png".format(jobid, timestamp, species, station, language_id)
elif ldiff:
infile2 = "job_{}_time_{}_species_{}_station_{}_diff_{}.png".format(jobid, timestamp, species, station, language_id)
else:
infile2 = "job_{}_time_{}_species_{}_station_{}_{}.png".format(jobid, timestamp, species, station, language_id)
files = [infile1, infile2]
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('eurad', file)),file)
zipf.close()
return dcc.send_file(
zipname
)
@callback(
Output("eurad_im_output_modal", "is_open"),
Input("eurad_im_output_close", "n_clicks"),
prevent_initial_call=True
)
def eurad_im_output_modal(close_button):
return False
@callback(
Output("ml_fcast_modal", "is_open"),
Input("ml_fcast_open", "n_clicks"),
Input("ml_fcast_close", "n_clicks"),
)
def ml_fcast_modal(open_button, close_button):
if ctx.triggered_id == "ml_fcast_open":
return True
else:
return False
@callback(
Output("ml_fcast_output_modal", "is_open"),
Input("ml_fcast_output_close", "n_clicks"),
prevent_initial_call=True
)
def ml_fcast_output_modal(close_button):
return False
@callback(
Output("eurad_scen_modal", "is_open"),
Input("eurad_scen_open", "n_clicks"),
Input("eurad_scen_close", "n_clicks"),
)
def eurad_scen_modal(open_button, close_button):
if ctx.triggered_id == "eurad_scen_open":
return True
else:
return False
@callback(
Output("eurad_scen_output_modal", "is_open"),
Input("eurad_scen_output_close", "n_clicks"),
prevent_initial_call=True
)
def eurad_scen_output_modal(close_button):
return False
@callback(
Output("help_metrics_modal", "is_open"),
Input("help_metrics_open", "n_clicks"),
Input("help_metrics_close", "n_clicks"),
)
def eurad_scen_modal(open_button, close_button):
if ctx.triggered_id == "help_metrics_open":
return True
else:
return False
@callback(
Output("help_emis_modal", "is_open"),
Input("help_emis_open", "n_clicks"),
Input("help_emis_close", "n_clicks"),
)
def eurad_emis_modal(open_button, close_button):
if ctx.triggered_id == "help_emis_open":
return True
else:
return False
@callback(
Output('job-info', "data"),
State('tbl-interactive', "derived_virtual_data"),
Input('tbl-interactive', "derived_virtual_selected_rows"),
State('user-info', "data"),
prevent_initial_call=True
)
def postprocess_job(rows, derived_virtual_selected_rows, users_dict):
jobinfo_dict = {}
try:
language_id = json.loads(users_dict)["language_id"]
except:
language_id = 0
jobnr = "bla"
eurad_im_output_modal_isopen = False
ml_fcast_output_modal_isopen = False
eurad_scen_output_modal_isopen = False
# if ((derived_virtual_selected_rows != []) and (not derived_virtual_selected_rows)):
if (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]]
if status == guitr.status_text[language_id][0]:
eurad_im_output_modal_isopen = (application == guitr.application_text[language_id][0])
ml_fcast_output_modal_isopen = (application == guitr.application_text[language_id][1])
eurad_scen_output_modal_isopen = (application == guitr.application_text[language_id][2])
jobinfo_dict["jobnr"] = jobnr
jobinfo_dict["eurad_im_output_modal_isopen"] = eurad_im_output_modal_isopen
jobinfo_dict["ml_fcast_output_modal_isopen"] = ml_fcast_output_modal_isopen
jobinfo_dict["eurad_scen_output_modal_isopen"] = eurad_scen_output_modal_isopen
jobinfo_json = json.dumps(jobinfo_dict)
return jobinfo_json
@callback(
# Output("eurad_im_output_modal_title", "value"),
# Output("eurad_im_output_modal", "is_open"),
Output("eurad_im_output_modal_container", "children"),
Output("ml_fcast_output_modal_container", "children"),
Output("eurad_scen_output_modal_container", "children"),
Input("job-info", "data"),
State("user-info", "data"),
prevent_initial_call=True
)
def get_jobs(jobs_dict, users_dict):
jobnr = json.loads(jobs_dict)["jobnr"]
try:
language_id = json.loads(users_dict)["language_id"]
except:
language_id = 0
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"]
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