Completed
Push — bokeh-plots ( 9018eb )
by Alex
20:27
created

BasePlot.data_datetimes_values()   A

Complexity

Conditions 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 2
1
"""
2
Ways that a plot of a selected sensor can be displayed
3
"""
4
import datetime
5
6
from bokeh.plotting import figure
7
from flask import make_response, request, current_app
8
9
10
from .blueprint import main
11
from ..models import Gage, Sensor, Sample, Correlation, River, Section
12
13
14
class BasePlot(object):
15
    """
16
    Base class for all plots
17
    """
18
    def data(self):
19
        """
20
        Returns sensor data
21
22
        Defaults to data within last seven days
23
        """
24
        start, end = self.startend()
25
        if start and end:
26
            return Sample.query.filter(start < Sample.datetime,
27
                                       Sample.datetime < end,
28
                                       Sample.sensor_id == self.sid)\
29
                               .order_by(Sample.datetime)
30
        if start:
31
            return Sample.query.filter(start < Sample.datetime,
32
                                       Sample.sensor_id == self.sid)\
33
                               .order_by(Sample.datetime)
34
        seven_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7)
35
        return Sample.query.filter(Sample.datetime > seven_ago,
36
                                   Sample.sensor_id == self.sid)\
37
                           .order_by(Sample.datetime)
38
39
    @staticmethod
40
    def startend():
41
        """
42
        Return datetime objects if start and end arguments are in url.
43
        Otherwise return None.
44
        """
45
        start = request.args.get('start')
46
        end = request.args.get('end')
47
        if start:
48
            start = datetime.datetime.strptime(start, '%Y%m%d')
49
        if end:
50
            end = datetime.datetime.strptime(end, '%Y%m%d')
51
        return (start, end)
52
53
54
    def data_datetimes_values(self):
55
        """
56
        Returns the date as two lists, datetimes and values
57
        """
58
        datetimes, values = [], []
59
60
        data = self.data()
61
62
        for sample in data:
63
            datetimes.append(sample.datetime)
64
            values.append(sample.value)
65
66
        return datetimes, values
67
68
69
    def bokeh(self):
70
        """
71
        Returns a bokeh plot object
72
        """
73
        p = figure(x_axis_type='datetime', title=str(self.sensor))
74
75
        datetimes, values = self.data_datetimes_values()
76
77
        p.circle(datetimes, values, legend=self.sensor.nice_name())
78
79
        return p
80
    
81
82
class SensorPlot(BasePlot):
83
    """
84
    Plot class for Sensors
85
86
    Arguments:
87
        gid (int): Gage.id
88
        stype (string): sensor type for gage
89
90
    Currently supports matplotlib, but designed to be adaptable to support bokeh
91
    or others
92
93
    If ?start=YYYYMMDD(&end=YYYYMMDD) argument, then the plot will use those
94
    dates instead of the default 7 days.
95
    """
96
    def __init__(self, gid, stype):
97
        self.gid = gid
98
        self.stype = stype.lower()
99
        self.sensor = Sensor.query.filter_by(gage_id=self.gid).filter_by(stype=self.stype).first_or_404()
100
        self.sid = self.sensor.id
101
102
103
class CorrelationPlot(BasePlot):
104
    """
105
    Plot class for correlations
106
    """
107
    def __init__(self, section_id, sensor_id):
108
        self.section_id = section_id
109
        self.correlation = Correlation.query.filter_by(section_id=section_id)\
110
                                            .filter_by(sensor_id=sensor_id)\
111
                                            .first_or_404()
112
        self.sid = sensor_id
113
        self.sensor = self.correlation.sensor
114
        self.gid = self.sensor.gage.id
115
116
117