Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
energy
bmon
Commits
246ee412
Commit
246ee412
authored
Apr 05, 2021
by
AlaskaMapScience
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add rolling averaging option to timeseries report
parent
dfab81b9
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
36 additions
and
8 deletions
+36
-8
bmsapp/data_util.py
bmsapp/data_util.py
+16
-2
bmsapp/reports/timeseries.py
bmsapp/reports/timeseries.py
+9
-2
bmsapp/static/bmsapp/scripts/reports.coffee
bmsapp/static/bmsapp/scripts/reports.coffee
+2
-2
bmsapp/static/bmsapp/scripts/reports.js
bmsapp/static/bmsapp/scripts/reports.js
+2
-2
bmsapp/templates/bmsapp/reports.html
bmsapp/templates/bmsapp/reports.html
+7
-0
No files found.
bmsapp/data_util.py
View file @
246ee412
...
@@ -6,6 +6,7 @@ from datetime import datetime
...
@@ -6,6 +6,7 @@ from datetime import datetime
import
pytz
,
calendar
,
time
,
math
import
pytz
,
calendar
,
time
,
math
from
dateutil
import
parser
from
dateutil
import
parser
import
numpy
as
np
import
numpy
as
np
import
pandas
as
pd
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -94,7 +95,7 @@ def histogram_from_series(pandas_series):
...
@@ -94,7 +95,7 @@ def histogram_from_series(pandas_series):
# to 4 significant figures
# to 4 significant figures
return
list
(
zip
(
avg_bins
,
cts
))
return
list
(
zip
(
avg_bins
,
cts
))
def
resample_timeseries
(
pandas_dataframe
,
averaging_hours
,
drop_na
=
True
):
def
resample_timeseries
(
pandas_dataframe
,
averaging_hours
,
use_rolling_averaging
=
False
,
drop_na
=
True
):
'''
'''
Returns a new pandas dataframe that is resampled at the specified "averaging_hours"
Returns a new pandas dataframe that is resampled at the specified "averaging_hours"
interval. If the 'averaging_hours' parameter is fractional, the averaging time
interval. If the 'averaging_hours' parameter is fractional, the averaging time
...
@@ -117,7 +118,20 @@ def resample_timeseries(pandas_dataframe, averaging_hours, drop_na=True):
...
@@ -117,7 +118,20 @@ def resample_timeseries(pandas_dataframe, averaging_hours, drop_na=True):
}
}
params
=
interval_lookup
.
get
(
averaging_hours
,
{
'rule'
:
str
(
int
(
averaging_hours
*
60
))
+
'min'
,
'loffset'
:
str
(
int
(
averaging_hours
*
30
))
+
'min'
})
params
=
interval_lookup
.
get
(
averaging_hours
,
{
'rule'
:
str
(
int
(
averaging_hours
*
60
))
+
'min'
,
'loffset'
:
str
(
int
(
averaging_hours
*
30
))
+
'min'
})
if
not
use_rolling_averaging
:
new_df
=
pandas_dataframe
.
resample
(
rule
=
params
[
'rule'
],
loffset
=
params
[
'loffset'
],
label
=
'left'
).
mean
()
new_df
=
pandas_dataframe
.
resample
(
rule
=
params
[
'rule'
],
loffset
=
params
[
'loffset'
],
label
=
'left'
).
mean
()
else
:
# resample to consistent interval
original_interval
=
pandas_dataframe
.
index
.
to_series
().
diff
().
quantile
(.
05
)
new_df
=
pandas_dataframe
.
resample
(
rule
=
original_interval
).
median
()
# apply the rolling averaging
new_df
=
new_df
.
rolling
(
int
(
pd
.
Timedelta
(
hours
=
averaging_hours
)
/
original_interval
),
center
=
True
,
min_periods
=
1
).
mean
()
# downsample the result if there are more than 1000 values
if
len
(
new_df
)
>
1000
:
new_df
=
new_df
.
resample
(
rule
=
(
pandas_dataframe
.
index
[
-
1
]
-
pandas_dataframe
.
index
[
0
])
/
1000
).
mean
()
if
drop_na
:
if
drop_na
:
new_df
=
new_df
.
dropna
()
new_df
=
new_df
.
dropna
()
...
...
bmsapp/reports/timeseries.py
View file @
246ee412
...
@@ -10,7 +10,7 @@ class TimeSeries(basechart.BaseChart):
...
@@ -10,7 +10,7 @@ class TimeSeries(basechart.BaseChart):
"""
"""
# see BaseChart for definition of these constants
# see BaseChart for definition of these constants
CTRLS
=
'refresh, ctrl_sensor, ctrl_avg, ctrl_occupied, time_period_group, get_embed_link'
CTRLS
=
'refresh, ctrl_sensor, ctrl_avg,
ctrl_use_rolling_averaging,
ctrl_occupied, time_period_group, get_embed_link'
MULTI_SENSOR
=
1
MULTI_SENSOR
=
1
def
result
(
self
):
def
result
(
self
):
...
@@ -28,8 +28,15 @@ class TimeSeries(basechart.BaseChart):
...
@@ -28,8 +28,15 @@ class TimeSeries(basechart.BaseChart):
# get the requested averaging interval in hours
# get the requested averaging interval in hours
if
'averaging_time'
in
self
.
request_params
:
if
'averaging_time'
in
self
.
request_params
:
averaging_hours
=
float
(
self
.
request_params
[
'averaging_time'
])
averaging_hours
=
float
(
self
.
request_params
[
'averaging_time'
])
if
'use_rolling_averaging'
in
self
.
request_params
:
use_rolling_averaging
=
True
else
:
use_rolling_averaging
=
False
else
:
else
:
averaging_hours
=
0
averaging_hours
=
0
use_rolling_averaging
=
False
# determine the start time for selecting records and loop through the selected
# determine the start time for selecting records and loop through the selected
# records to get the needed dataset
# records to get the needed dataset
...
@@ -51,7 +58,7 @@ class TimeSeries(basechart.BaseChart):
...
@@ -51,7 +58,7 @@ class TimeSeries(basechart.BaseChart):
if
not
df
.
empty
:
if
not
df
.
empty
:
# perform average (if requested)
# perform average (if requested)
if
averaging_hours
:
if
averaging_hours
:
df
=
bmsapp
.
data_util
.
resample_timeseries
(
df
,
averaging_hours
)
df
=
bmsapp
.
data_util
.
resample_timeseries
(
df
,
averaging_hours
,
use_rolling_averaging
)
# create lists for plotly
# create lists for plotly
if
np
.
absolute
(
df
.
val
.
values
).
max
()
<
10000
:
if
np
.
absolute
(
df
.
val
.
values
).
max
()
<
10000
:
...
...
bmsapp/static/bmsapp/scripts/reports.coffee
View file @
246ee412
...
@@ -108,7 +108,7 @@ process_chart_change = ->
...
@@ -108,7 +108,7 @@ process_chart_change = ->
# start by hiding all input controls
# start by hiding all input controls
set_visibility
([
'refresh'
,
'ctrl_sensor'
,
'ctrl_avg'
,
'ctrl_avg_export'
,
set_visibility
([
'refresh'
,
'ctrl_sensor'
,
'ctrl_avg'
,
'ctrl_avg_export'
,
'ctrl_normalize'
,
'ctrl_occupied'
,
'xy_controls'
,
'time_period_group'
,
'ctrl_normalize'
,
'ctrl_occupied'
,
'xy_controls'
,
'time_period_group'
,
'download_many'
,
'get_embed_link'
],
false
)
'download_many'
,
'get_embed_link'
,
'ctrl_use_rolling_averaging'
],
false
)
# get the chart option control that is selected. Then use the data
# get the chart option control that is selected. Then use the data
# attributes of that option element to configure the user interface.
# attributes of that option element to configure the user interface.
...
@@ -320,7 +320,7 @@ $ ->
...
@@ -320,7 +320,7 @@ $ ->
$
(
"#select_chart"
).
change
process_chart_change
$
(
"#select_chart"
).
change
process_chart_change
# Set up change handlers for inputs.
# Set up change handlers for inputs.
ctrls
=
[
'averaging_time'
,
'averaging_time_export'
,
'normalize'
,
'show_occupied'
,
ctrls
=
[
'averaging_time'
,
'averaging_time_export'
,
'normalize'
,
'use_rolling_averaging'
,
'show_occupied'
,
'select_sensor'
,
'select_sensor_x'
,
'select_sensor_y'
,
'averaging_time_xy'
,
'div_date'
,
'select_sensor'
,
'select_sensor_x'
,
'select_sensor_y'
,
'averaging_time_xy'
,
'div_date'
,
'start_date'
,
'end_date'
]
'start_date'
,
'end_date'
]
$
(
"#
#{
ctrl
}
"
).
change
inputs_changed
for
ctrl
in
ctrls
$
(
"#
#{
ctrl
}
"
).
change
inputs_changed
for
ctrl
in
ctrls
...
...
bmsapp/static/bmsapp/scripts/reports.js
View file @
246ee412
...
@@ -101,7 +101,7 @@
...
@@ -101,7 +101,7 @@
process_chart_change
=
function
()
{
process_chart_change
=
function
()
{
var
multi
,
selected_chart_option
,
sensor_val
,
single
,
vis_ctrls
;
var
multi
,
selected_chart_option
,
sensor_val
,
single
,
vis_ctrls
;
set_visibility
([
'
refresh
'
,
'
ctrl_sensor
'
,
'
ctrl_avg
'
,
'
ctrl_avg_export
'
,
'
ctrl_normalize
'
,
'
ctrl_occupied
'
,
'
xy_controls
'
,
'
time_period_group
'
,
'
download_many
'
,
'
get_embed_link
'
],
false
);
set_visibility
([
'
refresh
'
,
'
ctrl_sensor
'
,
'
ctrl_avg
'
,
'
ctrl_avg_export
'
,
'
ctrl_normalize
'
,
'
ctrl_use_rolling_averaging
'
,
'
ctrl_occupied
'
,
'
xy_controls
'
,
'
time_period_group
'
,
'
download_many
'
,
'
get_embed_link
'
],
false
);
selected_chart_option
=
$
(
"
#select_chart
"
).
find
(
"
option:selected
"
);
selected_chart_option
=
$
(
"
#select_chart
"
).
find
(
"
option:selected
"
);
vis_ctrls
=
selected_chart_option
.
data
(
"
ctrls
"
).
split
(
"
,
"
);
vis_ctrls
=
selected_chart_option
.
data
(
"
ctrls
"
).
split
(
"
,
"
);
set_visibility
(
vis_ctrls
,
true
);
set_visibility
(
vis_ctrls
,
true
);
...
@@ -299,7 +299,7 @@
...
@@ -299,7 +299,7 @@
$
(
"
#select_group
"
).
change
(
update_bldg_list
);
$
(
"
#select_group
"
).
change
(
update_bldg_list
);
$
(
"
#select_bldg
"
).
change
(
update_chart_sensor_lists
);
$
(
"
#select_bldg
"
).
change
(
update_chart_sensor_lists
);
$
(
"
#select_chart
"
).
change
(
process_chart_change
);
$
(
"
#select_chart
"
).
change
(
process_chart_change
);
ctrls
=
[
'
averaging_time
'
,
'
averaging_time_export
'
,
'
normalize
'
,
'
show_occupied
'
,
'
select_sensor
'
,
'
select_sensor_x
'
,
'
select_sensor_y
'
,
'
averaging_time_xy
'
,
'
div_date
'
,
'
start_date
'
,
'
end_date
'
];
ctrls
=
[
'
averaging_time
'
,
'
averaging_time_export
'
,
'
normalize
'
,
'
use_rolling_averaging
'
,
'
show_occupied
'
,
'
select_sensor
'
,
'
select_sensor_x
'
,
'
select_sensor_y
'
,
'
averaging_time_xy
'
,
'
div_date
'
,
'
start_date
'
,
'
end_date
'
];
for
(
i
=
0
,
len
=
ctrls
.
length
;
i
<
len
;
i
++
)
{
for
(
i
=
0
,
len
=
ctrls
.
length
;
i
<
len
;
i
++
)
{
ctrl
=
ctrls
[
i
];
ctrl
=
ctrls
[
i
];
$
(
"
#
"
+
ctrl
).
change
(
inputs_changed
);
$
(
"
#
"
+
ctrl
).
change
(
inputs_changed
);
...
...
bmsapp/templates/bmsapp/reports.html
View file @
246ee412
...
@@ -91,6 +91,13 @@
...
@@ -91,6 +91,13 @@
Shade Occupied Periods
Shade Occupied Periods
</label>
</label>
</div>
</div>
<div
id=
"ctrl_use_rolling_averaging"
class=
"form-check mb-4 ml-3"
>
<input
class=
"form-check-input"
type=
"checkbox"
value=
""
id=
"use_rolling_averaging"
name=
"use_rolling_averaging"
>
<label
class=
"form-check-label"
for=
"use_rolling_averaging"
>
Use Rolling Averaging
</label>
</div>
<div
id=
"ctrl_normalize"
class=
"form-check mb-4 ml-3"
>
<div
id=
"ctrl_normalize"
class=
"form-check mb-4 ml-3"
>
<input
class=
"form-check-input"
type=
"checkbox"
value=
""
id=
"normalize"
<input
class=
"form-check-input"
type=
"checkbox"
value=
""
id=
"normalize"
name=
"normalize"
>
name=
"normalize"
>
...
...
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