Пример #1
0
	def build_components(self, is_closed):
		plot_dict = {}
		for table in self.tables:
			cp = table.__tablename__
			url =f"http://*****:*****@{timestamp}{%d %b %Y %l:%M:%S:%N %P}'),
					('rate', '@{rate}{%0.4f}'),
				],
				formatters={
					'@{timestamp}': 'datetime',
					'@{rate}': 'printf'
				}
			)
			plot.add_tools(hover_tool)
			callback = CustomJS(
				args={'line':line, 'source':source, 'cp':cp}, code="""
				var rates = source.data.rate;
				var first_val = rates[0];
				var last_val = rates[rates.length-1];
				var delta = Number.parseFloat(Math.abs(last_val-first_val)).toFixed(5);
				var increasing = first_val < last_val;
				if (increasing) {
					line.glyph.line_color = 'green';
				} else {
					line.glyph.line_color = 'red';
				}
						var card_class_dict = {
						true: {
						  "card_class":"card-text text-center font-weight-lighter text-success",
						  "new_color": "green",
						  "arrow": "▲"
						},
						false: {
						  "card_class":"card-text text-center font-weight-lighter text-danger",
						  "new_color": "red",
						  "arrow": "▼"
						  }
						}
						var formats = card_class_dict[increasing];

						$('#delta_'+cp)
						.removeClass()
						.addClass(
							  formats['card_class']
						)
						.html(
							formats["arrow"].concat(delta)
						);
						$('#current_'+cp).html(last_val);

				"""
			)
			source.js_on_change('change:data', callback)
			plot_dict[cp] = plot
		return components(plot_dict)
Пример #2
0
def create_bokeh_figure(
    corners,
    lon_limits,
    lat_limits,
    base_url="figs/",
    base_height=800,
    image_alpha=0.8,
    title="GOES GeoColor Imagery at ",
):
    img_args, x_range, y_range, scale = compute_image_locations_ranges(
        corners, lon_limits, lat_limits)
    map_fig = figure(
        plot_width=int(scale * base_height),
        plot_height=base_height,
        x_axis_type="mercator",
        y_axis_type="mercator",
        x_range=x_range,
        y_range=y_range,
        title=title,
        toolbar_location="right",
        sizing_mode="scale_width",
        name="map_fig",
    )
    hover = HoverTool(
        names=['sites'],
        tooltips=[("Site", "@name"),
                  ('Value', '@value of @capacity @units Max'),
                  ('Time', '@time')],
    )
    map_fig.add_tools(hover)
    map_fig.xaxis.axis_label = (
        "Data from https://registry.opendata.aws/noaa-goes/. Map tiles from Stamen Design. "  # NOQA
        "Plot generated with Bokeh by UA HAS Renewable Power Forecasting Group."
    )
    map_fig.xaxis.axis_label_text_font_size = "7pt"
    map_fig.xaxis.axis_line_alpha = 0

    slider = Slider(
        title="GOES Image",
        start=0,
        end=1,
        value=1,
        name="timeslider",
        sizing_mode="scale_width",
    )

    play_buttons = RadioButtonGroup(
        labels=["\u25B6", "\u25FC", "\u27F3"],
        active=1,
        name="play_buttons",
        sizing_mode="scale_width",
    )
    speed_source = ColumnDataSource(data=dict(speed=[config.PLAY_SPEED]),
                                    name='speed_source')
    faster_button = Button(label="\u2795",
                           sizing_mode='fixed',
                           width=30,
                           height=30,
                           name="faster_button")
    slower_button = Button(label="\u2796",
                           sizing_mode='fixed',
                           width=30,
                           height=30,
                           name="slower_button")
    play_button_row = row([play_buttons, faster_button, slower_button],
                          sizing_mode='scale_width',
                          name='all_play_buttons')
    fig_source = ColumnDataSource(data=dict(url=[]),
                                  name="figsource",
                                  id="figsource")
    adapter = CustomJS(
        args=dict(slider=slider,
                  fig_source=fig_source,
                  base_url=base_url,
                  title=map_fig.title,
                  max_images=config.MAX_IMAGES),
        code="""
    const result = {url: []}
    const urls = cb_data.response
    var pnglen = 0
    var len = urls.length
    var start = 0
    if (len > max_images) {
        start = len - max_images
    }
    for (i=start; i<len; i++) {
        var name = urls[i]['name'];
        if (name.endsWith('.png')) {
            result.url.push(base_url + name)
            pnglen += 1
        }
    }
    slider.end = Math.max(pnglen - 1, 1)
    var lasturl = result.url[pnglen - 1]
    cb_obj.tags = [lasturl]
    // first run
    if (fig_source.data['url'].length == 0) {
        fig_source.data['url'][0] = lasturl
        fig_source.tags = ['']
        fig_source.change.emit()
        slider.value = slider.end
    }
    slider.change.emit()
    return result
    """,
    )
    url_source = AjaxDataSource(data_url=base_url,
                                polling_interval=10000,
                                adapter=adapter)
    url_source.method = "GET"
    # url_source.if_modified = True

    pt_adapter = CustomJS(code="""
    const result = {x: [], y: [], name: [], capacity: [], value: [], time: [], units: []}
    const pts = cb_data.response
    for (i=0; i<pts.length; i++) {
        result.x.push(pts[i]['x'])
        result.y.push(pts[i]['y'])
        result.name.push(pts[i]['name'])
        result.capacity.push(pts[i]['capacity'])
        result.units.push(pts[i]['units'])
        result.time.push(pts[i]['last_time'])
        result.value.push(pts[i]['last_value'])
    }
    return result
""")

    pt_source = AjaxDataSource(data_url="metadata.json",
                               polling_interval=int(1e5),
                               adapter=pt_adapter)
    pt_source.method = "GET"

    slider_callback = CustomJS(
        args=dict(fig_source=fig_source, url_source=url_source),
        code="""
        if ('url' in url_source.data && cb_obj.value < url_source.data['url'].length){
            var inp_url = url_source.data['url'][cb_obj.value];
            fig_source.data['url'][0] = inp_url;
            fig_source.tags = [inp_url];
            fig_source.change.emit();
        }
        if (cb_obj.value == cb_obj.end) {
            cb_obj.tags = [1]
        } else {
            cb_obj.tags = [0]
        }
        """,
    )

    newest_callback = CustomJS(args=dict(fig_source=fig_source, slider=slider),
                               code="""
        if (slider.tags[0] == 1){
            if (slider.value != slider.end) {
                slider.value = slider.end
                slider.change.emit()
            }
            fig_source.data['url'][0] = cb_obj.tags[0]
            fig_source.tags = [cb_obj.tags[0]];
            fig_source.change.emit();
        }
        """)

    title_callback = CustomJS(
        args=dict(title=map_fig.title, base_title=title),
        code="""
        var url = cb_obj.data['url'][0]
        var date = new Date(url.split('/').pop().split('_').pop().split('.')[0])
        title.text = base_title + date
        title.change.emit()
        """,
    )
    faster_callback = CustomJS(args=dict(speed_source=speed_source,
                                         speed_incr=config.PLAY_SPEED_INCR),
                               code="""
    var old = speed_source.data['speed'][0]
    var newspeed = old - speed_incr
    if (newspeed > 0){
        speed_source.data = {"speed": [newspeed]}
        speed_source.change.emit()
    }
    """)
    slower_callback = CustomJS(args=dict(speed_source=speed_source,
                                         speed_incr=config.PLAY_SPEED_INCR),
                               code="""
    var old = speed_source.data['speed'][0]
    var newspeed = old + speed_incr
    speed_source.data = {"speed": [newspeed]}
    speed_source.change.emit()
    """)
    change_speed_callback = CustomJS(args=dict(slider=slider,
                                               play_buttons=play_buttons,
                                               pause=config.RESTART_PAUSE),
                                     code="""
    var timeoutSet = false;
    function fromstart(){
        timeoutSet = false
        if (play_buttons.active == 0){
            slider.value = 0
            slider.change.emit()
        }
    }
    function advance() {
        if (slider.value < slider.end) {
            slider.value += 1
            slider.change.emit()
        } else if (!timeoutSet){
            setTimeout(fromstart, pause)
            timeoutSet = true;
        }
    }

    if (play_buttons.active == 0){
        var id = play_buttons._id
        clearInterval(id)
        id = setInterval(advance, cb_obj.data['speed'][0])
        play_buttons._id = id
    }
    """)
    play_callback = CustomJS(
        args=dict(slider=slider,
                  speed_source=speed_source,
                  pause=config.RESTART_PAUSE),
        code="""
    function stop() {
        var id = cb_obj._id
        clearInterval(id)
        cb_obj.active = 1
    }

    var timeoutSet = false;
    function fromstart(){
        timeoutSet = false
        if (cb_obj.active == 0){
            slider.value = 0
            slider.change.emit()
        }
    }
    function advance() {
        if (slider.value < slider.end) {
            slider.value += 1
            slider.change.emit()
        } else if (!timeoutSet){
            setTimeout(fromstart, pause)
            timeoutSet = true;
        }
    }

    function start() {
        var id = setInterval(advance, speed_source.data['speed'][0])
        cb_obj._id = id
    }
    if (cb_obj.active == 0) {
        start()
    } else if (cb_obj.active == 2) {
        stop()
        slider.value = 0
        slider.change.emit()
    } else {
        stop()
    }
    """,
    )

    # ajaxdatasource to nginx list of files as json possibly on s3
    # write metadata for plants to file, serve w/ nginx
    # new goes image triggers lambda to process sns -> sqs -> lambda
    map_fig.add_tile(STAMEN_TONER)
    map_fig.image_url(url="url",
                      global_alpha=image_alpha,
                      source=fig_source,
                      **img_args)
    if config.SERVICE_AREA is not None:
        geo_source = GeoJSONDataSource(
            geojson=getattr(areas, config.SERVICE_AREA.upper()))
        map_fig.patches(xs='xs',
                        ys='ys',
                        source=geo_source,
                        fill_alpha=0,
                        line_alpha=0.9,
                        line_color=config.BLUE)
    map_fig.cross(x="x",
                  y="y",
                  size=12,
                  fill_alpha=0.9,
                  source=pt_source,
                  color=config.RED,
                  name='sites')
    fig_source.js_on_change("tags", title_callback)
    slider.js_on_change("value", slider_callback)
    url_source.js_on_change("tags", newest_callback)
    play_buttons.js_on_change("active", play_callback)
    faster_button.js_on_click(faster_callback)
    slower_button.js_on_click(slower_callback)
    speed_source.js_on_change("data", change_speed_callback)
    doc = curdoc()
    for thing in (map_fig, play_button_row, slider):
        doc.add_root(thing)
    doc.title = "GOES Image Viewer"
    return doc