Link tip labels to phylogenetic tree using dots - r

I'm trying to produce a non-ultrametric tree using the ape package in R and the function plot.phylo(). I'm struggling to find any documentation on how to keep the tip label vertically aligned on their left edge and with a series of dots (variable length) linking the species' name to the tip of the node.
Any help would be much appreciated as well as links to other packages within R that may be able to achieve this.
An example of the newick tree
I don't have any tree examples of what i want, however, the description seems self explanatory. the labels would all be shifted to the very right, and aligned on their left side, then a series of dots (.......) would link the label to where there old position was.
MLJTT = newickTree (as a string)
plot.phylo(read.tree(text = MLJTT), show.tip.label = T,use.edge.length = T, no.margin = T, cex = 0.55)
And example of three that I want to copy the layout of from here:

Ok, I ended up slightly modifying the default plot.phylo code to accomidate such a change. Here's how it looks
library(ape)
plot.phylo2 <- plot.phylo
environment(plot.phylo2) <- environment(plot.phylo)
body(plot.phylo2)[[c(34, 3, 6, 3, 4, 3)]] <- quote({
mx <- max(xx[1:Ntip])
segments(xx[1:Ntip], yy[1:Ntip] + loy, mx, yy[1:Ntip] + loy,
lty=2, col="grey")
text(mx + lox, yy[1:Ntip] + loy, x$tip.label, adj = adj,
font = font, srt = srt, cex = cex, col = tip.color)
})
This is somewhat fragile and may change in different version of ape, I've tested this with version ape_3.1-4. You can check if this will work by verifying that
body(plot.phylo)[[c(34, 3, 6, 3, 4, 3)]]
returns
text(xx[1:Ntip] + lox, yy[1:Ntip] + loy, x$tip.label, adj = adj,
font = font, srt = srt, cex = cex, col = tip.color)
just to make sure we are changing the correct line. But the code above basically replaces that line where the labels are drawn by moving the x axis where they are drawn and adding in the segments for the dotted lines. Then you can run this with your test data
MLJTT = read.tree(text="..<sample data>..")
plot.phylo2(MLJTT,
show.tip.label = T,use.edge.length = T, no.margin = T, cex = 0.55)
And this produces

I think what you may be looking for is the argument to plot.phylo:
align.tip.label = TRUE
Have you tried this?
MLJTT <- rtree(100)
plot.phylo(MLJTT, show.tip.label = T, align.tip.label = T, use.edge.length = T, no.margin = T, cex = 0.55)

Related

Enlarge single symbol (/) in R expression

I have the following code:
plot(x = 1, y = 1, xlim = c(1,2), ylim = c(1,2),
ylab = expression(bgroup("(",A[B]^{C},")")[~D[2]] / bgroup("(",E[F]^{G},")")[~H]))
Which leads to this plot:
Is it possible to make the division symbol ("/") taller so it properly divides two expression and doesn't look like it's shooting out of D2?
My attempt at manually drawing it with cex>1 lead to an ugly and fat division symbol. I don't want it fatter, just taller.
I am looking for solutions that use base plot methods.
If you don't mind using latex, you can export the plot using tickz. That will unleash the full power of latex formatting. E.g. with a standard sized division sign it looks like this:
library(devtools)
install_github('daqana/tikzDevice')
library(tikzDevice)
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$(A_B^C)_{D_2} / (E_F^G)_{H}$')
dev.off()
or if you want an even bigger division sign, you can use one of the latex codes (in ascending order of size) \big/, \Big/, \bigg/, or \Bigg/:
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$\\left(A_B^C\\right)_{D_2} \\bigg/ \\left(E_F^G\\right)_{H}$')
dev.off()

R quantmod chart_Series: Title and Subtitle allignment

