Adding multiple bokeh html files to a django template - python

I created some plots with bokeh and exported them as html files. I now try to add these plots in a django template. The first plot works just fine, but if I want to add a second one it is not displayed.
Here i have the python file that creates the bokeh html:
from bokeh.plotting import figure, output_file, show
output_file("test2.html",title="test2")
p = figure(plot_width=400, plot_height=400)
p.circle([1, 5, 7, 2, 5], [6, 7, 2, 5, 5], size=20, color="navy", alpha=0.5)
show(p)
This is the second plot, the first one is saved as test.html, the title is test and some of the point coordinates are different.
And here is my django template:
{% extends "MainPage/PageBase.html" %}
{% block content %}
<div class="container">
<div class="card">
<div class="card-header">
<font size="3">plot1</font>
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p><div class="basic">
{% include "GPanalysis\WorkingData\test.html" %}
</div></p>
</blockquote>
</div>
</div>
<div class="card">
<div class="card-header">
<font size="3">plot2</font>
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p><div class="basic">
{% include "GPanalysis\WorkingData\test2.html" %}
</div></p>
</blockquote>
</div>
</div>
</div>
{% endblock %}
In the first box appears a graph but the second one is empty.
I switched the position of two plots, but only the one that comes first in the html script will be displayed. If I try to call the same graph twice, it will be plotted twice but the second one is directly below the first one and not at the location it should be according to the html script.
I am not sure if this is an error i have somewhere or if what I am trying is simply not possible. I am aware, that there are other possibilities to get multiple bokeh plots in one template, but this one would be the easyest for my situation as i have to generate the html files anyway.
Thanks for any helpful answer.

Don't do this. Bokeh file output is not designed or intended to be embedded this way, and there is no expectation that it should work well or at all:
File output generates full HTML files with their own <head>, by doing this you are 100% guaranteed to generate malformed HTML
Bokeh objects from different files will probably end up stomping on each other, because file output is not intended to be used this way.
There are APIs sepcifically purposed for Embedding Plots and Apps and those should be used.

Related

Does wtforms Integer Field force a new line when displayed on webpage?

I am using wtforms as part of a Python + Flask project. There are some cases where I want multiple fields of a form to appear on the same line on the webpage. With SelectField, this works as expected. However, when I use IntegerField, it seems to automatically create a new line after the field is displayed, and I get have more than one on a line.
The Form:
class PremiumMandatory(FlaskForm):
match_dol = IntegerField('Dollar')
match_per = IntegerField('Percent')
The .html
{{form.match_dol.label}}
${{form.match_dol(size=3)}}
&nbsp
{{form.match_per(size=3)}}%
{% for error in form.match_per.errors %}
Using the above, the two fields also appear on different lines on the webpage. Ho do I keep then on the same line?
This is an entirely HTML/CSS problem. There are many ways to put multiple fields of a form on the same line, for example, you could use Bootstrap's grid system, which is very easy to use.
Another simple way is:
<form>
<div style="display: table;">
<div style="display: table-row;">
<div style="display: table-cell;">
{{ form.match_dol.label }}
{{ form.match_dol(size=3) }}
</div>
<div style="display: table-cell;">
{{ form.match_per.label }}
{{ form.match_per(size=3) }}
</div>
</div>
<div style="display: table-row;">
...
</div>
</div>
</form>

Perform arithmetic operation in Jinja2

I want to find the difference between two different values. But, I am getting a Jinja2 error. I am not sure about how to find the difference in this template.
I tried using - operator but this did not work. So, I used sub to find the difference between actual and predicted score.
{% for e in question.essays %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{loop.index}}</h3>
</div>
<div class="panel-body">
<div class="actual-score">Actual score: {% if e.actual_score %} {{e.actual_score|round(1)}}/5{% endif %}</div>
<div class="predicted-score">Predicted score: {% if e.predicted_score %}{{e.predicted_score|round(1)}}/5{% endif %}</div>
<p class="essay-text">Text: {{e.text}}</p>
<div class="diff">Difference: {{ e.actual_score|sub(e.predicted_score)}} </div>
</div>
I am getting this error:
TemplateAssertionError: no filter named 'sub'
According to the Jinja2 documentation, using - should work pretty fine. Also from my end, it is working just fine. Mind posting the error message you get when using the operator. I also cannot find the sub tag in the documentation for Jinja2.
Therefore, as Amazing Things Around You has said, I think this should work:
{{ e.actual_score - e.predicted_score }}
Just a side note, the only other template tag I have found that does arithmetic operations close to that is Django's add tag, which also does not do subtraction.

Get individual graphs from Plotly using Flask and Python

I am trying to show graphs made in plotly on a webpage served by flask.
The way it is set up now, they both display on the same page, one on top of the other. I want to show them individually on different pages.
The solution I found for plotly displays all of the graphs made, and I'm not sure how to get individual graphs
My flask/python
graphs = [
dict(
data=[thetaGraph, deltaGraph, alphaGraph, betaGraph,gammaGraph ],
layout=dict(
title='Brain Data'
)
),
dict(
data=[xGraph,yGraph,zGraph],
layout=dict(
title='Accelerometer Data'
)
),
]
ids = ['graph-{}'.format(i) for i, _ in enumerate(graphs)]
graphJSON = json.dumps(graphs, cls=plotly.utils.PlotlyJSONEncoder)
return render_template('index.html', title='Home',ids=ids, graphJSON=graphJSON)
And then the webpage
<div class="container">
<div class="row">
<!-- LEFT SIDE -->
<div class="col-6">
{% for id in ids %}
<div id="{{id}}"></div>
{% endfor %}
</div>
</div>
</div>
<footer>
<script type="text/javascript">
var graphs = {{graphJSON | safe}};
var ids = {{ids | safe}};
for(var i in graphs) {
Plotly.plot(ids[i], // the ID of the div, created above
graphs[i].data,
graphs[i].layout || {});
}
</script>
</footer>
Im unsure how to get just the first graph in that html, and then the second graph elsewhere on the page. Ive tried using {% for id in range(0,1) %} just to get the first element, or just putting <div id="{{ids[0]}}"></div>
but I get 'ids' in undefined
When printing out ids i get ['graph-0', 'graph-1'] which means that this is a list and I should be able to index it, but apparently that is not a thing with flask. I'm sure there is some strange way that flask needs it similarly to it's ways of reading from 2D arrays
I was able to figure out a way to complete my task, but it does not involve indexing arrays. Since the javascript creates usable id's I am able to show individual graphs by simple referencing them
Replacing
<div class="col-6">
{% for id in ids %}
<div id="{{id}}"></div>
{% endfor %}
</div>
With
<div class="col-6">
<div id="graph-0"></div>
</div>
Gave me the outcome I was looking for

Bokeh server : Customize row ratio

I am using Bokeh to vizualize scientific data for a while and I fail to customize my layout as I wish.
from bokeh.plotting import figure
from bokeh.io import show
from bokeh.layouts import row
from bokeh.models.widgets import Button
tools_to_show = 'hover, box_zoom, save, reset, pan'
p = figure(tools=tools_to_show, output_backend = "webgl")
p.line([1, 2, 3, 4], [9, 5, 7, 6])
b_valid = Button(label="valid")
my_plot = row(p, b_valid, sizing_mode="stretch_both")
show(my_plot)
I have a plot area and a controls area. The controls area should be smaller, maybe 1/3 of available width to let the plot with a bigger area (2/3 of available width).
I'm using sizing_mode = "stretch_both" to be sure to use all available space in screen.
I need to keep using the bokeh server (bokeh serve myapp.py) to get python callback working, so the embbeded solution suggested here is not working for me.
Maybe there is a way with serving directory with bokeh command because there is a template mechanism, but I can't figure how to get seperate div for plot and controls.
Have you any (simple) idea ?
Edit : it seems that it's not a feature currently available on bokeh. A promising solution is to be able to place components embedded in template using bokeh server : amilestone is scheduled
I would say that we are backing away from the built-in layout system for more than very simple things. PR #7708 was just merged an will be in the upcoming 0.13.0 release. When 0.13.0 is available, you can embed individual document roots separately in temlates, e.g. if you define five plots in a Bokeh server app:
curdoc().add_root(p0)
curdoc().add_root(p1)
curdoc().add_root(p2)
curdoc().add_root(p3)
curdoc().add_root(p4)
They can all be placed in responsive Bootstrap layouts:
<div class="row">
<div class="col-sm-8">
{{ embed(doc.roots[0]) }}
<br>
</div>
<div class="col-sm-4">
{{ embed(doc.roots[1]) }}
<br>
</div>
</div>
<div class="row">
<div class="col-sm-4">
{{ embed(doc.roots[2]) }}
<br>
</div>
<div class="col-sm-4">
{{ embed(doc.roots[3]) }}
<br>
</div>
<div class="col-sm-4">
{{ embed(doc.roots[4]) }}
<br>
</div>
</div>

Can We use page breaks in for loops?

I wanted to print barcodes using for loop in python. This is my code:
`{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<hr>
{% set a = doc.end %}
{% set count = 0 %}
<div class="row">
{%- for i in range(doc.start,doc.end) -%}
<div class="col-md-4 text-center">
<p style="font-family: Code39AzaleaFont;font-weight: normal;font-style: normal;font-size:30px;">
00000000000000{{ i }}</p>
{% set count = count + 1 %}
{{count}}
<br/>
</div>
{%- endfor -%}
</div>
<hr>
<br>
<p class="strong">
<br>
<br>
<br>
{{ _("Authorized Signatory") }}
</p>
</div>`
The problem is,I wanted to restrict the number of barcodes printed on one sheet of paper to 24.Is there any way to do that?
You can add a page break after every 24th barcode using:
{% if count % 24 %}<div style="page-break-before: always;"></div>{% endif %}
HTML doesn't have a really good concept of "paper sheet size". A HTML page has an infinite height and browser's are notoriously bad a printing HTML in a readable way (with the notable exception of Opera).
With CSS 3, three page break properties were defined.
They might be supported by your browser. If they are, then wrap 24 bar codes in a <div> and give that <div> a class which tells the browser to break the page afterwards.
If the browser emits an empty page at the end, then you need two classes: One for the first <div> without a page break and one for every successive <div> and a page-break-before: always;
If that doesn't work well, you should look at PDF. PDF allows you place elements exactly on pages with a known, fixed size.

Categories