Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
pmall
app_OP
Commits
dde358df
Commit
dde358df
authored
Jul 28, 2020
by
Samuël Weber
Browse files
estimate works
parent
bf7ad3e1
Changes
5
Hide whitespace changes
Inline
Side-by-side
apps/app_components.py
View file @
dde358df
...
...
@@ -4,6 +4,7 @@ import dash_html_components as html
import
plotly.graph_objs
as
go
import
pandas
as
pd
import
sqlite3
import
pyOPestimator
def
get_station_dropdown_component
(
stations
):
...
...
@@ -632,6 +633,59 @@ def get_estimate_warning_component():
return
component
def
get_monthly_relative_contribution
():
"""TODO: Docstring for get_monthly_relative_contribution.
:returns: TODO
"""
dfpm
=
pd
.
DataFrame
(
index
=
pd
.
DatetimeIndex
(
freq
=
"M"
,
start
=
"2018-01-01"
,
end
=
"2019-01-01"
),
columns
=
[
"PM10"
],
data
=
[
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
]
)
dfpm
.
index
.
name
=
"Date"
dfpm
=
dfpm
.
reset_index
()
dfopDTT
,
dfrel
=
pyOPestimator
.
get_op_from_pm10
(
dfpm
,
"DTTv"
)
dfopAA
,
_
=
pyOPestimator
.
get_op_from_pm10
(
dfpm
,
"AAv"
)
dfopDTT
=
dfopDTT
.
melt
(
id_vars
=
[
"Date"
,
"totalOP"
,
"month"
,
"PM10"
],
var_name
=
"Factor"
,
value_name
=
"OP"
)
dfopAA
=
dfopAA
.
melt
(
id_vars
=
[
"Date"
,
"totalOP"
,
"month"
,
"PM10"
],
var_name
=
"Factor"
,
value_name
=
"OP"
)
factors
=
dfopDTT
[
'Factor'
].
unique
()
colors
=
{}
for
factor
in
factors
:
colors
[
factor
]
=
get_sourceColor
(
source
=
factor
)
fignormDTT
=
px
.
area
(
dfopDTT
,
x
=
"Date"
,
y
=
"OP"
,
color
=
"Factor"
,
color_discrete_map
=
colors
)
fignormDTT
.
update_yaxes
(
{
"title"
:
"OP DTT relative montly contribution (%)"
}
)
fignormAA
=
px
.
area
(
dfopAA
,
x
=
"Date"
,
y
=
"OP"
,
color
=
"Factor"
,
color_discrete_map
=
colors
)
fignormAA
.
update_yaxes
(
{
"title"
:
"OP AA relative montly contribution (%)"
}
)
component
=
dbc
.
Row
(
dbc
.
Col
(
)
)
def
plot_ts
(
df
,
station
,
var
,
groupby
):
"""Set a trace for plotly of the timeserie var in df for the given station,
grouped by groupby.
...
...
apps/app_estimateOP.py
View file @
dde358df
...
...
@@ -20,6 +20,7 @@ NCLICKED = 0
layout
=
dbc
.
Container
(
id
=
"container-results"
,
children
=
[
dcc
.
Store
(
id
=
'memory-op'
),
dbc
.
Row
([
dbc
.
Col
(
id
=
"upload-col"
,
...
...
@@ -28,20 +29,18 @@ layout = dbc.Container(
id
=
'upload-data'
,
children
=
html
.
Div
([
dcc
.
Markdown
(
"""
[Select Files](#ref) (`.csv` or `.xls(x)` with a `Date` and `PM10` column)
[Select Files](#ref)
(`.csv` or `.xls(x)` with a `Date` and `PM10` column)
"""
,
id
=
"select-file"
),
]),
style
=
{
'width'
:
'100%'
,
'height'
:
'60px'
,
'lineHeight'
:
'60px'
,
'borderWidth'
:
'1px'
,
'borderStyle'
:
'dashed'
,
'borderRadius'
:
'5px'
,
'textAlign'
:
'center'
,
'margin'
:
'10px'
},
# Allow multiple files to be uploaded
multiple
=
False
...
...
@@ -72,13 +71,49 @@ layout = dbc.Container(
id
=
"graph-col"
,
width
=
9
,
children
=
[
ac
.
get_options_estimate_component
(),
dcc
.
Markdown
(
"### First order estimator of OP from PM10 concentration"
),
dcc
.
Loading
(
dcc
.
Graph
(
id
=
"graph"
)),
ac
.
get_estimate_warning_component
()
]
)
])
dbc
.
Row
(
[
dbc
.
Col
(
[
dcc
.
Markdown
(
"### First order estimator of OP from PM10 concentration"
),
ac
.
get_options_estimate_component
(),
dcc
.
Loading
(
[
dcc
.
Graph
(
id
=
"graph-abs"
)]
),
],
className
=
"col-12"
),
dbc
.
Col
(
html
.
Div
(
id
=
'output-data-op'
,
children
=
[
dash_table
.
DataTable
(
id
=
"datatable-op"
,
sort_action
=
"native"
,
sort_mode
=
"multi"
,
filter_action
=
'native'
,
page_size
=
5
,
export_columns
=
'all'
,
export_format
=
"xlsx"
,
style_cell
=
{
'overflow'
:
'hidden'
,
'textOverflow'
:
'ellipsis'
,
'maxWidth'
:
0
,
},
),
]
),
className
=
'col-9'
),
],
className
=
"justify-content-center"
),
dbc
.
Row
(
ac
.
get_estimate_warning_component
(),
)
]
)
])
],
fluid
=
True
,
# end container
...
...
@@ -124,6 +159,9 @@ def parse_contents(contents, filename):
def
update_output
(
content
,
name
,
clicked
):
errors
=
[]
global
NCLICKED
if
clicked
is
None
:
clicked
=
0
if
clicked
>
NCLICKED
:
df
=
pyOPestimator
.
load_dataset
(
"atmoaura_GRE-fr_pm10"
)
data
=
df
.
to_dict
(
'records'
)
...
...
@@ -158,11 +196,32 @@ def update_output(content, name, clicked):
)
return
(
data
,
columns
,
flash
)
@
app
.
callback
(
Output
(
'graph'
,
'figure'
),
[
Input
(
'datatable'
,
'derived_virtual_data'
),
Input
(
'option-OPtype'
,
'value'
),
Input
(
'option-temporality'
,
'value'
),
])
@
app
.
callback
(
Output
(
'memory-op'
,
'data'
),
[
Input
(
'datatable'
,
'derived_virtual_data'
),
Input
(
'option-OPtype'
,
'value'
),
])
def
update_storage
(
dfpm
,
OPtype
):
if
dfpm
is
None
or
len
(
dfpm
)
==
0
:
raise
PreventUpdate
dfpm
=
pd
.
DataFrame
(
dfpm
)
dfpm
[
"Date"
]
=
pd
.
to_datetime
(
dfpm
[
"Date"
])
dfop
=
pyOPestimator
.
get_op_from_pm10
(
dfpm
,
OPtype
)
factors
=
list
(
dfop
.
drop
([
"Date"
,
"month"
,
"PM10"
,
"totalOP"
],
axis
=
1
).
columns
)
# dfop = dfop.melt(id_vars=["Date", "totalOP", "month", "PM10"], var_name="Factor",
# value_name="OP")
return
dfop
.
to_dict
(
'record'
)
@
app
.
callback
(
Output
(
'graph-abs'
,
'figure'
),
[
Input
(
'datatable'
,
'derived_virtual_data'
),
Input
(
'option-OPtype'
,
'value'
),
Input
(
'option-temporality'
,
'value'
),
],
)
def
update_graph
(
dfpm
,
OPtype
,
temporality
):
"""update the estimated PM OP graph
...
...
@@ -185,20 +244,48 @@ def update_graph(dfpm, OPtype, temporality):
dfop
=
dfop
.
shift
(
-
15
,
freq
=
"D"
).
reset_index
()
dfop
=
dfop
.
melt
(
id_vars
=
[
"Date"
,
"totalOP"
,
"month"
,
"PM10"
],
var_name
=
"Factor"
,
value_name
=
"OP"
)
# dfop = pd.DataFrame(dfop)
# factors = dfop["Factor"].unique()
#
# if temporality == "monthly":
# dfop = dfop.groupby(
# pd.Grouper(key="Date", freq="M")
# ).mean()
# dfop = dfop.shift(-15, freq="D").reset_index()
colors
=
{}
for
factor
in
factors
:
colors
[
factor
]
=
ac
.
get_sourceColor
(
source
=
factor
)
fig
=
px
.
area
(
fig
abs
=
px
.
area
(
dfop
,
x
=
"Date"
,
y
=
"OP"
,
color
=
"Factor"
,
color_discrete_map
=
colors
)
fig
.
update_yaxes
(
fig
abs
.
update_yaxes
(
{
"title"
:
"OP {} estimation (nmol.min⁻¹.m⁻³)"
.
format
(
OPtype
)}
)
return
fig
return
figabs
@
app
.
callback
([
Output
(
'datatable-op'
,
'data'
),
Output
(
'datatable-op'
,
'columns'
)
],
[
Input
(
'memory-op'
,
'data'
)
],
[
State
(
'option-OPtype'
,
'value'
),
]
)
def
add_op_to_datatable
(
dfop
,
OPtype
):
df
=
pd
.
DataFrame
(
dfop
)
df
[
"Date"
]
=
pd
.
to_datetime
(
df
[
"Date"
])
df
[
"total_{}"
.
format
(
OPtype
)]
=
df
[
"totalOP"
]
df
.
drop
(
"totalOP"
,
axis
=
1
,
inplace
=
True
)
data
=
df
.
to_dict
(
'records'
)
columns
=
[{
'name'
:
i
,
'id'
:
i
}
for
i
in
df
.
columns
]
return
(
data
,
columns
)
estimate.mdwn
View file @
dde358df
...
...
@@ -3,24 +3,35 @@
### Method
Gathering several research program in France metropolitan area succeed to estimate a
climatology of the PM10 sources contribution to the ambient PM10 concentration.
We are then able to estimate a roughly monthly mean relative contribution of each sources to the PM10.
Then, for a given day of PM10 measurement, we can estimate the relative
contribution of a set of common sources found in the metropolitan territory.
We should keep in mind that this is a crude approximation since it does not
climatology of the PM<sub>10</sub> sources contribution to the ambient
PM<sub>10</sub> concentration in urbanized area ([Weber et al.
2019](https://www.mdpi.com/2073-4433/10/6/310) & the SOURCES project
[http://pmsources.u-ga.fr/](http://pmsources.u-ga.fr/)). Hence, we are able to
estimate a roughly monthly mean relative contribution of each sources to the
PM<sub>10</sub> concentration.
Thus, we can roughly estimate the contribution of the majority sources of PM<sub>10</sub>
for a given day, considering that this sampling is representative of our data
set. We should keep in mind that this is a crude approximation since it does not
take into account for local specificities nor for variation over year of the
sources contributions.
Finally, thanks to the recent development of the scientific community, and notably
Weber et al. 2020 for the France area, we can attribute an oxidative
[
Weber et al. 2020
](#ref)
for the France area, we can attribute an oxidative
potential (OP) of a set of sources. A simple multiplication end up with the
sources contribution to the oxidative potential of PM.
sources contribution to the oxidative potential of PM
<sub>10</sub>
.
### Pitfall
This method is a crude, first order approximation of the sources contribution
to the ambient PM10 concentration. The learning set is representative of
urbanized area over France, for year between 2013 to 2018.
The oxidative potential of the sources does present some variation for a given source
at different location. In this method we only take into account for the mean value of them.
For this two reason, this method should be used cautiously and only give a first
idea of what could be the OP of your PM10 timeserie.
**This method is a crude, first order approximation** of the sources contribution
to the ambient PM<sub>10</sub> concentration. The learning set is representative of
14 urbanized area over France, for years between 2013 to 2018 and your site
location may be influenced by sources not present in our learning set. Notably,
it assumes a steady state situation for the relative contribution of the
sources which may be deemed invalid when evaluating the impact of Low Emission Zone for
instance.
Moreover, **the oxidative potential of the sources do present some variation for a given source**
at different location but this method we only take into account for the mean value of them.
For this two reasons, this method should be used cautiously and only give a first
idea of what could be the OP of your PM<sub>10</sub> timeserie.
requirements-freeze.txt
View file @
dde358df
...
...
@@ -21,7 +21,6 @@ matplotlib==3.0.3
numpy==1.18.1
pandas==0.25.3
patsy==0.5.1
pkg-resources==0.0.0
plotly==4.5.0
py4pm==0.3
pyOPestimator==0.1.1
...
...
requirements.txt
View file @
dde358df
...
...
@@ -11,3 +11,4 @@ scipy
statsmodels
py4pm
pyOPestimator
xlrd
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment