Failing to place an image with pylatex - python

I am using pylatex to create a pdf with an image in it at the coordinates that I specify. I have used the code below but no matter what coordinates I enter, the image is always in the upper left corner. Please help me.
from pylatex import (Document, TikZ,
TikZNode, TikZCoordinate,
TikZOptions, StandAloneGraphic, NoEscape)
geometry_options = {"margin": "0cm"}
doc = Document(documentclass='standalone',document_options=('tikz'), geometry_options=geometry_options)
doc.append(NoEscape(r'\noindent'))
with doc.create(TikZ()) as pic:
# img = TikZNode(text='\includegraphics[width=0.8\\textwidth]{example-image-a}',
# at = TikZCoordinate(3,4),
# options=TikZOptions('inner sep=0pt,anchor=south west'))
img = TikZNode(text=StandAloneGraphic('example-image-a').dumps(),
at = TikZCoordinate(1,2),
options=TikZOptions('inner sep=0pt')
)
pic.append(img)
tex = doc.dumps()
doc.generate_pdf('basic',compiler='lualatex', clean_tex=False)
doc.generate_tex()
Tex-Code:
\documentclass[tikz]{standalone}%
\usepackage[T1]{fontenc}%
\usepackage[utf8]{inputenc}%
\usepackage{lmodern}%
\usepackage{textcomp}%
\usepackage{lastpage}%
\usepackage{geometry}%
\geometry{margin=0cm}%
\usepackage{tikz}%
%
%
%
\begin{document}%
\normalsize%
\noindent%
\begin{tikzpicture}%
\node[inner sep=0pt] at (1.0,2.0) {\includegraphics[width=0.8\textwidth]{example-image-a}};%
\end{tikzpicture}%
\end{document}
This looks pretty similar to the code in this post to me:
https://tex.stackexchange.com/questions/9559/drawing-on-an-image-with-tikz

The size of the tikz picture will adapt to the content and it is normally placed wherever you use it on the page, just as if you would write a normal letter.
You can see this if you add another, bigger element, to your picture. If you now play around with the coordinates of your node, you will see the image moving around.
Normally you could also position your nodes relative to the paper with the [remember picture, overlay] option, but you are using the standalone class, which will automatically adapt the paper size to the content, so in your case this does not help.
\documentclass[tikz]{standalone}%
\usepackage[T1]{fontenc}%
\usepackage[utf8]{inputenc}%
\usepackage{lmodern}%
\usepackage{textcomp}%
\usepackage{lastpage}%
%\usepackage{geometry}%
%\geometry{margin=0cm}%
\usepackage{tikz}%
%
%
%
\begin{document}%
\normalsize%
\noindent%
\begin{tikzpicture}%
\path (-20,-20) rectangle (20,20);
\node[inner sep=0pt] at (3.0,2.0) {\includegraphics[width=0.8\textwidth]{example-image-a}};%
\end{tikzpicture}%
\end{document}

Related

Python - plt.savefig() resulting in blank image without plt.show()

I work on a crowd simulation, and I tried to get a simple representation at a given time like this : new to the site so here is the link. I work with Spyder and the code works wonderfully when I display the image in ipython with plt.show(), but when i try to save the images with plt.savefig() (I removed plt.show() prior to that, not the issue) i ended up with blank images. Here is the code :
p,v,t = resolve() #p[c][i] is the position vector of individual i at time t[c]
N = len(t) # number of instant
n = len(m) # number of individual
murs_x = [w[0] for w in W] # wall points x coordinates
murs_y = [w[1] for w in W] # wall points y coordinates
conv = 39.3701 #inch/m
L = longueur*conv/50 # width of figure
H = (largeur + decalage)*conv/50 # height of figure
for c in range(N):
fig1 = plt.figure(num="aff",figsize = (L,H), dpi = 200) # arbitrary num, allow to recreate the figure
ax = fig1.add_axes([1,1,1,1])
ax.set_axis_off() # visual purpose
ax.set_frame_on(False) # visual purpose
ax.axis([0,longueur,0,largeur+decalage])
ax.scatter(murs_x,murs_y,s=0.01,marker='.')
for i in range(n):
if p[c][i][1] <= (largeur + r[i]): # presence condition for individual i
ax.add_artist(plt.Circle((p[c][i][0], p[c][i][1]), r[i], alpha=1))
# drawing of the circle representing individual i
# here is the plt.show(), unused
fig1.savefig(str(c)+".png") # trying to save instant c visual represention
fig1.clf()
Moreover, without the 2 lines for visual purposes, the images are not totally blank but rather like this : another link.
I first attempted to use matplotlib.animation to create a video, however i had the same issue of a blank video with 2 cropped zeros in the upper right corner. I suppose that the issue is linked to the artist class (I had better results using scattered points instead of circles to represent each individual) but I am a beginner and do not know how to handle it precisely. At least the size of the image is the one expected one.
Thanks for reading this.

