Source code for app.main.plot

"""
Ways that a plot of a selected sensor can be displayed
"""

from flask import make_response, request
import datetime
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

from .blueprint import main
from ..models import Sensor, Sample


[docs]class SensorPlot(object): """ Base plot object for Sensors Arguments: gid (int): Gage.id stype (string): sensor type for gage Currently supports matplotlib, but designed to be adaptable to support bokeh or others If ?start=YYYYMMDD(&end=YYYYMMDD) argument, then the plot will use those dates instead of the default 7 days. """ def __init__(self, gid, stype): self.gid = gid self.stype = stype.lower() self.sensor = Sensor.query.filter_by(gage_id=self.gid).filter_by(stype=self.stype).first_or_404() self.sid = self.sensor.id
[docs] def data(self): """ Returns sensor data Defaults to data within last seven days """ start = request.args.get('start', None) end = request.args.get('end', None) if start: start = datetime.datetime.strptime(start, '%Y%m%d') if end: end = datetime.datetime.strptime(end, '%Y%m%d') if start and end: return Sample.query.filter(start < Sample.datetime, Sample.datetime < end, Sample.sensor_id == self.sid)\ .order_by(Sample.datetime) if start: return Sample.query.filter(start < Sample.datetime, Sample.sensor_id == self.sid)\ .order_by(Sample.datetime) seven_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7) return Sample.query.filter(Sample.datetime > seven_ago, Sample.sensor_id == self.sid)\ .order_by(Sample.datetime)
def _setaxislimits(self, axis, ymin, ymax): """ Set limits for y axis. If not set on sensor, then use a buffer of 10% """ if ymin == ymax: ybuff = 0.1*ymin else: ybuff = 0.1*(ymax-ymin) if self.sensor.minimum: axis.set_ylim(ymin=self.sensor.minimum) else: axis.set_ylim(ymin=ymin-ybuff) if self.sensor.maximum: axis.set_ylim(ymax=self.sensor.maximum) else: axis.set_ylim(ymax=ymax+ybuff)
[docs] def matplot(self): """ Returns a matplotlib figure for building into a plot """ import matplotlib matplotlib.use('Agg') from matplotlib.figure import Figure import seaborn as sns sns.set() data = self.data() fig = Figure() ax = fig.add_subplot(1, 1, 1) x = [] y = [] for sample in data: x.append(sample.datetime) y.append(sample.value) ax.plot(x, y, '-') self._setaxislimits(ax, min(y), max(y)) return fig
[docs] def png(self): """ Returns a StringIO PNG plot for the sensor """ from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas fig = self.matplot() canvas = FigureCanvas(fig) png_output = StringIO() canvas.print_png(png_output) return png_output.getvalue()
[docs] def jpg(self): """ Returns a StringIO JPG plot for the sensor """ from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas fig = self.matplot() canvas = FigureCanvas(fig) jpg_output = StringIO() canvas.print_jpg(jpg_output) return jpg_output.getvalue()
@main.route('/gage/<int:gid>/<stype>.png')
[docs]def gagesensorplot(gid, stype): """**/gage/<id>/<sensor type>.png** Draw a PNG plot for the requested gage's sensor """ response = make_response(SensorPlot(gid, stype).png()) response.headers['Content-Type'] = 'image/png' return response
@main.route('/gage/<int:gid>/<stype>.jpg') @main.route('/gage/<int:gid>/<stype>.jpeg')
[docs]def gagesensorplotjpg(gid, stype): """**/gage/<id>/<sensor type>.jpg** **/gage/<id>/<sensor type>.jpeg** Draw a JPEG plot for the requested gage's sensor """ response = make_response(SensorPlot(gid, stype).jpg()) response.headers['Content-Type'] = 'image/jpeg' return response