mirror of
https://github.com/weewx/weewx.git
synced 2026-05-05 00:32:49 -04:00
Moved get_aggregate() to aggregate.py. Added heat/cool to aggregate
This commit is contained in:
23
TODO.md
23
TODO.md
@@ -1,10 +1,13 @@
|
||||
### Extensible types
|
||||
Need some way of initializing the daily summaries for wind.
|
||||
|
||||
### Logging
|
||||
Refactor wee_import to use the new logging facility.
|
||||
Refactor `wee_import` to use the new logging facility.
|
||||
|
||||
Update *Upgrading Guide*.
|
||||
|
||||
|
||||
### Issue 435 (Update WU uploader)
|
||||
### Issue [#435](https://github.com/weewx/weewx/issues/435) (Update WU uploader)
|
||||
Need to test some of the new types, in particular `windSpeed2`, `windGust10`,
|
||||
`windGustDir10`.
|
||||
|
||||
@@ -15,22 +18,6 @@ from `weeutil.weeutil`.
|
||||
|
||||
Document the suffixes `.exists` and `.has_data`.
|
||||
|
||||
Explore introducing extendable observation types. They would be registered
|
||||
with `Manager`.
|
||||
|
||||
The following drivers have been checked under Python 3:
|
||||
|
||||
```
|
||||
vantage.py
|
||||
wmr100.py
|
||||
```
|
||||
|
||||
In general, we should expect the user to run the command `python`, whatever that might
|
||||
point to. On some systems, it will be Python 2, others Python 3.
|
||||
|
||||
Nevertheless, we should probably include a section on how to run explicitly under
|
||||
Python 2 vs 3.
|
||||
|
||||
Update macos.htm for how to install using Python 3.
|
||||
|
||||
Update redhat.htm for how to install using Python 3.
|
||||
|
||||
@@ -39,8 +39,9 @@ simple_sql = "SELECT %(aggregate_type)s(%(obs_type)s) FROM %(table_name)s " \
|
||||
"WHERE dateTime > %(start)s AND dateTime <= %(stop)s AND %(obs_type)s IS NOT NULL"
|
||||
|
||||
|
||||
def get_aggregate(obs_type, timespan, aggregate_type, db_manager, **option_dict):
|
||||
"""Returns an aggregation of an observation type over a given time period.
|
||||
def get_aggregate_archive(obs_type, timespan, aggregate_type, db_manager, **option_dict):
|
||||
"""Returns an aggregation of an observation type over a given time period, using the
|
||||
main archive table.
|
||||
|
||||
obs_type: The type over which aggregation is to be done (e.g., 'barometer',
|
||||
'outTemp', 'rain', ...)
|
||||
@@ -195,7 +196,7 @@ def get_aggregate_daily(obs_type, timespan, aggregate_type, db_manager, **option
|
||||
# boundaries, and are not the first or last records in the database.
|
||||
if not (isStartOfDay(timespan.start) or timespan.start == db_manager.first_timestamp) \
|
||||
or not (isStartOfDay(timespan.stop) or timespan.stop == db_manager.last_timestamp):
|
||||
raise weewx.ViolatedPrecondition("Invalid timespan for using daily summaries: %s" % timespan)
|
||||
raise weewx.UnknownAggregation(aggregate_type)
|
||||
|
||||
if 'val' in option_dict:
|
||||
val = option_dict['val']
|
||||
@@ -392,3 +393,93 @@ def get_aggregate_wind(obs_type, timespan, aggregate_type, db_manager, **option_
|
||||
t, g = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type)
|
||||
# Form the ValueTuple and return it:
|
||||
return weewx.units.ValueTuple(value, t, g)
|
||||
|
||||
|
||||
def get_aggregate_heatcool(obs_type, timespan, aggregate_type, db_manager, **option_dict):
|
||||
"""Returns an aggregation of a wind type over a timespan by using the main archive table.
|
||||
|
||||
obs_type: The type over which aggregation is to be done (e.g., 'barometer',
|
||||
'outTemp', 'rain', ...)
|
||||
|
||||
timespan: An instance of weeutil.Timespan with the time period over which
|
||||
aggregation is to be done.
|
||||
|
||||
aggregate_type: The type of aggregation to be done.
|
||||
|
||||
db_manager: An instance of weewx.manager.Manager or subclass.
|
||||
|
||||
option_dict: Not used in this version.
|
||||
|
||||
returns: A ValueTuple containing the result. Note that the value contained in the ValueTuple
|
||||
will be a complex number for aggregation_types of 'avg', 'sum', 'first', 'last', 'min', and 'max'.
|
||||
"""
|
||||
# Default base temperature and unit type for heating and cooling degree days,
|
||||
# as a value tuple
|
||||
default_heatbase = (65.0, "degree_F", "group_temperature")
|
||||
default_coolbase = (65.0, "degree_F", "group_temperature")
|
||||
default_growbase = (50.0, "degree_F", "group_temperature")
|
||||
|
||||
# Check to see whether heating or cooling degree days are being asked for:
|
||||
if obs_type not in ['heatdeg', 'cooldeg', 'growdeg']:
|
||||
raise weewx.UnknownType(obs_type)
|
||||
|
||||
# Only summation (total) or average heating or cooling degree days is supported:
|
||||
if aggregate_type not in ['sum', 'avg']:
|
||||
raise weewx.UnknownAggregation(aggregate_type)
|
||||
|
||||
# Get the base for heating and cooling degree-days
|
||||
units_dict = option_dict.get('skin_dict', {}).get('Units', {})
|
||||
dd_dict = units_dict.get('DegreeDays', {})
|
||||
heatbase = dd_dict.get('heating_base', default_heatbase)
|
||||
coolbase = dd_dict.get('cooling_base', default_coolbase)
|
||||
growbase = dd_dict.get('growing_base', default_growbase)
|
||||
heatbase_t = (float(heatbase[0]), heatbase[1], "group_temperature")
|
||||
coolbase_t = (float(coolbase[0]), coolbase[1], "group_temperature")
|
||||
growbase_t = (float(growbase[0]), growbase[1], "group_temperature")
|
||||
|
||||
total = 0.0
|
||||
count = 0
|
||||
for daySpan in weeutil.weeutil.genDaySpans(timespan.start, timespan.stop):
|
||||
# Get the average temperature for the day as a value tuple:
|
||||
Tavg_t = get_aggregate_daily('outTemp', daySpan, 'avg', db_manager)
|
||||
# Make sure it's valid before including it in the aggregation:
|
||||
if Tavg_t is not None and Tavg_t[0] is not None:
|
||||
if obs_type == 'heatdeg':
|
||||
# Convert average temperature to the same units as heatbase:
|
||||
Tavg_target_t = weewx.units.convert(Tavg_t, heatbase_t[1])
|
||||
total += weewx.wxformulas.heating_degrees(Tavg_target_t[0], heatbase_t[0])
|
||||
elif obs_type == 'cooldeg':
|
||||
# Convert average temperature to the same units as coolbase:
|
||||
Tavg_target_t = weewx.units.convert(Tavg_t, coolbase_t[1])
|
||||
total += weewx.wxformulas.cooling_degrees(Tavg_target_t[0], coolbase_t[0])
|
||||
else:
|
||||
# Must be 'growdeg'. Convert average temperature to the same units as growbase:
|
||||
Tavg_target_t = weewx.units.convert(Tavg_t, growbase_t[1])
|
||||
total += weewx.wxformulas.cooling_degrees(Tavg_target_t[0], growbase_t[0])
|
||||
|
||||
count += 1
|
||||
|
||||
if aggregate_type == 'sum':
|
||||
result = total
|
||||
else:
|
||||
result = total / count if count else None
|
||||
|
||||
# Look up the unit type and group of the result:
|
||||
(t, g) = weewx.units.getStandardUnitType(db_manager.std_unit_system, obs_type, aggregate_type)
|
||||
# Return as a value tuple
|
||||
return weewx.units.ValueTuple(result, t, g)
|
||||
|
||||
|
||||
aggregate_fns = [get_aggregate_heatcool,
|
||||
get_aggregate_wind,
|
||||
get_aggregate_daily,
|
||||
get_aggregate_archive]
|
||||
|
||||
|
||||
def get_aggregate(obs_type, timespan, aggregate_type, db_manager, **option_dict):
|
||||
for agg_fn in aggregate_fns:
|
||||
try:
|
||||
return agg_fn(obs_type, timespan, aggregate_type, db_manager, **option_dict)
|
||||
except (weewx.UnknownAggregation, weewx.UnknownType):
|
||||
pass
|
||||
raise weewx.UnknownAggregation(aggregate_type)
|
||||
|
||||
@@ -19,6 +19,7 @@ import gen_fake_data
|
||||
import weeutil.logger
|
||||
import weewx
|
||||
import weewx.aggregate
|
||||
import weewx.manager
|
||||
from weeutil.weeutil import TimeSpan
|
||||
from weewx.units import ValueTuple
|
||||
|
||||
@@ -56,7 +57,7 @@ class TestAggregate(unittest.TestCase):
|
||||
def test_get_aggregate(self):
|
||||
# Use the same function to test calculating aggregations from the main archive file, as well
|
||||
# as from the daily summaries:
|
||||
self.get_aggregate_fn(weewx.aggregate.get_aggregate)
|
||||
self.get_aggregate_fn(weewx.aggregate.get_aggregate_archive)
|
||||
self.get_aggregate_fn(weewx.aggregate.get_aggregate_daily)
|
||||
|
||||
def get_aggregate_fn(self, aggregate_fn):
|
||||
@@ -88,7 +89,7 @@ class TestAggregate(unittest.TestCase):
|
||||
self.assertAlmostEqual(sum_vt[0], 7.68, 2)
|
||||
|
||||
# get_aggregate() has a few extra aggregate types:
|
||||
if aggregate_fn == weewx.aggregate.get_aggregate:
|
||||
if aggregate_fn == weewx.aggregate.get_aggregate_archive:
|
||||
first_vt = aggregate_fn('outTemp', TimeSpan(start_ts, stop_ts), 'first', db_manager)
|
||||
# Get the timestamp of the first record inside the month
|
||||
ts = start_ts + gen_fake_data.interval
|
||||
@@ -134,7 +135,7 @@ class TestAggregate(unittest.TestCase):
|
||||
avg_wind_vt = weewx.aggregate.get_aggregate_daily('wind', TimeSpan(start_ts, stop_ts), 'avg', db_manager)
|
||||
self.assertAlmostEqual(avg_wind_vt[0], 10.21, 2)
|
||||
# Double check this last one against the average calculated from the archive
|
||||
avg_wind_vt = weewx.aggregate.get_aggregate('windSpeed', TimeSpan(start_ts, stop_ts), 'avg', db_manager)
|
||||
avg_wind_vt = weewx.aggregate.get_aggregate_archive('windSpeed', TimeSpan(start_ts, stop_ts), 'avg', db_manager)
|
||||
self.assertAlmostEqual(avg_wind_vt[0], 10.21, 2)
|
||||
|
||||
vecavg_wind_vt = weewx.aggregate.get_aggregate_daily('wind', TimeSpan(start_ts, stop_ts), 'vecavg',
|
||||
@@ -145,6 +146,24 @@ class TestAggregate(unittest.TestCase):
|
||||
db_manager)
|
||||
self.assertAlmostEqual(vecdir_wind_vt[0], 88.74, 2)
|
||||
|
||||
def test_get_aggregate_heatcool(self):
|
||||
with weewx.manager.open_manager_with_config(self.config_dict, 'wx_binding') as db_manager:
|
||||
month_start_tt = (2010, 3, 1, 0, 0, 0, 0, 0, -1)
|
||||
month_stop_tt = (2010, 4, 1, 0, 0, 0, 0, 0, -1)
|
||||
start_ts = time.mktime(month_start_tt)
|
||||
stop_ts = time.mktime(month_stop_tt)
|
||||
|
||||
# First, with the default heating base:
|
||||
heatdeg = weewx.aggregate.get_aggregate_heatcool('heatdeg', TimeSpan(start_ts, stop_ts), 'sum', db_manager)
|
||||
self.assertAlmostEqual(heatdeg[0], 1123.99, 2)
|
||||
# Now with an explicit heating base:
|
||||
heatdeg = weewx.aggregate.get_aggregate_heatcool('heatdeg', TimeSpan(start_ts, stop_ts), 'sum',
|
||||
db_manager,
|
||||
skin_dict={'Units': {'DegreeDays': {
|
||||
'heating_base': (60.0, "degree_F", "group_temperature")
|
||||
}}})
|
||||
self.assertAlmostEqual(heatdeg[0], 968.99, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -9,7 +9,6 @@ from __future__ import print_function
|
||||
import weewx
|
||||
|
||||
scalar_types = []
|
||||
series_types = []
|
||||
|
||||
|
||||
def get_scalar(key, record, db_manager=None):
|
||||
|
||||
Reference in New Issue
Block a user