How to view this .fits image without resizing and without modifying colors?

I am trying to open a full-color image from a '.fits' file. But, when comparing it to the corresponding '.gif' image, there appears to be an error regarding its color and size.
How can I view the real-color image in its proper dimensions?
As an example, one can select the '.fits' file and corresponding '.gif' file located at the top of this webpage. My example code, which uses the APLPY module, is below.
def from_fits_to_image(color_scheme, rloc, rname='synop_Ml_0.2104', rext='.fits', cmap=None):
"""
color_scheme : 'rgb', 'grayscale', or 'false color'; color scheme of image to be shown
rloc : type <str>; location of file to be read
rname : type <str>; name of file to be read
rext : type <str>; extension of file to be read
cmap : None or type <str>; colormap
"""
rpath = rloc + rname + rext
if color_scheme == 'rgb':
pic = aplpy.FITSFigure(rpath)
# pic.show_rgb(alt_filename) # what filename is supposed to go here?
else:
pic = aplpy.FITSFigure(rpath)
if color_scheme == 'grayscale':
pic.show_grayscale()
elif color_scheme == 'false color':
if cmap is None:
pic.show_colorscale()
else:
pic.show_colorscale(cmap=cmap)
# plt.savefig(...)
plt.show()
So long as one provides the proper rloc (the location of the downloaded '.fits' file) and color_scheme, the above code will run.
Calling the function below will show an empty plot of the proper dimensions. To make it non-empty, I must supply another existing filename, though I am unclear on what exactly that should be.
from_fits_to_image(color_scheme='rgb', rloc=rloc)
Each of the function calls below reveal a plot that has been resized to small. While color_scheme='grayscale' seems to colorize the plot properly, the other methods do not properly colorize the image.
from_fits_to_image('grayscale', rloc=rloc)
from_fits_to_image('false color', rloc=rloc)
from_fits_to_image('false color', rloc=rloc, cmap='plasma')
For comparison, the '.gif' image is below. Ideally, the output will look exactly like the image below.
EDIT:
I have tried using astropy, PIL, and pyfits unsuccessfully. Any help would be appreciated.
EDIT 2:
Below is the result using fits from astropy.io.
from astropy.io import fits
def reada(rloc, rname='synop_Ml_0.1998', rext='.fits'):
""" """
rpath = rloc + rname + rext
# hdu_list = fits.open(rpath)
# hdu_list.info()
pic = fits.getdata(rpath)
plt.imshow(pic)
plt.show()
reada(rloc=rloc)
I've played with the vmin and vmax kwargs, but to no success. Also, using pyfits to open the file results in the following error, even when using pyfits.open(rpath, uint=True, do_not_scale_image_data=True):
TypeError: Image data can not convert to float
Judging from the gif, it seems that the image is a false-color one, and it's a matter of choosing a right color map. I can't say if there's an equivalent color map in python to the one you've linked to, but we can find something that is pretty close, recreating all the features in the image:
fig = aplpy.FITSFigure('synop_Ml_0.2104.fits')
fig.show_colorscale(vmin=-60, vmax=60, cmap='hot')
which shows the following (note that aplpy does not understand this coordinate system so it plots the figure in pixel coordinates):
The second part of the question is more tricky, and I can't fully answer it. Firstly, you need to convert the Carrington time into longitude, and sine latitude into degrees, and then plot the new values for the axis labels either instead of the old ones or as a parasite axes alongside the old ones (you can refer to an parasite axes example here).
Now it looks like the Carrington time is just degrees rotated since November 9, 1853, and the x-axis spans exactly 360, so I assume the conversion is simply an offset by 757079.95, the the x-axis value at the left edge. We can double-check it on the world coordinates, by looking at how the pixel span of the map corresponds to the coordinate span:
In [88]: fig._wcs.wcs_pix2world(fig._ax1.get_xlim(), fig._ax1.get_ylim(), origin=1)
Out[88]: [array([757439.95, 757079.95]), array([-1., 1.])]
and the difference in values for the xaxis edges, 757079.95 and 757439.95, is exactly 360 degrees.
So then we can use some matplotlib tricks to manually offset the coordinate values to force them to go from zero to 360 and get the xaxis to match your gif image:
# using hidden attributes is non-pythonic but aplpy does not leave us other options
ax = fig._ax1
x_range = ax.get_xlim()
new_ticklabels = np.arange(60, 361, 60)
new_tick_positions = new_ticklabels / 360. * x_range[1] + x_range[0]
ax.set_xticks(new_tick_positions)
ax.set_xticklabels(new_ticklabels)
fig.axis_labels.set_xtext('Carrington Longitude')
Keep in mind that aplpy is a library designed for plotting celestial, not solar, coordinates, so getting the axes transform to work properly could be a rather painful process. An alternative way, and perhaps a better one, would be to plot the fits file with sunpy, a python library for solar physics. However, I have never used it, and it seems to throw an error for this particular fits file. Looks like you need to modify the header of the fits file to get the coordinates properly read. Perhaps you can get in touch with sunpy community if you want to use the library?

Why does ReportLab not draw my lines where I want it to?

sorry for the title. I'm not quite sure what the problem is, so I'm unable to express it more precisely.
I'm trying to replicate an existing form (only available on paper) using Python in ReportLab.
I measure the existing form and use the values to draw using ReportLab. Here is an example:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import mm
def test():
c = canvas.Canvas('test.pdf', pagesize=landscape(A4))
h, w = A4
c.line(21*mm, 37*mm, 278*mm, 37*mm)
c.showPage()
c.save()
When I print this file (no scaling) and measure it, the line is not where it is supposed to be. It is horizontally offset to the right by about 5mm and vertically offset towards the top by about 3mm.
Why is that? Is there some border around the canvas/page that is not documented in the manual? Is the line wider than its visual representation?
I know that I can accomodate for this error by simply adding the offset in my code, but this is an already tedious task and I want to make sure that I am not missing some issue inherent to ReportLab or PDF generation in general.
Draw a ruler in a page A4 or in pagesize as you mentioned and you can see these coordinates in your page and then you can draw line where ever you needed in your page based on plotted coordinates
def drawMyRuler(c):
c.drawString(100,810, 'x100')
c.drawString(200,810, 'x200')
c.drawString(300,810, 'x300')
c.drawString(400,810, 'x400')
c.drawString(500,810, 'x500')
c.drawString(10,100, 'y100')
c.drawString(10,200, 'y200')
c.drawString(10,300, 'y300')
c.drawString(10,400, 'y400')
c.drawString(10,500, 'y500')
c.drawString(10,600, 'y600')
c.drawString(10,700, 'y700')
c.drawString(10,800, 'y800')
def test():
c = canvas.Canvas('test.pdf', pagesize=landscape(A4))
h, w = A4
drawMyRuler(c)
#remaining code as per drawMyRuler coordinates...

OpenGL Texturing - some jpg's are being distorted in a strange way

I am trying to draw a textured square using Python, OpenGL and GLFW.
Here are all the images I need to show you.
Sorry for the way of posting images, but I don't have enough reputation to post more than 2 links (and I can't even post a photo).
I am getting this:
[the second image from the album]
Instead of that:
[the first image from the album]
BUT if I use some different jpg files:
some of them are being displayed properly,
some of them are being displayed properly until I rotate them 90 degrees (I mean using numpy rot90 function on an array with RGB components) and then send them to the GPU. And it looks like that (colors don't change, I only get some distortion):
Before rotation:
[the third image from the album]
After rotation:
[the fourth image from the album]
It all depends on a file.
Does anybody know what I do wrong? Or see anything that I don't see?
Code:
First, I do the thing with initializing glfw, creating a window, etc.
if __name__ == '__main__':
import sys
import glfw
import OpenGL.GL as gl
import numpy as np
from square import square
from imio import imread,rgb_flag,swap_rb
from txio import tx2gpu,txrefer
glfw.glfwInit()
win =glfw.glfwCreateWindow(800,800,"Hello")
glfw.glfwMakeContextCurrent(win)
glfw.glfwSwapInterval(1)
gl.glClearColor(0.75,0.75,0.75,1.0)
Then I load an image using OpenCV imread function and I remember about swapping red with blue. Then I send the image to gpu - I will describe tx2gpu in a minute.
image = imread('../imtools/image/ummagumma.jpg')
if not rgb_flag: swap_rb(image)
#image = np.rot90(image)
tx_id = tx2gpu(image)
The swap_rb() function (defined in a different file, imported):
def swap_rb(mat):
X = mat[:,:,2].copy()
mat[:,:,2] = mat[:,:,0]
mat[:,:,0] = X
return mat
Then comes the main loop (in a while I will describe txrefer and square):
while not glfw.glfwWindowShouldClose(win):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
txrefer(tx_id); square(2); txrefer(0)
glfw.glfwSwapBuffers(win)
glfw.glfwPollEvents()
And here is the end of the main function:
glfw.glfwDestroyWindow(win)
glfw.glfwTerminate()
NOW IMPORTANT THINGS:
A function that defines a square looks like that:
def square(scale=1.0,color=None,solid=True):
s = scale*.5
if type(color)!=type(None):
if solid:
gl.glBegin(gl.GL_TRIANGLE_FAN)
else:
gl.glBegin(gl.GL_LINE_LOOP)
gl.glColor3f(*color[0][:3]); gl.glVertex3f(-s,-s,0)
gl.glColor3f(*color[1][:3]); gl.glVertex3f(-s,s,0)
gl.glColor3f(*color[2][:3]); gl.glVertex3f(s,s,0)
gl.glColor3f(*color[3][:3]); gl.glVertex3f(s,-s,0)
else:
if solid:
gl.glBegin(gl.GL_TRIANGLE_FAN)
else:
gl.glBegin(gl.GL_LINE_LOOP)
gl.glTexCoord2f(0,0); gl.glVertex3f(-s,-s,0)
gl.glTexCoord2f(0,1); gl.glVertex3f(-s,s,0)
gl.glTexCoord2f(1,1); gl.glVertex3f(s,s,0)
gl.glTexCoord2f(1,0); gl.glVertex3f(s,-s,0)
gl.glEnd()
And texturing functions look like that:
import OpenGL.GL as gl
unit_symbols = [
gl.GL_TEXTURE0,gl.GL_TEXTURE1,gl.GL_TEXTURE2,
gl.GL_TEXTURE3,gl.GL_TEXTURE4,
gl.GL_TEXTURE5,gl.GL_TEXTURE6,gl.GL_TEXTURE7,
gl.GL_TEXTURE8,gl.GL_TEXTURE9,
gl.GL_TEXTURE10,gl.GL_TEXTURE11,gl.GL_TEXTURE12,
gl.GL_TEXTURE13,gl.GL_TEXTURE14,
gl.GL_TEXTURE15,gl.GL_TEXTURE16,gl.GL_TEXTURE17,
gl.GL_TEXTURE18,gl.GL_TEXTURE19,
gl.GL_TEXTURE20,gl.GL_TEXTURE21,gl.GL_TEXTURE22,
gl.GL_TEXTURE23,gl.GL_TEXTURE24,
gl.GL_TEXTURE25,gl.GL_TEXTURE26,gl.GL_TEXTURE27,
gl.GL_TEXTURE28,gl.GL_TEXTURE29,
gl.GL_TEXTURE30,gl.GL_TEXTURE31]
def tx2gpu(image,flip=True,unit=0):
gl.glActiveTexture(unit_symbols[unit])
texture_id = gl.glGenTextures(1)
gl.glBindTexture(gl.GL_TEXTURE_2D,texture_id)
gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_WRAP_S,gl.GL_REPEAT)
gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_WRAP_T,gl.GL_REPEAT)
gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR)
gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR)
yres,xres,cres = image.shape
from numpy import flipud
gl.glTexImage2D(gl.GL_TEXTURE_2D,0,gl.GL_RGB,xres,yres,0,gl.GL_RGB,gl.GL_UNSIGNED_BYTE,flipud(image))
gl.glBindTexture(gl.GL_TEXTURE_2D,0)
return texture_id
def txrefer(tex_id,unit=0):
gl.glColor4f(1,1,1,1);
gl.glActiveTexture(unit_symbols[unit])
if tex_id!=0:
gl.glEnable(gl.GL_TEXTURE_2D)
gl.glBindTexture(gl.GL_TEXTURE_2D,tex_id)
else:
gl.glBindTexture(gl.GL_TEXTURE_2D,0)
gl.glDisable(gl.GL_TEXTURE_2D)
The problem you have there are alignment issues. OpenGL initial alignment setting for "unpacking" images is that each row starts on a 4 byte boundary. This happens if the image width is not a multiple of 4 or if there are not 4 bytes per pixel. But it's easy enough to change this:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
would probably do the trick for you. Call it right before glTex[Sub]Image.
Another thing: Your unit_symbols list is completely unnecessary. The OpenGL specification explicitly says that GL_TEXTUREn = GL_TEXTURE0 + n. You can simply do glActiveTexture(GL_TEXTURE0 + n). However when loading a texture image the unit is completely irrelevant; the only thing it may matter is, that loading a texture only goes with binding one, which happens in a texture unit; a texture can be bound in any texture unit desired.
Personally I use the highest texture unit for loading images, to avoid accidently clobbering required state.

