palaeoverse / rphylopic

Get Silhouettes of Organisms from PhyloPic
https://rphylopic.palaeoverse.org
GNU General Public License v3.0
91 stars 9 forks source link

Specify width, instead of height, when plotting phylopics #103

Closed megaraptor1 closed 1 month ago

megaraptor1 commented 8 months ago

Describe the bug The ysize argument in add_phylopic is ignored if ggplot:coord_cartesian is called. It is not possible to scale images imported via rphylopic.

To Reproduce

library(rphylopic)
img<-get_phylopic(uuid=get_uuid(name = "Rhizoprionodon terraenovae"))
ggplot() +
coord_cartesian(xlim=c(0,1))+
  add_phylopic(img=img,x=0.5,ysize=0.5)

Expected behavior The silhouette should be plotted and take up about 50% of the size of the resulting ggplot.

Screenshots Rplot04

Argument ysize is set to 0.5 when this image was plotted, and coord_cartesian was set to xlim=c(0,1)

Desktop (please complete the following information):

Additional context Add any other context about the problem here.

willgearty commented 8 months ago

Hi @megaraptor1, thanks for submitting your issue! I believe this is the intended behavior. ysize refers to the height of the silhouette in coordinate space, not as a proportion of the plot size. In your example, it looks like the shark is about 0.5 units high, just as you've specified to ysize. Let us know if the documentation isn't clear enough and we can improve that.

willgearty commented 8 months ago

Ah, never mind, I thought the shark was going from -.25 to .25, but I see it is actually -.025 to .025, so only a height of 0.05. I'll look into this when I get a chance, thanks!

megaraptor1 commented 8 months ago

What I really need is a way to scale the shark so the tip of its nose is at 0 and the tip of its tail is at 1 (x length of image is 1). There does not appear to be a way to do this based on current documentation.

willgearty commented 8 months ago

Ah, I see. Right now, as you've discovered, we scale the image based on it's height. The height shouldn't change as long as the ysize doesn't change, so you could just tweak the width of the plot until the shark is the width you want in x units. But that's a little hacky. Maybe we could have an alternate way to specify the width instead. I'll have to think about that...

megaraptor1 commented 8 months ago

I am unable to tweak the width like that because I have to get this graph to line up with another graph

https://stackoverflow.com/questions/77923358/how-can-i-plot-an-image-directly-above-a-ggplot-aligned-with-the-graph-below

willgearty commented 8 months ago

I will look into having a way to specify the width OR the height.

megaraptor1 commented 8 months ago

Just tried playing around with the width of the plot until I get the shark the right size. Does not really work. The size of the figure is heavily dependent on the size of surrounding elements. If I plot another figure on top of it I can kind of get it to work, but the function as written now seems heavily dependent on the existence of a pre-existing graph to scale silhouettes.

LewisAJones commented 8 months ago

coord_cartesian sets expand to TRUE by default. What about setting it to FALSE to get the desired plot as a quick solution for now @megaraptor1?

# Load libraries
library(rphylopic)
library(ggplot2)
# Get image
img <- get_phylopic(uuid=get_uuid(name = "Rhizoprionodon terraenovae"))
# Plot
ggplot() +
  coord_cartesian(xlim = c(0,1), ylim = c(0,1), expand = FALSE) +
  add_phylopic(img = img, x = 0.5, y = 0.5, ysize = Inf)

image

megaraptor1 commented 8 months ago

@LewisAJones

Does not work. The two graphs do not match up when I try to stitch them together in patchwork. I can try guesstimating values for ysize but that gets back to the same problem as before where it is not easy to estimate what value is needed.

library(patchwork);library(rphylopic);library(tidyverse)

img<-get_phylopic(uuid=get_uuid(name = "Rhizoprionodon terraenovae"))

p1 <- ggplot() +
  coord_cartesian(xlim=c(0,1),ylim=c(0,1),expand=F)+
  add_phylopic(img=img,x=0.5,y=0.5,ysize=1)+
  geom_vline(aes(xintercept=c(0,1)))+
  theme_void()

proportion<-data.frame(group=c(rep("A",10),
                               rep("B",10),
                               rep("C",10)),
                       num=c(rnorm(20,mean=0.45,sd=0.05),
                             rnorm(20,mean=0.55,sd=0.05),
                             rnorm(20,mean=0.5,sd=0.05)))

p2 <- ggplot(proportion,aes(y=group,x=num)) +
  geom_boxplot()+
  coord_cartesian(xlim=c(0,1))+
  geom_vline(xintercept=1)+
  geom_vline(xintercept=0)

p1 / p2 + plot_layout(heights = 1:2) & theme(plot.margin = margin(0, 20, 0, 0))

Rplot10

I managed to find a workaround where I digitized the .svg silhouette from Phylopic, extracted the X-Y coordinates from it in a third-party software, and then plotted those coordinates as a polygon to be able to more precisely control the length of the silhouette.

willgearty commented 8 months ago

I'm currently working on allowing users to specify the width of the silhouette instead of the height, but I'm glad you found a workaround in the meantime @megaraptor1.