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
apli_pmall
Commits
f2c1a18f
Commit
f2c1a18f
authored
Feb 09, 2018
by
Samuël Weber
Browse files
clean dir
parent
9d2fdbd9
Changes
3
Hide whitespace changes
Inline
Side-by-side
apli_bdd_aerosols.py
deleted
100644 → 0
View file @
9d2fdbd9
# -*- coding: utf-8 -*-
import
dash
import
dash_auth
from
dash.dependencies
import
Input
,
Output
,
State
import
dash_core_components
as
dcc
import
dash_html_components
as
html
import
dash_table_experiments
as
dt
import
plotly.graph_objs
as
go
import
urllib
import
pandas
as
pd
import
sqlite3
from
app_setting
import
server_setting
,
BDDPATH
,
BASEURL
,
ENABLE_AUTH
,
VALID_USERNAME_PASSWORD_PAIRS
def
add_season
(
df
):
"""
Add a season column to the DataFrame df from it index.
copy: Boolean, default False
either or not copy the initial dataframe
"""
month_to_season
=
pd
.
np
.
array
([
None
,
'DJF'
,
'DJF'
,
'MAM'
,
'MAM'
,
'MAM'
,
'JJA'
,
'JJA'
,
'JJA'
,
'SON'
,
'SON'
,
'SON'
,
'DJF'
])
df_tmp
=
df
.
copy
()
# ensure we have date in index
df_tmp
.
index
=
pd
.
to_datetime
(
df_tmp
[
"date"
])
df_tmp
[
"season"
]
=
month_to_season
[
df_tmp
.
index
.
month
]
df_tmp
[
"season"
]
=
df_tmp
[
"season"
].
astype
(
"category"
)
df_tmp
[
"season"
].
cat
.
set_categories
([
"DJF"
,
"MAM"
,
"JJA"
,
"SON"
],
inplace
=
True
)
return
df_tmp
conn
=
sqlite3
.
connect
(
"{BDDPATH}/db.sqlite"
.
format
(
BDDPATH
=
BDDPATH
))
df
=
pd
.
read_sql
(
'SELECT * FROM `values_all`;'
,
conn
)
df
.
date
=
pd
.
to_datetime
(
df
.
date
)
list_station
=
df
.
station
.
unique
()
list_station_OP
=
df
.
loc
[
pd
.
notnull
(
df
[
"PO_AA_m3"
]),
"station"
].
unique
()
notNumeric
=
[
"index"
,
"number ID"
,
"date"
,
"sample ID"
,
"sample ID_PO"
,
"sample ID_chem"
,
"Particle size"
,
"commentary"
,
"big serie"
,
"station"
]
# do not add species to plot when we already have too many...
tooManyPlot
=
30
minSample
=
40
class
AppOptions
():
def
__init__
(
self
,
tsplot
=
True
,
boxplot
=
True
):
self
.
tsplot
=
tsplot
self
.
boxplot
=
boxplot
LocalOption
=
AppOptions
()
getting_help_text
=
'''
### Getting help
#### Dash
This app is written with [Dash](https://plot.ly/dash/), so the graph are
interactive and responsive. *Hover* over points to see their values, *click* on
legend items to toggle traces, *click and drag* to zoom, *hold down shift, and
click and drag* to pan.
#### This app
Check the [README file](https://github.com/weber-s/apli_dash) on github for an
example on how to use this app.
'''
app
=
dash
.
Dash
(
url_base_pathname
=
BASEURL
)
if
ENABLE_AUTH
:
auth
=
dash_auth
.
BasicAuth
(
app
,
VALID_USERNAME_PASSWORD_PAIRS
)
app
.
layout
=
html
.
Div
(
children
=
[
html
.
Div
(
children
=
[
html
.
Div
(
children
=
[
'''Select station(s) and specie(s).'''
,
html
.
Div
(
children
=
[
html
.
Label
(
'Station'
),
dcc
.
Dropdown
(
id
=
"station-dropdown"
,
options
=
[{
'label'
:
s
,
'value'
:
s
}
for
s
in
list_station
if
df
[
df
[
"station"
]
==
s
].
shape
[
0
]
>
minSample
],
multi
=
True
,
value
=
[
"ANDRA-PM10"
]
),
html
.
Div
(
children
=
[
"""Minimum sample #"""
,
dcc
.
Slider
(
id
=
'nbsample-slider'
,
marks
=
{
str
(
i
):
i
for
i
in
pd
.
np
.
arange
(
0
,
301
,
10
)},
min
=
0
,
max
=
300
,
value
=
50
),
],
style
=
{
'display'
:
'inline-block'
,
'width'
:
'80%'
}),
html
.
Div
(
dcc
.
Checklist
(
id
=
'hasOP_check'
,
options
=
[{
'label'
:
'With OP'
,
'value'
:
'hasOP'
}],
values
=
[
'noOP'
],
labelStyle
=
{
'display'
:
'block'
}
),
style
=
{
'display'
:
'inline-block'
,
'vertical-align'
:
'top'
,
'margin-left'
:
'15px'
}
),
html
.
Br
(),
html
.
Label
(
'Species'
),
dcc
.
Dropdown
(
id
=
'specie-dropdown'
,
options
=
[{
'label'
:
"OC"
,
'value'
:
"OC"
}],
multi
=
True
,
value
=
[
"date"
,
"Particle size"
,
"station"
]
),
]),
html
.
Div
([
html
.
Div
([
html
.
Button
(
id
=
'refresh-button'
,
children
=
"Refresh download data"
),
html
.
A
(
children
=
'>Download link<'
,
id
=
'download-data'
,
download
=
"rawdata.csv"
,
href
=
""
,
target
=
"_blank"
,
style
=
{
"padding"
:
"10px"
})
],
style
=
{
"margin"
:
"10px"
}),
html
.
Div
(
children
=
[
dt
.
DataTable
(
rows
=
[{}],
# initialise the rows
row_selectable
=
True
,
filterable
=
True
,
sortable
=
True
,
editable
=
False
,
selected_row_indices
=
[],
id
=
'datatable'
)
]),
],
style
=
{
"border-style"
:
"solid"
,
"margin"
:
"10px auto 10px"
}),
html
.
Div
([
dcc
.
Markdown
(
children
=
getting_help_text
)
]),
],
style
=
{
"display"
:
"inline-block"
,
"width"
:
"55%"
,
"vertical-align"
:
"top"
}),
html
.
Div
(
children
=
[
html
.
Div
(
children
=
[
dcc
.
Graph
(
id
=
'ts-graph'
,
figure
=
{
'layout'
:
{
'title'
:
'Time serie(s)'
}
}
)
]),
html
.
Div
(
children
=
[
dcc
.
Graph
(
id
=
'box-graph'
,
figure
=
{
'layout'
:
{
'title'
:
'Seasonal variation'
}
}
)
]),
],
style
=
{
"display"
:
"inline-block"
,
"width"
:
"40%"
})
])
])
@
app
.
callback
(
Output
(
'station-dropdown'
,
'options'
),
[
Input
(
'nbsample-slider'
,
'value'
),
Input
(
'hasOP_check'
,
'values'
)])
def
set_station_option
(
nbsample
,
hasOP
):
"""
Limit the station list to the ones with > X samples
"""
stations_tmp
=
[]
if
'hasOP'
in
hasOP
:
stations_tmp
+=
[
i
for
i
in
list_station
if
i
in
list_station_OP
]
else
:
stations_tmp
=
list_station
return
[{
'label'
:
s
,
'value'
:
s
}
for
s
in
stations_tmp
if
df
[
df
[
"station"
]
==
s
].
shape
[
0
]
>
nbsample
]
@
app
.
callback
(
Output
(
'specie-dropdown'
,
'options'
),
[
Input
(
'station-dropdown'
,
'value'
)])
def
set_specie_option
(
stations
):
species
=
[]
for
station
in
stations
:
species
=
species
+
[
i
for
i
in
df
[
df
[
"station"
]
==
station
].
dropna
(
axis
=
1
,
how
=
"all"
).
columns
if
i
not
in
species
]
return
[{
'label'
:
i
,
'value'
:
i
}
for
i
in
species
]
@
app
.
callback
(
Output
(
'datatable'
,
'rows'
),
[
Input
(
'station-dropdown'
,
'value'
),
Input
(
'specie-dropdown'
,
'value'
),
Input
(
'hasOP_check'
,
'values'
)])
def
update_datatable
(
stations
,
species
,
hasOP
):
'''
For user selections, return the relevant table
'''
stations_tmp
=
[]
if
'hasOP'
in
hasOP
:
stations_tmp
+=
[
i
for
i
in
stations
if
i
in
list_station_OP
]
else
:
stations_tmp
=
stations
dftmp
=
df
.
loc
[
df
[
"station"
].
isin
(
stations_tmp
),
species
]
return
dftmp
.
to_dict
(
"records"
)
@
app
.
callback
(
Output
(
'datatable'
,
'columns'
),
[
Input
(
'station-dropdown'
,
'value'
),
Input
(
'specie-dropdown'
,
'value'
)])
def
update_datatable_columns
(
stations
,
species
):
"""
Update columns
"""
default_col
=
[
"date"
,
"station"
,
"Particle size"
]
col
=
default_col
+
[
i
for
i
in
species
if
i
not
in
default_col
]
return
col
@
app
.
callback
(
Output
(
'download-data'
,
'href'
),
[
Input
(
'refresh-button'
,
'n_clicks'
)],
[
State
(
'datatable'
,
'rows'
)])
def
update_downloader
(
click
,
datatable
):
dftmp
=
pd
.
DataFrame
(
datatable
)
csvString
=
dftmp
.
to_csv
(
index
=
False
,
encoding
=
'utf-8'
)
csvString
=
"data:text/csv;charset=utf-8,"
+
urllib
.
parse
.
quote
(
csvString
)
return
csvString
@
app
.
callback
(
Output
(
'ts-graph'
,
'figure'
),
[
Input
(
'datatable'
,
'rows'
)])
def
update_ts_graph
(
datatable
):
traces
=
[]
returnError
=
{
'date'
:
traces
,
'layout'
:
{
'title'
:
'Time serie(s)'
}
}
if
not
LocalOption
.
tsplot
:
return
returnError
nbPlot
=
0
#len(stations) * len(set(species)-set(notNumeric))
if
nbPlot
>
tooManyPlot
:
print
(
"TS: too many things to plot... skip it"
,
nbPlot
)
return
returnError
dfdt
=
pd
.
DataFrame
(
datatable
)
stations
=
dfdt
.
station
.
unique
()
species
=
dfdt
.
columns
if
"date"
not
in
dfdt
.
columns
:
print
(
"TS: no date given"
)
return
returnError
if
"station"
not
in
dfdt
.
columns
:
print
(
"TS: no station given"
)
return
returnError
for
station
in
stations
:
dftmp
=
dfdt
[
dfdt
[
"station"
]
==
station
]
for
specie
in
species
:
if
specie
in
notNumeric
:
continue
dftmp
=
dftmp
.
sort_values
(
by
=
"date"
)
traces
.
append
(
go
.
Scatter
(
x
=
dftmp
.
loc
[:,
"date"
],
y
=
dftmp
.
loc
[:,
specie
],
mode
=
"lines+markers"
,
name
=
station
+
'-'
+
specie
))
return
{
'data'
:
traces
,
'layout'
:
go
.
Layout
(
yaxis
=
{
"title"
:
"ng or µg /m3"
},
showlegend
=
True
,
title
=
"Time serie(s)"
,
margin
=
go
.
Margin
(
l
=
50
,
r
=
0
,
b
=
50
,
t
=
50
,
pad
=
4
),
legend
=
dict
(
orientation
=
"h"
)
)
}
@
app
.
callback
(
Output
(
'box-graph'
,
'figure'
),
[
Input
(
'station-dropdown'
,
'value'
),
Input
(
'specie-dropdown'
,
'value'
),
Input
(
'datatable'
,
'rows'
)])
def
update_box_grah
(
stations
,
species
,
datatable
):
"""Seasonal boxplot"""
traces
=
[]
returnError
=
{
'date'
:
traces
,
'layout'
:
{
'title'
:
'Seasonal dispersion'
}
}
nbPlot
=
len
(
stations
)
*
len
(
set
(
species
)
-
set
(
notNumeric
))
if
nbPlot
>
tooManyPlot
:
print
(
"TS: too many things to plot... skip it"
,
nbPlot
)
return
if
len
(
species
)
==
0
:
print
(
"BOX: no data to plot, sp:"
,
species
)
traces
.
append
(
go
.
Box
(
y
=
[
0
]
))
return
{
'data'
:
traces
,
'layout'
:
go
.
Layout
(
showlegend
=
True
,
boxmode
=
'group'
)
}
if
len
(
stations
)
==
0
:
print
(
"BOX: no station"
)
return
dfdt
=
pd
.
DataFrame
(
datatable
)
dftmp
=
add_season
(
dfdt
)
dftmp
=
dftmp
.
sort_values
(
by
=
"season"
)
for
station
in
stations
:
idxStation
=
dftmp
[
"station"
]
==
station
for
specie
in
species
:
if
specie
in
notNumeric
:
continue
traces
.
append
(
go
.
Box
(
y
=
dftmp
.
loc
[
idxStation
,
specie
],
x
=
dftmp
.
loc
[
idxStation
,
"season"
],
name
=
station
+
"-"
+
specie
))
return
{
'data'
:
traces
,
'layout'
:
go
.
Layout
(
yaxis
=
{
"title"
:
"ng or µg /m3"
},
showlegend
=
True
,
boxmode
=
'group'
,
margin
=
go
.
Margin
(
l
=
50
,
r
=
0
,
b
=
50
,
t
=
50
,
pad
=
4
),
legend
=
dict
(
orientation
=
"h"
)
)
}
if
__name__
==
'__main__'
:
app
.
run_server
(
**
server_setting
)
app_setting_default.py
deleted
100644 → 0
View file @
9d2fdbd9
# server settigns. Change it for production
server_setting
=
{
"debug"
:
"True"
,
"host"
:
"127.0.0.1"
,
"port"
:
8050
}
# The path to your BDD
BDDPATH
=
"/home/webersa/Documents/apli_dash/"
# base url
BASEURL
=
"/"
# AUTH
ENABLE_AUTH
=
False
VALID_USERNAME_PASSWORD_PAIRS
=
[
[
"user"
,
"mdp"
]
]
pmall/templates/home.html
View file @
f2c1a18f
...
...
@@ -4,10 +4,10 @@
{% block title %}Home{% endblock %}
{% block content %}
The app is at
<a
href=
"/pmall_app/"
>
pmall_app
</a>
.
{% if user.is_authenticated %}
Hi {{ user.username }}!
The app is at
<a
href=
"/pmall_app/"
>
pmall_app
</a>
<p><a
href=
"{% url 'logout' %}"
>
logout
</a></p>
{% else %}
<p>
You are not logged in
</p>
...
...
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