Reportlab [ Platypus ] - Image does not render

I am working on a report that includes a mixture of tables and images. The images [ graphs, actually ] are saved to the filesystem in .png form.
The method that actually renders the PDF is:
def _render_report(report_data):
file_name = get_file_name() # generate random filename for report
rpt = Report(settings.MEDIA_ROOT + os.sep + file_name)
Story = []
for (an, sam, event), props in report_data.iteritems():
Story.append(Paragraph("%s - sample %s results for %s" % (an.name, sam.name, event.name), styles["Heading2"]))
data_list = [['Lab', 'Method', 'Instrument', 'Unit', 'Raw Result', 'Converted Result', 'Outlier']]
for (index, series) in props['frame'].iterrows():
data_list.append(_format([
Paragraph(Lab.objects.get(pk=series['labs']).name, styles['BodyText']),
Paragraph(Method.objects.get(pk=series['methods']).name, styles['BodyText']),
Paragraph(Instrument.objects.get(pk=series['instruments']).name, styles['BodyText']),
Paragraph(Unit.objects.get(pk=series['units']).name, styles['BodyText']),
series['raw_results'],
series['results'],
series['outlier']
]))
table = Table(data_list, colWidths=[45 * mm, 35 * mm, 35 * mm, 25 * mm, 35 * mm, 35 * mm, 35 * mm], repeatRows=1)
Story.append(table)
Story.append(PageBreak())
if props['graph'] is not None:
Story.append(Image("/tmp/%s" % props['graph'], width=10 * inch, height=6 * inch))
Story.append(PageBreak())
rpt.draw(Story, onFirstPage=setup_header_and_footer, onLaterPages=setup_header_and_footer)
return file_name
Background Information
The page is set up as an A4, in landscape orientation
My development environment is a virtualenv; PIL 1.1.7 and reportlab 2.6 are installed and functional
The "Report" class used above is simply a thin wrapper around SimpleDocTemplate that sets up some defaults but delegates to SimpleDocTemplate's build implementation. Its code is:
class Report(object):
def __init__(self, filename, doctitle="Report", docauthor="<default>",
docsubject="<default>", doccreator="<default>", orientation="landscape", size=A4):
DEFAULTS = {
'leftMargin' : 10 * mm,
'rightMargin' : 10 * mm,
'bottomMargin' : 15 * mm,
'topMargin' : 36 * mm,
'pagesize' : landscape(size) if orientation == "landscape" else portrait(size),
'title' : doctitle,
'author' : docauthor,
'subject' : docsubject,
'creator' : doccreator
}
self.doc = SimpleDocTemplate(filename, **DEFAULTS)
def draw(self, flowables, onFirstPage=setup_header_and_footer, onLaterPages=setup_header_and_footer):
self.doc.build(flowables, onFirstPage=setup_header_and_footer,
onLaterPages=setup_header_and_footer, canvasmaker=NumberedCanvas)
What I have already looked at
I have confirmed that the images exist on disk. The paths are fully qualified paths.
PIL is installed, and is able to read the images correctly
The space assigned to the image is adequate; I have confirmed this by calculation. Also, if I increase the image size, ReportLab complains about the Image Flowable being too large. The current dimension should fit.
I have tested with and without the page breaks; they do not seem to make any difference
The Problem
The table, headings and page templates render OK but the images are blank. Earlier today, I had encountered this issue [ when setting up the templates used by this report ]. The workaround was to use canvas.drawInlineImage(... in place of canvas.DrawImage(... . It therefore looks as though there is an issue with my setup; I could use some pointers on how to debug it.
Update
I was able to apply a variant of the same workaround used in this linked question ( use canvas.drawInlineImage in place of canvas.drawImage. I subclassed `Image' as follows:
class CustomImage(Image):
"""
Override - to use inline image instead; inexplicable bug with non inline images
"""
def draw(self):
lazy = self._lazy
if lazy>=2: self._lazy = 1
self.canv.drawInlineImage(self.filename,
getattr(self,'_offs_x',0),
getattr(self,'_offs_y',0),
self.drawWidth,
self.drawHeight
)
if lazy>=2:
self._img = None
self._lazy = lazy
The only change from the "stock" Image class is in one line - using self.canv.drawInlineImage where there was self.canvas.drawImage before.
This "works" in the sense that the images are finally visible in my PDF. The reason why drawImage is not working still remains a mystery.
I have tried #PedroRomano's suggestion ( to make sure the images RGBA ), and even tried JPEG images instead of PNGs. These did not make a difference.
I eventually brought this matter to a close by using a custom Image subclass:
class CustomImage(Image):
"""
Override - to use inline image instead; inexplicable bug with non inline images
"""
def draw(self):
lazy = self._lazy
if lazy>=2: self._lazy = 1
self.canv.drawInlineImage(self.filename,
getattr(self,'_offs_x',0),
getattr(self,'_offs_y',0),
self.drawWidth,
self.drawHeight
)
if lazy>=2:
self._img = None
self._lazy = lazy
Saving the graphs in vector graphics formats eg EPS, saving as JPEG, saving as PNG with and without the alpha channel all did not seem to make a difference.
The optimal solution would be to generate your graphs in a vector format like postscript that is supported by reportlab. A lot of UNIX software can do this out of the box, and on windows you can use the excellent PDFCreator.
If you have to use raster images for your graphs, try converting your images to JPEG format. Those can be easily embedded in a PDF file using the DCTDecode filter. (This is e.g. what jpeg2pdf does.)

Categories