Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from collections import OrderedDict
from datetime import datetime, timedelta
import rrdtool
import numpy as np
from .time import to_unix_timestamp
from .wind import mean_wind_vector_degrees
def dewpoint(tempC, relhum):
"""
Algorithm from Tom Whittaker tempC is the temperature in degrees Celsius,
relhum is the relative humidity as a percentage.
:param tempC: temperature in celsius
:param relhum: relative humidity as a percentage
"""
gasconst = 461.5
latheat = 2500800.0
dp = (1.0 / (1.0 / (273.15 + tempC)
- gasconst * np.log((0.0 + relhum) / 100) / (latheat - tempC * 2397.5)))
return np.minimum(dp - 273.15, tempC)
class RrdModel(object):
keys = ['air_temp', 'rh', 'dewpoint',
'wind_speed', 'winddir_north', 'winddir_east',
'pressure', 'precip', 'accum_precip', 'solar_flux',
'altimeter']
def __init__(self, filepath):
self._filepath = filepath
def initialize(self, start=None):
start = start or datetime.now() - timedelta(days=365)
secs = to_unix_timestamp(start)
rrdtool.create(self._filepath,
'--start={}'.format(secs),
'--step=5',
'DS:air_temp:GAUGE:10:-40:50',
'DS:rh:GAUGE:10:0:100',
'DS:dewpoint:GAUGE:10:0:100',
'DS:wind_speed:GAUGE:10:0:100',
'DS:winddir_north:GAUGE:10:-100:100',
'DS:winddir_east:GAUGE:10:-100:100',
'DS:pressure:GAUGE:10:0:1100',
'DS:precip:GAUGE:10:0:100',
'DS:accum_precip:GAUGE:10:0:100',
'DS:solar_flux:GAUGE:10:0:1000',
'DS:altimeter:GAUGE:10:0:100',
'RRA:AVERAGE:0.5:1:6307200',
'RRA:AVERAGE:0.5:12:525600',
'RRA:AVERAGE:0.5:60:105120',
'RRA:AVERAGE:0.5:360:17520')
def _print(self, record):
stamp = record.get_stamp()
values = ':'.join([str(record[k]) for k in self.keys])
values = '{:d}:{}'.format(to_unix_timestamp(stamp), values)
print values
def get_slice(self, start, end, names=None, average=5):
names = names or self.keys[:]
if isinstance(start, datetime):
start = to_unix_timestamp(start)
if isinstance(end, datetime):
end = to_unix_timestamp(end)
# normalize request times to averaging interval
start -= start % average
end -= end % average
range, columns, rawdata = rrdtool.fetch(self._filepath,
'AVERAGE',
'-r {:d}'.format(average),
'-s {:d}'.format(start),
'-e {:d}'.format(end))
src_data = np.array(rawdata)
dst_data = np.zeros((src_data.shape[0], len(names))) * float('nan')
# get only the columns we're interested in
for dst_idx, name in enumerate(names):
if name in columns:
dst_data[:,dst_idx] = src_data[:,columns.index(name)]
# we compute dewpoint since it wasn't always available
if name == 'dewpoint':
temp = src_data[:,self.keys.index('air_temp')].astype(np.float64)
rh = src_data[:,self.keys.index('rh')].astype(np.float64)
dst_data[:,dst_idx] = dewpoint(temp, rh)
# get the wind direction in degrees from the vector components
elif name == 'wind_dir':
east = src_data[:,self.keys.index('winddir_east')].astype(np.float64)
north = src_data[:,self.keys.index('winddir_north')].astype(np.float64)
dst_data[:,dst_idx] = mean_wind_vector_degrees(east, north)
times = np.array([np.arange(start, end + average, average)])
return np.concatenate((times.T, dst_data), axis=1)