Commit 9502fa63 authored by Samuël Weber's avatar Samuël Weber
Browse files

multiple improvment

parent 33da8852
......@@ -10,16 +10,38 @@ import pyOPestimator
def get_station_dropdown_component(stations):
station_dropdown_component = html.Div(
style={"position": "relative"},
children=[
html.Label('Station'),
dcc.Dropdown(
id="station-dropdown",
options=[{'label': s, 'value': s} for s in stations],
multi=True,
value=["CHAM"]
html.Div(
children=[
dbc.InputGroup(
[
dbc.InputGroupAddon(
[
dbc.Button(
id="select-all-stations",
children=["Select all"],
),
dbc.Button(
id="clear-all-stations",
children=["Clear all"],
),
],
addon_type="prepend"
),
dcc.Dropdown(
id="station-dropdown",
options=[{'label': s, 'value': s} for s in stations],
value=["CHAM"],
multi=True
),
],
className="dash-bootstrap",
),
]
)
],
style={"position": "relative"}
)
return station_dropdown_component
......@@ -221,7 +243,7 @@ def get_boxplot_options_component(id=None):
id=id+"-boxplot-options" if id else "boxplot-options",
children=[
html.Div([
html.Label('Graph type: '),
html.Label('Select the graphic type: '),
dcc.RadioItems(
id=id+'-boxplot-options-graph-type' if id else 'boxplot-options-graph-type',
className='options-items',
......@@ -233,7 +255,7 @@ def get_boxplot_options_component(id=None):
)
]),
html.Div([
html.Label('Group by: '),
html.Label('Select how to group by (i.e. x axis): '),
dcc.RadioItems(
id=id+'-boxplot-options-groupby' if id else 'boxplot-options-groupby',
className='options-items',
......@@ -250,6 +272,8 @@ def get_boxplot_options_component(id=None):
def get_rawdata_monthly_component():
monthly_boxplot_component = [
html.H3("Monthly aggregated view of variables"),
dcc.Markdown("You can select multiple station and PMF factor and OP at a time"),
get_boxplot_options_component(id="monthly"),
dcc.Loading(
dcc.Graph(
......@@ -262,6 +286,8 @@ def get_rawdata_monthly_component():
def get_rawdata_seasonal_component():
seasonal_boxplot_component = [
html.H3("Seasonal aggregated view of variables"),
dcc.Markdown("You can select multiple station and PMF factor and OP at a time"),
get_boxplot_options_component(id="seasonal"),
dcc.Loading(
dcc.Graph(
......@@ -274,6 +300,8 @@ def get_rawdata_seasonal_component():
def get_rawdata_timeserie_component():
timeserie_component = [
html.H3("Timeserie of the measured OP or PMF sources contribution to PM10"),
dcc.Markdown("You can select multiple station and PMF factor and OP at a time"),
dcc.Loading(
dcc.Graph(
id='ts-graph',
......@@ -333,15 +361,30 @@ def get_profile_component():
"""Dispersion of the concentration of specie in factor from the
constrained run of all sites.""",
),
dcc.Markdown(
"""
Percentage of each species apportionned by the given source (in %) and relative
mass contribution to the PM10 mass (in g.g⁻¹).
The variability presented here come from the different sites selected (1
value per site).
"""
),
dbc.Row(
[
dcc.Graph(
id="concentration-graph",
figure={'data': [], "layout": {"title": "Relative concentration"}}
figure={'data': [], "layout": {"title": "Relative concentration"}},
className="col-xl-6"
),
dcc.Graph(
id="totalspeciesum-graph",
figure={'data': [], "layout": {"title": "Contribution to total specie sum"}}
figure={'data': [], "layout": {"title": "Contribution to total specie sum"}},
className="col-xl-6"
)
]
)
]
)
return profile_component
......@@ -438,14 +481,17 @@ def get_specie_repartition_component():
id="specie-repartition-component",
children=[
dcc.Loading(
dcc.Graph(
id="repartition-graph",
figure={
'data': [],
'layout': {
'title': 'Specie repartition among factors (Loading...)',
html.Div(
id="repartition-graph-container",
children=dcc.Graph(
id="repartition-graph",
figure={
'data': [],
'layout': {
'title': 'Specie repartition among factors (Loading...)',
}
}
}
)
)
)
]
......@@ -545,6 +591,7 @@ def get_op_contribution_ts_component():
id="op-contribution-ts-component",
children=[
html.H3("Contribution of PMF factors to the OP (timeserie per site)"),
dbc.Label("Select the frequency to aggregate: "),
dcc.RadioItems(
id='op-contribution-ts-plottype',
className='options-items',
......@@ -556,32 +603,42 @@ def get_op_contribution_ts_component():
value='daily',
),
html.Br(),
dcc.Dropdown(
id='op-contribution-ts-station-dropdown',
className='dropdown',
options=[{"label": "CHAM", "value": "CHAM"}],
value=["CHAM"],
multi=False,
),
dcc.RadioItems(
id='op-contribution-ts-estimator',
className='options-items',
options=[
{'label': 'Mean', 'value': 'mean'},
{'label': 'Median', 'value': 'median'}
# dcc.Dropdown(
# id='op-contribution-ts-station-dropdown',
# className='dropdown',
# options=[{"label": "CHAM", "value": "CHAM"}],
# value=["CHAM"],
# multi=False,
# ),
html.Div(
id="op-contribution-ts-statistical-indicator",
children=[
dbc.Label("Select the statistical indicator (i.e. aggregation function): "),
dcc.RadioItems(
id='op-contribution-ts-estimator',
className='options-items',
options=[
{'label': 'Mean', 'value': 'mean'},
{'label': 'Median', 'value': 'median'}
],
value='median',
)
],
value='median',
),
dcc.Markdown("""
**Daily** is the daily reconstructed OP from the
regression model. You have to chose only one station from
the little dropdown above. The default one is "CHAM".
**Monthly** (mean or median) are the monthly aggregated mean or median for each station. **Quaterly** is the seasonal (4 seasons: DJF, MAM, JJA, SON) mean or median aggratation per station. This plot may take some time to generate...
**Monthly** (mean or median) are the monthly aggregated mean or median for each station. **Quaterly** is the seasonal (4 seasons: DJF, MAM, JJA, SON) mean or median aggretation per station.
The bars represent the contribution of each source to
the OP (in nmol.min⁻¹.m⁻³) and the line and dot are the
observed OP.
This plot may take some time to generate and is better rendered one
station at a time.
"""),
dcc.Loading(
dcc.Graph(
......
......@@ -128,11 +128,11 @@ layout = dbc.Container(
dbc.ListGroupItemHeading("PMF factor chemistry"),
dbc.NavLink('Profile and contribution per station',
href='/results?component=pmf_profile_and_contribution', id='item-pmf_profile_and_contribution'),
dbc.NavLink('Profiles comparison',
dbc.NavLink('Profiles chemical comparison between station',
href='/results?component=pmf_profiles', id='item-pmf_profiles'),
dbc.NavLink('DeltaTool',
dbc.NavLink('Profiles chemical similitude (DeltaTool)',
href="/results?component=pmf_deltatool", id='item-pmf_deltatool'),
dbc.NavLink('Uncertainties',
dbc.NavLink('Concentration uncertainties (BS and DISP) between station',
href="/results?component=pmf_unc", id='item-pmf_unc'),
dbc.NavLink('Species repartition',
href="/results?component=pmf_speciesrepartition", id='item-pmf_speciesrepartition'),
......@@ -194,6 +194,47 @@ def toggle_items_collapse(n, is_open):
return not is_open
return is_open
@app.callback(Output('source-dropdown', 'options'),
[Input('station-dropdown', 'value')])
def set_source_option(stations_dd):
"""Set the possible source dropdown"""
conn = sqlite3.connect(DBPATH)
query = "SELECT * FROM SRC WHERE station IN ('{stations}')".format(
stations="', '".join(stations_dd)
)
sources = pd.read_sql(query, con=conn).dropna(axis=1, how='all').columns
conn.close()
# sources = []
# sources = profile.loc[profile["station"].isin(stations_dd)].dropna(axis=1, how='all').columns
sources = set(sources) - set(BASE_VAR_SRC)
sources = list(sources)
remove_var = ["Specie", "index"]
for var in remove_var:
if var in sources:
sources.remove(var)
sources.sort()
return [{'label': i.replace("_", " "), 'value': i} for i in sources]
@app.callback(Output('station-dropdown', 'value'),
[
Input('select-all-stations', 'n_clicks_timestamp'),
Input('clear-all-stations', 'n_clicks_timestamp')
],
[
State('station-dropdown', 'value')
]
)
def select_all_station(select_time, clear_time, current_values):
if all([x is None for x in [select_time, clear_time]]):
return current_values
if clear_time is None or (select_time is not None and (select_time > clear_time)):
values = [i for i in settings.STATION_ORDER]
elif select_time is None or (clear_time is not None and (clear_time > select_time)):
values = []
return values
@app.callback(Output('specie-dropdown', 'options'),
[Input('station-dropdown', 'value')])
def set_specie_option(stations):
......@@ -249,29 +290,6 @@ def get_op_options(stations):
return options
@app.callback(Output('source-dropdown', 'options'),
[Input('station-dropdown', 'value')])
def set_source_option(stations_dd):
"""Set the possible source dropdown"""
conn = sqlite3.connect(DBPATH)
query = "SELECT * FROM SRC WHERE station IN ('{stations}')".format(
stations="', '".join(stations_dd)
)
sources = pd.read_sql(query, con=conn).dropna(axis=1, how='all').columns
conn.close()
# sources = []
# sources = profile.loc[profile["station"].isin(stations_dd)].dropna(axis=1, how='all').columns
sources = set(sources) - set(BASE_VAR_SRC)
sources = list(sources)
remove_var = ["Specie", "index"]
for var in remove_var:
if var in sources:
sources.remove(var)
sources.sort()
return [{'label': i.replace("_", " "), 'value': i} for i in sources]
@app.callback(Output('OP-dropdown-source', 'options'),
[Input('station-dropdown', 'value')])
def set_source_option(stations_dd):
......@@ -346,7 +364,7 @@ def disable_op_contribution_ts_estimator(plottype):
else:
return {"display": "None"}
@app.callback(Output('op-contribution-ts-estimator', 'style'),
@app.callback(Output('op-contribution-ts-statistical-indicator', 'style'),
[
Input('op-contribution-ts-plottype', 'value'),
],
......@@ -375,14 +393,18 @@ def update_ts_graph(stations, species, sources):
"""
traces = []
returnError = {
figure = {
'data': traces,
'layout': {'title': 'PM concentration'}
'layout': {'title': 'Evolution'}
}
if (len(species) + len(sources)) == 0:
print("TS: len(species+sources)==0")
return returnError
figure["layout"]["title"] = "Select at least one source or OP"
return figure
if len(stations) == 0:
figure["layout"]["title"] = "Select at least one station"
return figure
nbPlot = len(stations) * (len(sources))
if nbPlot > tooManyPlot:
......@@ -427,11 +449,18 @@ def update_ts_graph(stations, species, sources):
groupby += [] # "programme PMF"]
traces += [i for i in ac.plot_ts(dftmp, station, var, groupby)]
units = []
if len(sources) > 0:
units.append("µg.m⁻³")
if len(species) > 0:
units.append("nmol.min⁻¹.m⁻³")
units = " or ".join(units)
figure = {
'data': traces,
'layout': go.Layout(
title="PM concentration",
yaxis={"title": 'µg/m3'},
title="PM concentration or OPv",
yaxis={"title": units},
showlegend=True,
margin=go.layout.Margin(
l=50,
......@@ -460,13 +489,18 @@ def update_monthlybox_graph(plots_options, groupby_var, species, sources,
"""Seasonal boxplot or barplot"""
traces = []
returnError = {
figure = {
'data': traces,
'layout': {'title': 'Seasonal dispersion'}
}
if (len(species) + len(sources)) == 0:
return returnError
figure["layout"]["title"] = "Select at least one factor or OP"
return figure
if len(stations) == 0:
figure["layout"]["title"] = "Select at least one station"
return figure
dfdt = ac.get_contribution(sources, species, stations)
......@@ -493,9 +527,16 @@ def update_monthlybox_graph(plots_options, groupby_var, species, sources,
dfdt = ac.add_month(dfdt, season=True)
units = []
if len(sources) > 0:
units.append("µg.m⁻³")
if len(species) > 0:
units.append("nmol.min⁻¹.m⁻³")
units = " or ".join(units)
return update_grouped_box(df=dfdt, species=species, sources=sources,
x_var_col=x_var_col, hue_var_list=hue_var_list, hue_var_col=hue_var_col,
plot_type=plot_type, xticklabels=xticklabels)
plot_type=plot_type, xticklabels=xticklabels, units=units)
@app.callback(Output('seasonal-box-graph', 'figure'),
[
......@@ -510,13 +551,19 @@ def update_seasonalbox_graph(plots_options, groupby_var, species, sources,
"""Seasonal boxplot or barplot"""
traces = []
returnError = {
figure = {
'data': traces,
'layout': {'title': 'Seasonal dispersion'}
}
if (len(species) + len(sources)) == 0:
return returnError
figure["layout"]["title"] = "Select at least one factor or OP"
return figure
if len(stations) == 0:
figure["layout"]["title"] = "Select at least one station"
return figure
dfdt = ac.get_contribution(sources, species, stations)
......@@ -543,9 +590,16 @@ def update_seasonalbox_graph(plots_options, groupby_var, species, sources,
dfdt = ac.add_month(dfdt, season=True)
units = []
if len(sources) > 0:
units.append("µg.m⁻³")
if len(species) > 0:
units.append("nmol.min⁻¹.m⁻³")
units = " or ".join(units)
return update_grouped_box(df=dfdt, species=species, sources=sources,
x_var_col=x_var_col, hue_var_list=hue_var_list, hue_var_col=hue_var_col,
plot_type=plot_type, xticklabels=xticklabels)
plot_type=plot_type, xticklabels=xticklabels, units=units)
def get_grouped_box_options(plots_options, temporality, groupby_var, stations):
# ==== Plot option ========================================================
......@@ -574,7 +628,12 @@ def get_grouped_box_options(plots_options, temporality, groupby_var, stations):
return (plot_type, date_var_list, x_var_col, x_var_list, hue_var_col,
hue_var_list, xticklabels)
def update_grouped_box(df, species, sources, x_var_col, hue_var_list, hue_var_col, plot_type, xticklabels):
def update_grouped_box(df, species, sources, x_var_col, hue_var_list, hue_var_col,
plot_type, xticklabels, units=None):
"""Share utility to plot box graph"""
if units is None:
units = "µg.m⁻³"
# ==== Plot part ==========================================================
traces = []
for hue in hue_var_list:
......@@ -597,7 +656,7 @@ def update_grouped_box(df, species, sources, x_var_col, hue_var_list, hue_var_co
return {
'data': traces,
'layout': go.Layout(
yaxis={"title": "µg/m3"},
yaxis={"title": units},
xaxis={'categoryorder': 'array',
'categoryarray': xticklabels},
showlegend=True,
......@@ -720,7 +779,6 @@ def update_concentration_graph(sources, stations):
conn.close()
d = d / d.xs("PM10", level="Specie")
d = d.reset_index()
# d.replace({0: np.nan}, inplace=True)
for s in sources:
data.append(go.Box(
......@@ -734,8 +792,10 @@ def update_concentration_graph(sources, stations):
'data': data,
'layout': go.Layout(
title="Contribution to the mass of PM10",
yaxis={"title": "g/g of PM10",
"type": "log"},
yaxis={"title": "g.g⁻¹ of PM10",
"type": "log",
"range": [-6, 0.5]
},
xaxis={
'categoryorder': 'array',
'categoryarray': SPECIES_ORDER_WO_OP,
......@@ -1063,8 +1123,8 @@ def update_uncertainty_graph_conc(sources, species, stations):
)
layout = dict(
title="Contribution µg/m3",
yaxis={"title": "µg/m3"},
title="Contribution µg.m⁻³",
yaxis={"title": "µg.m⁻³"},
xaxis={'categoryorder': 'array',
'categoryarray': settings.STATION_ORDER},
boxmode='group',
......@@ -1095,7 +1155,7 @@ def update_uncertainty_graph_norm(sources, species, stations):
data = []
figure = {
"data": data,
"layout": {"title": "Contribution to µg/µg"}
"layout": {"title": "Contribution to g.g⁻¹"}
}
if len(stations) == 0:
......@@ -1179,10 +1239,10 @@ def update_uncertainty_graph_norm(sources, species, stations):
)
layout = dict(
title="Contribution to µg/µg",
title="Contribution to g.g⁻¹",
yaxis={
"title": "µg/µg",
"range": [0, 1],
"title": "g.g⁻¹",
# "range": [0, 1],
},
xaxis={'categoryorder': 'array',
'categoryarray': settings.STATION_ORDER},
......@@ -1327,7 +1387,7 @@ def update_deltatool_graph(sources, stations, graphOptions):
return to_return
@app.callback(Output('specie-repartition-component', 'children'),
@app.callback(Output('repartition-graph-container', 'children'),
[
Input('station-dropdown', 'value'),
])
......@@ -1348,13 +1408,8 @@ def update_specie_repartition_graph(stations):
if len(stations) == 0:
figure["layout"]["title"] = "Select at least 1 station"
return figure
# if len(sources) == 0:
# figure["layout"]["title"] = "Select at least 1 profile"
# return figure
# if len(species) == 0:
# figure["layout"]["title"] = "Select at least 1 specie"
# return figure
children = dcc.Graph(id="repartition-none", figure=copy.deepcopy(figure))
return children
query = "SELECT * FROM profiles_constrained WHERE Station IN ('{stations}');".format(
stations="', '".join(stations)
......@@ -1402,7 +1457,8 @@ def update_specie_repartition_graph(stations):
dcc.Graph(id="repartition-{station}".format(station=station),
figure=copy.deepcopy(figure))
)
return subplots
children = subplots
return children
@app.callback(Output('beta-coefficient-graph', 'figure'),
......@@ -1680,10 +1736,10 @@ def update_op_contribution_graph(stations, species, plot_type):
Input('station-dropdown', 'value'),
Input('OP-dropdown', 'value'),
Input('op-contribution-ts-plottype', 'value'),
Input('op-contribution-ts-station-dropdown', 'value'),
# Input('op-contribution-ts-station-dropdown', 'value'),
Input('op-contribution-ts-estimator', 'value'),
])
def update_op_contribution_ts_graph(stations, species, plot_type, stationts, estimator):
def update_op_contribution_ts_graph(stations, species, plot_type, estimator):
"""
"""
......@@ -1703,14 +1759,14 @@ def update_op_contribution_ts_graph(stations, species, plot_type, stationts, est
)
}
if plot_type == "daily":
if stationts is not None:
if isinstance(stationts, list):
stations = stationts
else:
stations = [stationts]
else:
stations = []
# if plot_type == "daily":
# if stationts is not None:
# if isinstance(stationts, list):
# stations = stationts
# else:
# stations = [stationts]
# else:
# stations = []
species = list(set(species).intersection(set(["DTTv", "AAv"])))
if len(species) != 1:
......
......@@ -74,3 +74,12 @@ p {
#upload-col {
max-width: 30%;
}
.dash-bootstrap .input-group-prepend + div {
flex-grow: 1;
}
.dash-bootstrap .input-group-prepend + div .Select-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment