matplotlib - write TeX on Qt form - qt

I'd like to add some TeX text to my Qt form, like label - just text, no graph, no lines, no borders, just TeX. I thought something like this: render TeX to bitmap and then place that bitmap on form, e.g. into QLabel. Or even better - use some backend, add it to form and use something tex_label.print_tex(<tex code>). Seems matplotplot has TeX parsers, but I can't figure out how to use them...
Thanks.

As a variant:
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
# Get window background color
bg = self.palette().window().color()
cl = (bg.redF(), bg.greenF(), bg.blueF())
# Create figure, using window bg color
self.fig = Figure(edgecolor=cl, facecolor=cl)
# Add FigureCanvasQTAgg widget to form
self.canvas = FigureCanvasQTAgg(self.fig)
self.tex_label_placeholder.layout().addWidget(self.canvas)
# Clear figure
self.fig.clear()
# Set figure title
self.fig.suptitle('$TeX$',
x=0.0, y=0.5,
horizontalalignment='left',
verticalalignment='center')
self.canvas.draw()

Related

How do I view an image in dotnet interactive?

I would like to view an image interactively in F# jupyter notebook similarly to how I can do this in python:
from PIL import Image
Image.open("image.png")
and that shows an image.
Is there a straightforward way to do this?
EmguCV, OpenCVSharp and ImageSharp all don't work together with the plotting libraries like Plotly.NET or XPlot to provide this functionality so I can't get something like matplotlib's pyplot.imshow.
In a notebook, you can display an image like this:
#!fsharp
// Load iamge
let data = File.ReadAllBytes("E:\\Downloads\\myImage.png");
// Convert so we can display it as HTML
let b64 = Convert.ToBase64String(data);
HTML($"<img src=\"data:image/png;base64,{b64}\"></img>") // last call without ; gets displayed
// Alt, this one has a semicolon:
// display(HTML($"<img src=\"data:image/png;base64,{b64}\"></img>"));

bokeh: How to export a grid to png with given size?

I prepared some bokeh plots to display as html.
To this end I prepared a gridplot containing the subplots, the legends and some headings. This all displays extremely nice in HTML and with sizing_mode='stretch_width' it's even kind of responsive.
webpage = gridplot([[header_col],[panel_grid_plot]], toolbar_location=None, sizing_mode='stretch_width')
show(webpage)
Now I also want to export this "webpage" to a PNG. To this end, I use
export_png(webpage, filename= png_filename, width=1800)
Unfortunately, the width parameter is ignored as the webpage is an object of type gridbox and not of type Plot. (This is checked in the bokeh/io/export.py in the method def get_layout_html())
The output is a png of a width of 800px which is kind of useless as the actual information is crushed (while the legends are nicely scaled):
Any ideas how to set the width of my PNG export to useful values?
Is there a way to convert a gridboxto a Plot?
Thanx!
You should've received a warning saying that the width argument will be ignored since you're passing into export_png something that's not a plot.
A way of achieving what you want:
webpage = gridplot(..., sizing_mode='stretch_width')
webpage.width = 1800
export_png(webpage)

Can I draw an annotation in bokeh with data from a ColumnDataSource?

I'd like to draw a vertical line on my Bokeh plot which gets moved around by javascript in the browser at runtime. (It's a timebar that marks the current time on a time series plot.)
For drawing a static vertical line, I'm using:
from bokeh.models import Span
timebar = Span(location=where_I_want_the_timebar, dimension=height)
my_figure.add_layout(timebar)
In order to enable the interactivity, I think I need to get the location from a ColumnDataSource. However, I can't figure out how to do that, because Span does not accept a source argument.
Alternatively, is there another way for me to move the timebar at runtime?
I found a workaround. In python:
from bokeh.models import Span
timebar = Span(name='timebar' location=where_I_want_the_timebar, dimension=height)
my_figure.add_layout(timebar)
Then in javascript in the browser:
let timebar = Bokeh.documents[0].get_model_by_name('timebar')
timebar.attributes.location = my_new_desired_location
timebar.change.emit()
If someone posts a way to use a ColumnDataSource I will accept that answer.

How to change the extent and position of an existing image in bokeh?

I am displaying 2d data as images of varying shapes in a bokeh server, and therefore need to dynamically update not only the image's data source, but also its dw, dh, x, and y properties. In the dummy example below, these changes are made in a callback function which is connected to a Button widget.
I've figured out that I need to access the glyph attribute of the image's GlyphRenderer object, and I can do so through its update() method (see code). But the changes don't take effect until I click the toolbar's Reset button. I've noticed that the changes also mysteriously take effect the second time I activate the callback() function. What is the proper way to make these changes?
import bokeh.plotting
import bokeh.models
import bokeh.layouts
import numpy as np
# set up the interface
fig1 = bokeh.plotting.figure(x_range=(0, 10), y_range=(0, 10))
im1 = fig1.image([], dw=5, dh=5)
button = bokeh.models.Button(label='scramble')
# add everything to the document
bokeh.plotting.curdoc().add_root(bokeh.layouts.column(button, fig1))
# define a callback and connect it
def callback():
# this always works:
im1.data_source.data = {'image': [np.random.random((100,100))]}
# these changes only take effect after pressing the "Reset"
# button, or after triggering this callback function twice:
im1.glyph.update(x=1, y=1, dw=9, dh=9)
button.on_click(callback)
I don't immediately see why you code isn't work. I can suggest explicitly using a ColumnDataSource and linking all of the Image glyph properties to columns in that source. Then you should be able to update the source.data in a single line and have all of the updates apply.
Here's some incomplete sample code to suggest how to do that:
from bokeh.models import Image, ColumnDataSource
from bokeh.plotting import figure
# the plotting code
plot = figure()
source = ColumnDataSource(data=dict(image=[], x=[], y=[], dw=[], dh=[]))
image = Image(data='image', x='x', y='y', dw='dw', dh=dh)
plot.add_glyph(source, glyph=image)
# the callback
def callback():
source.data = {'image': [np.random.random((100,100))], 'x':[1], 'y':[1], 'dw':[9], 'dh':[9]}
button.on_click(callback)

Can transparency be used with PostScript/EPS?

I am trying to save an R plot as an EPS file but I have a problem with the following component of the plot - the gray transparent polygon (transparent black = gray effect):
polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)
This line of code works fine when saving the plot as PDF but not as EPS. Looks like EPS does not support transparency? What other choice would I have?
Here is the code for the full plot:
postscript(file="Figure.eps", width=5.5, height=5.5, onefile=F, horizontal=F)
ts(t(data.frame(initial_timepoint, second_timepoint, third_timepoint, final_timepoint)))->obj
obj[,-c(3,7)]->obj1
plot(obj1, plot.type="single", lwd=0.6, xaxs="i",yaxs="i",xlab="",ylab="LV ejection fraction (%)",xaxt='n',yaxt='n',ylim=c(0,70),col="black")
axis(1, at=c(1,2,3,4), labels=c("1","2","3","4"),cex.axis=1)
axis(2, at=seq(0,70,10), labels=c("0%","10%","20%","30%","40%","50%","60%","70%"),cex.axis=1, las=1)
abline(v=c(2,3),lwd=0.6,lty=2)
stderr <- function(x) sqrt(var(x,na.rm=TRUE)/length(na.omit(x)))
avg<-c(mean(initial_timepoint,na.rm=T), mean(second_timepoint,na.rm=T), mean(third_timepoint,na.rm=T), mean(final_timepoint,na.rm=T))
err<-c(stderr(initial_timepoint), stderr(second_timepoint), stderr(third_timepoint), stderr(final_timepoint))
my.count <- c(1,2,3,4)
my.count.rev <- c(4,3,2,1)
y.polygon.6 <- c((avg+err*1.96)[my.count],(avg-err*1.96)[my.count.rev])
x.polygon <- c(my.count, my.count.rev)
polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)
lines(avg,col="black",lwd=0.8,lty=3)
lines((avg+err*1.96),lwd=0.8,lty=3)
lines((avg-err*1.96),lwd=0.8,lty=3)
dev.off()
Although the EPS format does not natively support semi-transparency, it is still possible to use cairo_ps(), that one automatically rasterizes semi-transparent areas, and the resolution at which it does this can be controlled with the argument fallback_resolution :
cairo_ps(file = "test.eps", onefile = FALSE, fallback_resolution = 600)
qplot(Sepal.Length, Petal.Length, data = iris, color = Species, size = Petal.Width, alpha = I(0.7))
dev.off()
All the non-semi-transparent areas then nicely stay as vector graphics.
Or even shorter you can also use :
ggsave("filename.eps", device=cairo_ps, fallback_resolution = 600)
Or use the functions to export to eps using the new export package, which just came out on CRAN :
install.packages("export")
library(export)
graph2eps("filename.eps", fallback_resolution = 600)
That package also supports a number of other export formats, including Powerpoint (graph2ppt), see ?graph2vector, which also retains semi-transparency...
The PostScript graphics model itself does not support general transparency of page elements at all. (Hence it is also not possible for EPS.) PostScript colors are all fully opaque.
An object drawn on top of another object would overwrite and cover all lower objects with its own color leaving no room for transparent effects. (If you see something that looks like transparency overlays in a PostScript viewer or printout, then that was only emulated transparency, by flattening the two (or more) respective objects into one single rasterized area creating the illusion of transparency.)
The PDF graphics model is based on PostScript's, but it extends it in various aspects, adding several new features. One of these is real transparency for complete objects.
After Adobe added transparency to PDF, it also created an extension [1] to the existing PostScript language that was able to include code in PS programs which would add transparency to PDFs created from this PostScript via Distiller. However, when rendering on screen or printing on paper this same original PostScript including this same code, that additional transparency would not appear, and the top (transparent in PDF) object would still overwrite the bottom ones when directly used in PostScript.
What other choice would I have?
Various:
Use PDF only. Don't use EPS.
If you must use EPS, use a two-step process:
Create the PDF first.
Then convert from the (transparency-enabled) PDF to EPS, 'flattening' the transparent elements into rasterized areas which emulate the desired transparency effect.
[1] The name of this extension is called pdfmark. With the help of the pdfmark operator one can also add other features to PostScript code which only materialize when distilling this PostScript to PDF: annotations, interactive form fields and buttons, metadata, hyperlinks, and more. All these elements would not have any effect in the direct PostScript rendering on screen or on paper prints.
Instead of making gray out of transparent black, I recommend using the gray.colors() function in R to generate the shades of gray you need. Then you get the look you want in your .eps file without a problem.
This is working fine for me to save .eps files
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.use('PS')
legend = plt.legend(loc="upper left", edgecolor="black")
legend.get_frame().set_alpha(None)
legend.get_frame().set_facecolor((0, 0, 0, 0))
plt.show()
plt.savefig('fig1.eps', format='eps')

Resources