I am trying to make a custom arrowhead with Wolfram Mathematica (v. 10.0) using function FilledCurve. The result is looking fine on the Wolfram output. When I save the picture as pdf, some undesirable vertical line appears on the left border of my arrowhead. It is visible also in the latex document where I insert my pictures.
The code is
px = 0.7; py = 0.14; mpx = -0.2;
pts = {{-px, py}, {mpx, 0}, {-px, -py}};
ah = Graphics[{FilledCurve[{BSplineCurve[pts], Line[{{-px, -py}, {0, 0}, {-px, py}}]}]}]
To see the problem you need to save the output as pdf and open it in Adobe Acrobat Reader (or insert it in latex document).
Any suggestions?
Thank you!
It seems there is some bag in WM.
I solves the problem just by creating the required curve "manually" from lines.
The final code (with some minor improvements) is as follows:
px = 0.7; py = 0.14; mpx = -0.3;
pts = {{-px, py}, {mpx, 0}, {-px, -py}};
curpts = Table[f[t], {t, 0, 1, 0.02}];
f = BSplineFunction[pts];
linpts = {{-px, -py}, {0, 0}, {-px, py}};
allpts = Join[curpts, {linpts[[-2]], linpts[[-1]]}];
ah = Graphics[{FilledCurve[Line[allpts]], Line[linpts]}]
Result:
Related
I am writing a latex document and using matplotlib for plots. I want to have the font and font size (9) of the captions of my latex document also for the plot axes and legend text.
Furthermore, I would like to fill out the \linewidth or \textwidth of my latex document, which is 369 pt. Now the matplotlib.pyplot.figure function accepts the input parameter figsize which should be in inches, so I duly specify it as 369/72 inches, 1/72 being the conversion factor from pt to inches.
Later I cut down excess white space by using the bbox_inches=tight and pad_inches=0 options of the savefig function.
The font and font size part works as intended. It looks exactly identical between the figure text and the caption text. However, I am still dissatisfied with the figure width.
Below is a minimal example of a figure I produce.
import matplotlib
import matplotlib.pyplot as plt
plt.rcdefaults()
plt.rcParams['font.size'] = '9'
plt.rcParams['figure.autolayout'] = False
matplotlib.rc('font', family='sans-serif', serif=['Palatino'])
matplotlib.rc('text', usetex=True)
params = {'text.latex.preamble': [
r'\usepackage[american]{babel}',
r'\usepackage{mathpazo}',
r'\usepackage{amsmath,amssymb,amsfonts,mathrsfs}',
r'\usepackage{textcomp}',
]}
plt.rcParams.update(params)
plt.rcParams['mathtext.default'] = 'regular'
plt.rcParams['legend.handlelength'] = 1
delta_adjust = 0
plt.rcParams['figure.subplot.bottom'] = delta_adjust
plt.rcParams['figure.subplot.top'] = 1 - delta_adjust
plt.rcParams['figure.subplot.left'] = delta_adjust
plt.rcParams['figure.subplot.right'] = 1 - delta_adjust
plt.rcParams['figure.subplot.hspace'] = 0.55
plt.rcParams['figure.subplot.wspace'] = 0.55
default_figsize=(369/72, 369/72)
fig = plt.figure(figsize=default_figsize)
sp1 = plt.subplot(3,3,1)
sp2 = plt.subplot(3,3,2)
sp3 = plt.subplot(3,3,3)
for sp in sp1, sp2, sp3:
sp.set_title('Title')
sp.set_xlabel('Xlabel')
sp.set_ylabel('Ylabel')
twin = sp3.twinx()
twin.set_ylabel('Ylabel')
fig.set_size_inches(default_figsize)
fig.savefig('./example.pdf', transparent=False, bbox_inches='tight', pad_inches=0, ending='.pdf')
This is the result of the above code. The figure has a width of 429.356 pt instead of the desired 369 pt. When I increase the delta_adjust parameter in the code, I get smaller pdf widths.
[philipp#desktop scripts]$ python minimal_example.py
[philipp#desktop scripts]$ pdfinfo example.pdf
Creator: matplotlib 3.1.2, http://matplotlib.org
Producer: matplotlib pdf backend 3.1.2
CreationDate: Thu Jan 13 11:41:13 2022 CET
Tagged: no
UserProperties: no
Suspects: no
Form: none
JavaScript: no
Pages: 1
Encrypted: no
Page size: 429.356 x 130.412 pts
Page rot: 0
File size: 102863 bytes
Optimized: no
PDF version: 1.4
When I scale the figsize parameter of the python code from 369 pt to 369*369/429 pt, I end up with a 386 pt pdf. I do not want to use a trial and error strategy to find the correct parameter. As a last resort, I could write an iterative program as a savefig routine but I would prefer to avoid this. For reference, here is the output of the program converted to png: image
In summary, I am looking for help on how to set the figure width reliably.
I am on Ubuntu 20.04, python 3.8, matplotlib 3.1.2, and I use the TkAgg backend which is the default.
Any help is appreciated.
Only after posting this question did this website recommend me the following question: How to get figure size and fontsize right for PDFs exported from matplotlib?
It turns out that bbox_inches=tight messes with the figure size.
I removed this option and set delta_adjust = 0.1 in the code above.
Now the figure has the expected size of exactly 369x369 pt.
Most of it is whitespace, which I can remove using the pdfcrop command line utility.
The current script looks like this.
import os
import matplotlib
import matplotlib.pyplot as plt
plt.rcdefaults()
plt.rcParams['font.size'] = '9'
plt.rcParams['figure.autolayout'] = False
matplotlib.rc('font', family='sans-serif', serif=['Palatino'])
matplotlib.rc('text', usetex=True)
params = {'text.latex.preamble': [
r'\usepackage[american]{babel}',
r'\usepackage{mathpazo}',
r'\usepackage{amsmath,amssymb,amsfonts,mathrsfs}',
r'\usepackage{textcomp}',
]}
plt.rcParams.update(params)
plt.rcParams['mathtext.default'] = 'regular'
plt.rcParams['legend.handlelength'] = 1
delta_adjust_h = 0.1
delta_adjust_v = 0.1
plt.rcParams['figure.subplot.bottom'] = delta_adjust_v
plt.rcParams['figure.subplot.top'] = 1 - delta_adjust_v
plt.rcParams['figure.subplot.left'] = delta_adjust_h
plt.rcParams['figure.subplot.right'] = 1 - delta_adjust_h
plt.rcParams['figure.subplot.hspace'] = 0.55
plt.rcParams['figure.subplot.wspace'] = 0.55
#factor = 369/429.356
factor = 1
default_figsize=(369/72*factor, 369/72*factor)
fig = plt.figure(figsize=default_figsize)
sp1 = plt.subplot(3,3,1)
sp2 = plt.subplot(3,3,2)
sp3 = plt.subplot(3,3,3)
for sp in sp1, sp2, sp3:
sp.set_title('Title')
sp.set_xlabel('Xlabel')
sp.set_ylabel('Ylabel')
twin = sp3.twinx()
twin.set_ylabel('Ylabel')
fig.set_size_inches(default_figsize)
#fig.savefig('./example.pdf', transparent=False, ending='.pdf', pad_inches=0)
# bbox_inches='tight', pad_inches=0, ending='.pdf')
fig.savefig('./example.pdf', transparent=True, pad_inches=0, ending='.pdf')
os.system('pdfcrop ./example.pdf ./example_cropped.pdf')
The output of pdfinfo is the following:
[philipp#desktop scripts]$ pdfinfo example_cropped.pdf
Creator: TeX
Producer: pdfTeX-1.40.20
CreationDate: Thu Jan 13 13:28:25 2022 CET
ModDate: Thu Jan 13 13:28:25 2022 CET
Tagged: no
UserProperties: no
Suspects: no
Form: none
JavaScript: no
Pages: 1
Encrypted: no
Page size: 364 x 112 pts
Page rot: 0
File size: 102853 bytes
Optimized: no
PDF version: 1.4
So it is still not perfect, as the figure width is slightly too small due to the cropping.
Also it is now not guaranteed that all the contents fit within the printed pdf, which previously was ensured by the bbox_inches option.
Nevertheless, this is an improvement as now the plot sizes can no longer exceed the latex \linewidth.
I may update this answer if I find a better solution.
Edit: There is a feature under development at matplotlib which would solve the problem: https://matplotlib.org/stable/tutorials/intermediate/constrainedlayout_guide.html
I tried it but it seems to work best when the subplots are all created at once, such as with plt.subplots. I will have to change all my scripts, because currently I add subplots one by one with plt.subplot. Moreover I need to set the vertical figure size explicitly instead of simply generating a square figure and cropping all the unused whitespace.
I am trying to estimate the head pose of single images mostly following this guide:
https://towardsdatascience.com/real-time-head-pose-estimation-in-python-e52db1bc606a
The detection of the face works fine - if i plot the image and the detected landmarks they line up nicely.
I am estimating the camera matrix from the image, and assume no lens distortion:
size = image.shape
focal_length = size[1]
center = (size[1]/2, size[0]/2)
camera_matrix = np.array([[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype="double")
dist_coeffs = np.zeros((4, 1)) # Assuming no lens distortion
I am trying to get the head pose by matching points in the image with points in the 3D model using solvePNP:
# 3D-model points to which the points extracted from an image are matched:
model_points = np.array([
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye corner
(225.0, 170.0, -135.0), # Right eye corner
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0) # Right mouth corner
])
image_points = np.array([
shape[30], # Nose tip
shape[8], # Chin
shape[36], # Left eye left corner
shape[45], # Right eye right corne
shape[48], # Left Mouth corner
shape[54] # Right mouth corner
], dtype="double")
success, rotation_vec, translation_vec) = \
cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs)
finally, I am getting the euler angles from the rotation:
rotation_mat, _ = cv2.Rodrigues(rotation_vec)
pose_mat = cv2.hconcat((rotation_mat, translation_vec))
_, _, _, _, _, _, angles = cv2.decomposeProjectionMatrix(pose_mat)
now the azimuth is what i would expect - it is negative if i look to the left, zero in the middle and positive to the right.
the elevation however is strange - if i look in the middle it has a constant value but the sign is random - changing from image to image (the value is around 170).
When i look up the sign is positive and the value decreases the more i look up,
When i look down the sign is negative and the value decreases the more i look down.
Can someone explain this output to me?
Ok so it seems i have found a solution - the model points (which i have found in several blogs on the topic) seem to be wrong. The code seems to work with this combination of model and image points (no idea why it was trial and error):
model_points = np.float32([[6.825897, 6.760612, 4.402142],
[1.330353, 7.122144, 6.903745],
[-1.330353, 7.122144, 6.903745],
[-6.825897, 6.760612, 4.402142],
[5.311432, 5.485328, 3.987654],
[1.789930, 5.393625, 4.413414],
[-1.789930, 5.393625, 4.413414],
[-5.311432, 5.485328, 3.987654],
[2.005628, 1.409845, 6.165652],
[-2.005628, 1.409845, 6.165652],
[2.774015, -2.080775, 5.048531],
[-2.774015, -2.080775, 5.048531],
[0.000000, -3.116408, 6.097667],
[0.000000, -7.415691, 4.070434]])
image_points = np.float32([shape[17], shape[21], shape[22], shape[26],
shape[36], shape[39], shape[42], shape[45],
shape[31], shape[35], shape[48], shape[54],
shape[57], shape[8]])
i want to change the aspect ratio of an image for the instagram with python .here is my code for change the aspact ration :
width,height=imageFile.size
aspectRatio = width/height
if(aspectRatio>=0.80 and aspectRatio<=1.90):
print("yeah")
else:
if(height>width):
futureHeight = width/.85
print(str(width)+" ,"+str(futureHeight))
print(width/futureHeight)
left = 0
int(futureHeight)
teetet = height-futureHeight/2
top = teetet / 4
right = width
bottom = height -150
im1 = imageFile.crop((left, top, right, bottom))
print(im1.size)
im1.show()
im1.save(image)
but still it show
ValueError: Incompatible aspect ratio.
whenever i try to upload this image
i resolved that using basic dimensions. using the inspector i saw that instagram convert images to 598.02x598.02 in the home page, so i typed:
im=PIL.Image.open(path)
im=im.resize((598,598), Image.ANTIALIAS)
im.save(path) # overwrite the image
instead of
im=PIL.Image.open(path)
baseheight = 560
hpercent = (baseheight / float(im.size[1]))
wsize = int((float(im.size[0]) * float(hpercent)))
im=im.resize((wsize, baseheight), PIL.Image.ANTIALIAS)
im.save(path)
in wich aspect ratio is out of range anyway.
now you can post it using something like instabot without troubles 'cause the aspect ratio is 1.0 .
I want to plot a simplified heatmap that is not so difficult to edit with the scalar vector graphics program I am using (inkscape). The original heatmap as produced below contains lots of rectangles, and I wonder if they could be merged together in the different sectors to simplify the output pdf file:
nentries=100000
ci=rainbow(nentries)
set.seed=1
mean=10
## Generate some data (4 factors)
i = data.frame(
a=round(abs(rnorm(nentries,mean-2))),
b=round(abs(rnorm(nentries,mean-1))),
c=round(abs(rnorm(nentries,mean+1))),
d=round(abs(rnorm(nentries,mean+2)))
)
minvalue = 10
# Discretise values to 1 or 0
m0 = matrix(as.numeric(i>minvalue),nrow=nrow(i))
# Remove rows with all zeros
m = m0[rowSums(m0)>0,]
# Reorder with 1,1,1,1 on top
ms =m[order(as.vector(m %*% matrix(2^((ncol(m)-1):0),ncol=1)), decreasing=TRUE),]
rowci = rainbow(nrow(ms))
colci = rainbow(ncol(ms))
colnames(ms)=LETTERS[1:4]
limits=c(which(!duplicated(ms)),nrow(ms))
l=length(limits)
toname=round((limits[-l]+ limits[-1])/2)
freq=(limits[-1]-limits[-l])/nrow(ms)
rn=rep("", nrow(ms))
for(i in toname) rn[i]=paste(colnames(ms)[which(ms[i,]==1)],collapse="")
rn[toname]=paste(rn[toname], ": ", sprintf( "%.5f", freq ), "%")
heatmap(ms,
Rowv=NA,
labRow=rn,
keep.dendro = FALSE,
col=c("black","red"),
RowSideColors=rowci,
ColSideColors=colci,
)
dev.copy2pdf(file="/tmp/file.pdf")
Why don't you try RSvgDevice? Using it you could save your image as svg file, which is much convenient to Inkscape than pdf
I use the Cairo package for producing svg. It's incredibly easy. Here is a much simpler plot than the one you have in your example:
require(Cairo)
CairoSVG(file = "tmp.svg", width = 6, height = 6)
plot(1:10)
dev.off()
Upon opening in Inkscape, you can ungroup the elements and edit as you like.
Example (point moved, swirl added):
I don't think we (the internet) are being clear enough on this one.
Let me just start off with a successful export example
png("heatmap.png") #Ruby dev's think of this as kind of like opening a `File.open("asdfsd") do |f|` block
heatmap(sample_matrix, Rowv=NA, Colv=NA, col=terrain.colors(256), scale="column", margins=c(5,10))
dev.off()
The dev.off() bit, in my mind, reminds me of an end call to a ruby block or method, in that, the last line of the "nested" or enclosed (between png() and dev.off()) code's output is what gets dumped into the png file.
For example, if you ran this code:
png("heatmap4.png")
heatmap(sample_matrix, Rowv=NA, Colv=NA, col=terrain.colors(32), scale="column", margins=c(5,15))
heatmap(sample_matrix, Rowv=NA, Colv=NA, col=greenred(32), scale="column", margins=c(5,15))
dev.off()
it would output the 2nd (greenred color scheme, I just tested it) heatmap to the heatmap4.png file, just like how a ruby method returns its last line by default
How to increase resolution of gif image generated by rgl package of R (plot3d and movie3d functions) - either externally or through R ?
R Code :
MyX<-rnorm(10,5,1)
MyY<-rnorm(10,5,1)
MyZ<-rnorm(10,5,1)
plot3d(MyX, MyY, MyZ, xlab="X", ylab="Y", zlab="Z", type="s", box=T, axes=F)
text3d(MyX, MyY, MyZ, text=c(1:10), cex=5, adj=1)
movie3d(spin3d(axis = c(0, 0, 1), rpm = 4), duration=15, movie="TestMovie",
type="gif", dir=("~/Desktop"))
Output :
Update
Adding this line at the beginning of code solved the problem
r3dDefaults$windowRect <- c(0, 100, 1400, 1400)
I don't think you can do much about the resolution of the gif itself. I think you have to make the image much larger as an alternative, and then when you display it smaller it looks better. This is untested as a recent upgrade broke a thing or two for me, but this did work under 2.15:
par3d(windowRect = c(0, 0, 500, 500)) # make the window large
par3d(zoom = 1.1) # larger values make the image smaller
# you can test your settings interactively at this point
M <- par3d("userMatrix") # save your settings to pass to the movie
movie3d(par3dinterp(userMatrix=list(M,
rotate3d(M, pi, 1, 0, 0),
rotate3d(M, pi, 0, 1, 0) ) ),
duration = 5, fps = 50,
movie = "MyMovie")
HTH. If it doesn't quite work for you, check out the functions used and tune up the settings.