I am having problems with aligning my subtitle in chart_Series.
At present it is just writing over the top of the x axis.
Also is it possible to switch off the text that is automatically written at the top of a
chart_Series chart so I can replace it with my own
library(quantmod)
getSymbols("SPY", from="2013-01-01", to=Sys.Date())
chart_Series(SPY)
title("S&P Index", sub = "text1\n\text2\ntext3",
cex.main = 2, font.main= 4, col.main= "blue",
cex.sub = 0.75, font.sub = 3, col.sub = "red")
I would be grateful for your help.
The 'quantmod' graphics are object-oriented. Data is stored in an environment (named 'Env') inside another environment (named whatever you name it, 'cspy' in this case). Special charting functions are stored with along with the data in a 'proto'-object. It is a more object-oriented approach than is used in either the S3 or S4 programming paradigms that are much more common in R. The 'proto'-package should be consulted for more details. After nosing around the code in chartSeries and the object it creates, I can get the labeling at the top to go away with this:
cspy <- chart_Series(SPY, name = NULL)
cspy$Env$actions[[4]] <- NULL
cspy
The 'quantmod' code has this:
cs$Env$name <- name
text.exp <- c(expression(text(1 - 1/3, 0.5, name, font = 2,
col = "#444444", offset = 0, cex = 1.1, pos = 4)),
expression(text(NROW(xdata[xsubset]),
0.5, paste(start(xdata[xsubset]), end(xdata[xsubset]),
sep = " / "), col = 1, adj = c(0, 0), pos = 2)))
cs$add(text.exp, env = cs$Env, expr = TRUE)
... but I wasn't able to figure out a name for that leaf so I looked at :
cspy$Env$actions
... and saw that the name and date-range were in the 4th item. so I just deleted it. (To get rid of only the name it is trivial: chart_Series(SPY, name = NULL). (I don't know if the location of that graphical item in the object will be consistent and I do not see a method for access that object-leaf, so this is possibly an unstable hack.)
To make room for the margin text (subtitle):
png("out.png")
myoma <- par("oma")
myoma[1] <- 3
par("oma" =myoma)
cspy
title("S&P Index", cex.main = 2, font.main= 4, col.main= "blue")
mtext(text= "text1\ntext2\ntext3", side=1, cex = 0.75, font = 3, col = "red",line=7)
dev.off()
I am not familiar with chart_Series plot from before. Normally I would have used the plotting parameter mar to increase the margin at the bottom of the plot, to make some more room for the sub-title. However, I didn't manage to increase the margin that way. Instead I had to use oma, to increase the outer margins of the plot. I added the sub-titles using mtext, instead of using the sub argument in title. You set the distance from the plot with line. The default chart_Series title is turned off by setting name = NULL. Please also note the 'Note' in ?chart_Series: "Highly experimental (read: alpha) use with caution.". Anyway,
par(oma = c(5, 0, 0, 0))
chart_Series(SPY, name = NULL)
title("S&P Index", cex.main = 2, font.main = 4, col.main = "blue")
mtext(text = "text1\n\text2\ntext3",
side = 1, line = 9, cex = 0.75, font = 3, col = "red")

Set plot margin of png plot device using par

I've created a choropleth of Brazil. When saving the plot in .png, the upper and the lower part of the plot are lost (covered). Here are the lines to save the plot.
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(0,-30),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
For saving the plot without losing the upper and the lower part of the map, I must change the coordinates to add white space at the bottom and at the top (i.e. replace c(0,-30) by c(5,-33)):
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
This works in the sense that I can see the full map but the map then does not use all the available area in the figure. It seems that there are some margin in the upper and the lower part of the figure when saving the plot. I've never had that problem with other types of plot.
Sorry, I don't have enough "reputation" to post images to show you how the maps look like.
Any idea of how to fix this?
Edit:
The comments below got me searching more into the problem and I finally found a fix. I apologize as I now realized that I did not understand the source of the problem and thus did not explain as best as I could have,
It seems that png resets the outer margin of the plot. Thus, even though I had set omi=c(0,0,0,0), those were not the value used by the png command in saving the plot. The solution was to set the plot parameters after calling png so save the figure.
plot.new()
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
From Details in ?par:
Each device has its own set of graphical parameters.
Thus, even though I had set the outer margin of the plot in par (omi = c(0,0,0,0)), those value were overwritten by the parameters in png when saving the plot.
The solution was to set the margin parameters in par after calling png
plot.new()
# first open png device...
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
# ...then set par
par(omi = c(0,0,0,0), mgp = c(0,0,0), mar = c(0,0,0,0), family = "D")
par(mfrow = c(1, 1), cex = 1, cex.lab = 0.75, cex.main = 0.2, cex.axis = 0.2)
plot(c(-75, -35), c(5, -33), type = "n", axes = FALSE, xlab = "", ylab = "", asp = 1.2)
plot(Brazil, col = cols[Brazil$Cons.g_ri], add = TRUE, border = "black", lwd = 0.5)
dev.off()

R legend issue, symbols of points are masked by lines

Is there a way to draw the lines in such a way that they would start on the side of the points, or allow the symbols to be in foreground?
My solution was to make the symbols bigger and more visible.
Edit 1: it's for plot {graphics} of the R program.
Edit 2: the code per popular request.
legend(2,.4,bty='n', c('sugar','citrus','none'), pch=c('s','c','u'), pt.bg='white',lty= c(1,2,3), lwd=1.5, title="Condition",pt.cex=c(1.5),cex=1.5)
Edit 3: This is solved for plot(type='b') but somehow not for legend.
Thanks for reading!
The only thing I can come up with is to manually finagle the dash lengths until they end up looking the way you want them. For instance, this:
> plot(1,1)
> legend(c("A", "B"), col = 1:2, x = 1, y = .8, lty="99", pch=1:2)
produces the image below.
The lty parameter allows you to specify the lengths of lines and dashes as hex characters. In this case, it's saying to create a line of length 9 then create a space of length 9 then repeat. It looks like 9 is about the best fit to space around a normal pch symbol.
Note that you'd probably need to adjust this depending on the size of the image, symbol, etc. My advice ultimately would be to export the image from R and touch up the image to meet your needs in graphic editing software.
Going with the suggestion by #JeffAllen, here is a way to get what I think you might want. It requires modifying the legend() function to return the position of the points (these are given by x1 and y1 in body(legend)[[46]]).
legend2 <- legend
body(legend2)[[49]] <- quote(
invisible(list(rect = list(w = w, h = h, left = left, top = top),
text = list(x = xt, y = yt), points = list(x = x1, y = y1)))
)
Make a plot:
plot(-100:100, -100:100, type = "b")
While drawing the legend, draw white circles (pch = 21 with pt.bg = 'white') over the lines, and assign the values invisibly returned by legend2() to an object. Note also the changes to pt.lwd and pt.cex.
myLegend <- legend2(1, .8, bty = 'n', c('sugar','citrus','none'), pch = 21,
pt.bg = 'white', pt.lwd = 0, lty = c(1, 2, 3), lwd = 1.5, title = "Condition",
pt.cex = c(1.8), cex = 1.5)
Finally, draw the characters you'd like to use in the legend using points(), supplying the x and y values from the object myLegend.
points(myLegend$points$x, myLegend$points$y, pch = c('s','c','u'), cex = 1.5)
And this should get you something like:
You could also use the filled points offered by R (pch=21:25) and specify the fill color using pc.bg which gets passed to the points call when creating a legend.
plot(1,1)
legend(c("A", "B"), col = 1:2, x = 1, y = .8, lty=1, pt.bg=1:2, pch=21:22)
generates the following:

GNU R, VennDiagram, and making a complement diagram

I have been working on Venn Diagrams in GNU R. I have tried using the packages venneuler and VennDiagram. I find that VennDiagram has a lot more granular control, but it seems to lack the documentation to fill in all the details. The closest I can find is this PPT file.
http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3041657/bin/1471-2105-12-35-S4.PPT which I found from the URL: http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3041657/
Here are my issues with using VennDiagram.
For the code
require(VennDiagram)
venn.diagram(list(B = 1:2000, A = 200:400),fill = c("yellow", "blue"),
alpha = c(0.8, 0.8), cex =1.5, cat.pos=0, cat.fontface = 4,
lty = 1, fontfamily =3, filename = "test001.jpeg");
(I had an image here, but since I am new I do not have rights to post the image. Please generate the image from the code above.)
I can make a subset (hence a circle within a circle). But I am not finding a way to do the following:
Make BC to show as the equal of B^C. No, a literal "B^C" does not work. I would think there is a way to relabel the sets in a different property, but I have not seen a way to do it.
To position the labels of B^C and A^C within the sets and not on the outside as currently shown. I tried cat.pos="inner" but that way not a valid property. I also tried cat.pos=c(0,0) in the hope that I could feed it as an X,Y where X & Y are from the center of the circle, but it did not produce any different results.
Thanks to DWin, here is the code to complete my diagram to the exercise.
Suppose that A ⊂ B. Show that Bc ⊂ Ac.
require(VennDiagram)
plot.new()
venn.plot <- venn.diagram(
x = list(B = 1:200, A = 20:40), category.names= expression(B, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5,
cat.pos=0, cat.dist=c(-.1, -.1), filename = NULL) ;
grid.draw(venn.plot); # grid graphic requires explicit print or draw operation
grid.text(expression(B^c),x=0.2,y=0.95)
grid.text(expression(A^c),x=0.16,y=0.95)
grid.text(expression(A^c),x=0.16,y=0.75)
Perhaps something like this:
venn.diagram(list(B = 1:200, A = 20:40), category.names= expression(B^c, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5, cat.pos=0,
cat.dist=c(.1, -.1), cat.fontface = 4,lty = 1, fontfamily =3,
filename = "test001.jpeg")
To get the labels inside the circles, supply 'cat.dist' with negative values. The trick is that the reference point is radial distance from the boundary at 12 o'clock rather than from the center. The documentation says that the category.names argument is interpreted with plotmath syntax. The superscript operation in plotmath is done with the "^" operator. I have here moved the A" inside while leaving the B^c outside to suggest that it is the area outside the B circle that is being labeled. (I also improved the plotting time by making the example smaller.) I tried drawing three labels but that does not seem to "part of the package".
Here's a way you can annotate with grid.text() on the screen device:
plot.new()
venn.plot <- venn.diagram(
x = list(B = 1:200, A = 20:40), category.names= expression(B^c, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5,
cat.pos=0, cat.dist=c(.05, -.1), filename = NULL) ;
grid.draw(venn.plot); # grid graphic requires explicit print or draw operation
grid.text("B",x=0.8)
# then you can save to file

Resources