R: add alpha-value to png-image - image

Is there a way to make a rasterGrob-object partly transparent, so to add an alpha-factor to it? I'm using a logo as a watermark within a ggplot2 plot by inserting a png-image (as rasterGrob) by annotation_custom. However, unlike with annotate, the alpha option does not work here, so I guess the image has to be changed in advance.
As a simple example based on what baptiste suggests in his blog, so far I'm doing it this way:
img.path <- readPNG("logo.png")
pngob <- rasterGrob(img.path)
qplot(1:10, rnorm(10), geom = "blank") +
annotation_custom(pngob, xmin=6.8, xmax=Inf, ymin=1, ymax=Inf) +
geom_point()
The example above works perfectly.
However, typing dim(pngob) into the console returns NULL. Thus, the suggestion below on how to set an alpha-value does not work:
m <- pngob
w <- matrix(rgb(m[,,1],m[,,2],m[,,3], m[,,4] * 0.2), nrow=dim(m)[1])
This returns the error Error in m[, , 1]: wrong number of dimensions

Straight from the ggplot2 blog by #baptiste. You can adjust alpha when you create w.
library(png)
library(gridExtra)
m <- readPNG(system.file("img", "Rlogo.png", package="png"), FALSE)
w <- matrix(rgb(m[,,1],m[,,2],m[,,3], m[,,4] * 0.2), nrow=dim(m)[1]) #0.2 is alpha
qplot(1:10, rnorm(10), geom = "blank") +
annotation_custom(xmin=-Inf, ymin=-Inf, xmax=Inf, ymax=Inf,
rpatternGrob(motif=w, motif.width = unit(1, "cm"))) +
geom_point()
Or if you want to have a single image:
qplot(1:10, rnorm(10), geom = "blank") +
annotation_custom(xmin=-Inf, ymin=-Inf, xmax=Inf, ymax=Inf,
rasterGrob(w)) +
geom_point()

Related

tmap:: faceted animated map: How to suppress title when custom label given

I have created an animated faceted map using tmap:: tm_facets along with custom panel labels. How do I avoid that the argument that is used to facet is shown as additional title? I only want the custom label in the panel.
Minimum example:
rm(list=ls(all=TRUE))
library(tmap)
library(spData)
urb_anim = tm_shape(world) + tm_polygons() +
tm_shape(urban_agglomerations) + tm_dots(size = "population_millions") +
tm_facets(along = "year", free.coords = FALSE) +
tm_layout(panel.labels = c("custom label1", "custom label2"))
That gives me the following result:
When I try to reproduce the example for an animated map from here: https://geocompr.robinlovelace.net/adv-map.html I also don't get the titles in a panel as in the example but outside the plot in the top left corner.
I found the answer myself:
Using the by instead of the along argument with tm_facets worked for me when setting ncol =1 and nrow = 1 and saving the the created map using tmap_animation. So the code should be:
urb_anim = tm_shape(world) + tm_polygons() +
tm_shape(urban_agglomerations) + tm_dots(size = "population_millions") +
tm_facets(by = "year", free.coords = FALSE, ncol=1, nrow=1) +
tm_layout(panel.labels = c("custom label1", "custom label2"))

ggplotly tooltip for geom_text and geom_segment; does not work on Mac

I am working on revising a CRAN package. I have one function call that seems to only cause errors on Mac. It caused an error on r-release-osx-x86_64-mavericks on CRAN. I ran it on El Capitan and Mavericks and it also produced the same error on both of these Mac versions. All other systems checked by CRAN (solaris, linux, windows) did not cause an error.
I created a MWE of the function call as follows (sorry it is long to create the data). Basically, it starts with creating a ggplot2 figure using 3 data frames (edgeDF - all non-path edges, nodeDF - all non-path nodes, pathDF - edges and nodes for path of interest):
set.seed(1)
label=c()
for (i in 1:10){
label[i] = paste(sample(letters,sample(3:10, 1),replace=TRUE),collapse='')
}
nodeDF = data.frame(label = label, x = runif(10,0,10), y = runif(10,0,10))
edgeDF = data.frame()
edgeDF = rbind(edgeDF, c(x=nodeDF[1,]$x, xend=nodeDF[1,]$y, y=nodeDF[2,]$x, yend=nodeDF[2,]$y))
edgeDF = rbind(edgeDF, c(x=nodeDF[5,]$x, xend=nodeDF[5,]$y, y=nodeDF[6,]$x, yend=nodeDF[6,]$y))
colnames(edgeDF) = c("x","y","xend","yend")
r1=runif(1,0,10)
r2=runif(1,0,10)
r3=runif(1,0,10)
r4=runif(1,0,10)
label=c()
for (i in 1:3){
label[i] = paste(sample(letters,sample(3:10, 1),replace=TRUE),collapse='')
}
xend = c(r1, r2, runif(1,0,10))
xstart = c(runif(1,0,10), r1, r2)
yend = c(r3, r4, runif(1,0,10))
ystart = c(runif(1,0,10), r3, r4)
pathDF = data.frame(label=label,xstart=xstart,ystart=ystart,xend=xend,yend=yend,x=xstart,y=ystart)
edgeCol="gray84"
pathEdgeCol="seagreen"
nodeCol="black"
plotTotalImage = ggplot2::ggplot(data = nodeDF, ggplot2::aes(x = x, y = y)) +
ggplot2::geom_segment(data = edgeDF, ggplot2::aes(x=x, y=y, xend=xend, yend=yend), colour = edgeCol) +
ggplot2::geom_segment(data = pathDF, ggplot2::aes(x=xstart, y=ystart, xend=xend, yend=yend), colour = pathEdgeCol) +
ggplot2::geom_text(data = nodeDF, ggplot2::aes(x = x, y = y, label = label), colour = nodeCol)
plotTotalImage = plotTotalImage + ggplot2::geom_text(data = pathDF,ggplot2::aes(x = x, y = y, label = label), fontface= "bold")
I call geom_segment to create the edges (gray ones are off path, green ones are on path). I call geom_text to create node labels (non-bold ones are off path, bold ones are on path). This successfully creates a static image.
At this point, I want to use plotly to add interactivity to the plot. I do not want information to hover for segments; I only want information to hover for node labels. When the mouse hovers over a node label, I want the x value and the label name to be displayed.
The following code works as intended on Windows:
animatePlotTotalImage <- plotly::plotly_build(plotly::ggplotly(plotTotalImage, tooltip = c("x", "label")))
animatePlotTotalImage$data[[1]]$hoverinfo <- "none"
animatePlotTotalImage$data[[2]]$hoverinfo <- "none"
animatePlotTotalImage$data[[3]]$hoverinfo <- c("x+text")
animatePlotTotalImage$data[[4]]$hoverinfo <- c("x+text")
animatePlotTotalImage
However, on Mac, it results in the following Error:
Error in `*tmp*`[[2]] : subscript out of bounds
I am unsure how to go about solving this problem. Any ideas or suggestions would be greatly appreciated!
I might be wrong but I think you have $x missing from your statements:
This works for me (mac Sierra):
animatePlotTotalImage <- plotly::plotly_build(plotly::ggplotly(plotTotalImage, tooltip = c("x", "label")))
animatePlotTotalImage$x$data[[1]]$hoverinfo <- "none"
animatePlotTotalImage$x$data[[2]]$hoverinfo <- "none"
animatePlotTotalImage$x$data[[3]]$hoverinfo <- c("x+text")
animatePlotTotalImage$x$data[[4]]$hoverinfo <- c("x+text")

Easeljs keep object within bounds

I am working on a drawing application in HTML5 canvas, using Easeljs. So far I am able to drag and drop objects into the field, but I only want them within certain bounds.
To illustrate:
Objects 1, 2, 4 and 5 should get deleted, but object 3 should be kept.
I have tried using hitTest(), but that didn't work properly (I probably did something wrong). I would love to post the code I used, but my PC froze while working on it... Thought I'd better ask while unfreezing, haha.
Here is a quick drag and drop sample with bounds constraining:
http://jsfiddle.net/xrqatyLs/8/
The secret sauce is just in constraining the drag position to your own values.
clip.x = Math.max(bounds.x, Math.min(bounds.x + bounds.width - clipWidth, evt.stageX));
clip.y = Math.max(bounds.y, Math.min(bounds.y + bounds.height-clipHeight, evt.stageY));
Here is another more complex example that manually checks if one rectangle intersects another rectangle:
http://jsfiddle.net/lannymcnie/yvfLwdzn/
Hope that helps!
Solution:
var obj1 = obj.getBounds().clone(); // obj = a pylon
var e = obj1.getTransformedBounds();
var obj2 = bg.getBounds().clone(); // bg = the big green field
var f = obj2.getTransformedBounds();
if(e.x < f.x || e.x + e.width > f.x + f.width) return false;
if(e.y < f.y || e.y + e.height > f.y + f.height) return false;
return true;
After all it's so simple, but I guess I was working on it for so long that I started to think too hard...

Figure window showing up matlab

I have written this code to help me compare different image histograms however when i run it i get a figure window popping up. I can't see anywhere in the code where i have written imshow and am really confused. Can anyone see why? thanks
%ensure we start with an empty workspace
clear
myPath= 'C:\coursework\'; %#'
number_of_desired_results = 5; %top n results to return
images_path = strcat(myPath, 'fruitnveg');
images_file_names = dir(fullfile(images_path, '*.png'));
images = cell(length(images_file_names), 3);
number_of_images = length(images);
%textures contruction
%loop through all textures and store them
disp('Starting construction of search domain...');
for i = 1:length(images)
image = strcat(images_path, '\', images_file_names(i).name); %#'
%store image object of image
images{i, 1} = imread(image);
%store histogram of image
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
%store name of image
images{i, 3} = images_file_names(i).name;
disp(strcat({'Loaded image '}, num2str(i)));
end
disp('Construction of search domain done');
%load the three example images
RGB1 = imread('C:\coursework\examples\salmon.jpg');
X1 = rgb2ind(RGB1,colormap(colorcube(256)));
example1 = imhist(X1);
RGB2 = imread('C:\coursework\examples\eggs.jpg');
X2 = rgb2ind(RGB2,colormap(colorcube(256)));
example2 = imhist(X2);
RGB3 = imread('C:\coursework\examples\steak.jpg');
X3 = rgb2ind(RGB3,colormap(colorcube(256)));
example3 = imhist(X3);
disp('three examples loaded');
disp('compare examples to loaded fruit images');
results = cell(length(images), 2);
results2 = cell(length(images), 2);
results3 = cell(length(images), 2);
for i = 1:length(images)
results{i,1} = images{i,3};
results{i,2} = hi(example1,images{i, 2});
end
results = flipdim(sortrows(results,2),1);
for i = 1:length(images)
results2{i,1} = images{i,3};
results2{i,2} = hi(example2,images{i, 2});
end
results2 = flipdim(sortrows(results2,2),1);
for i = 1:length(images)
results3{i,1} = images{i,3};
results3{i,2} = hi(example3,images{i, 2});
end
results3 = flipdim(sortrows(results3,2),1);
The colormap function sets the current figure's colormap, if there is no figure one is created.
The second parameter of imhist should be the number of bins used in the histogram, not the colormap.
Run your code in the Matlab debugger, step through it line by line, and see when the figure window pops up. That'll tell you what's creating it.
Etienne's answer is right for why you're getting a figure, but I'd just like to add that colormap is unnecessary in this code:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
All you need is:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colorcube(256)));
The second input of rgb2ind should be a colormap, yes. But the output of colorcube is a colormap already. Unless you've got an existing figure and you either want to set the colormap of it or retrieve the colormap it is currently using, the actual function colormap is not necessary.
Other than opening an unnecessary figure, the output of your existing code won't be wrong, as I think in this situation colormap will just pass as an output argument the colormap it was given as an input argument. For example, if you want to set the current figure colormap to one of the inbuilts and return the actual colormap:
cmap = colormap('bone');

problem saving pdf file in R with ggplot2

I am encountering an odd problem. I am able to create and save pdf file using R/ggplot2 and view them while the R Console is running. As soon as I exit the R console, Preview on Mac OS X will no longer display the PDF. I have been able to save .png files w/o problem, but for reasons beyond my control, I need to save in pdf files. The code I am using to save is as follows:
pdfFile <-c("/Users/adam/mock/dir/structure.pdf")
pdf(pdfFile)
ggplot(y=count,data=allCombined, aes(x=sequenceName, fill=factor(subClass))) + geom_bar()
ggsave(pdfFile)
Has anyone encountered a similar problem? If so, what do I need to do to fix it?
Thank you very much for your time.
The problem is that you don't close the pdf() device with dev.off()
dat <- data.frame(A = 1:10, B = runif(10))
require(ggplot2)
pdf("ggplot1.pdf")
ggplot(dat, aes(x = A, y = B)) + geom_point()
dev.off()
That works, as does:
ggplot(dat, aes(x = A, y = B)) + geom_point()
ggsave("ggplot1.pdf")
But don't mix the two.
It is in the R FAQ, you need a print() around your call to ggplot() -- and you need to close the plotting device with dev.off() as well, ie try
pdfFile <-c("/Users/adam/mock/dir/structure.pdf")
pdf(pdfFile)
ggplot(y=count,data=allCombined,aes(x=sequenceName,fill=factor(subClass)))
+ geom_bar()
dev.off()
Edit: I was half-right on the dev.off(), apparently the print() isn;t needed. Gavin's answer has more.
The following plot
pdf("test.pdf")
p <- qplot(hp, mpg, data=mtcars, color=am,
xlab="Horsepower", ylab="Miles per Gallon", geom="point")
p
dev.off()
works in the console but not in a function or when you source this from a file.
myfunc <- function() {
p <- qplot(hp, mpg, data=mtcars, color=am,
xlab="Horsepower", ylab="Miles per Gallon", geom="point")
p
}
pdf("test.pdf")
myfunc()
dev.off()
Will produce a corrupt pdf file and the way to fix it us use
print(p)
within a function.
In a console. "p" is automatically printed but not in a function or when you source the file.
You can also change the filename of your pdf plot within ggsave if you want to call it something other than "ggplot1" or whatever concise object name you chose; just give the filename first and then tell it which plot you're referring to, for example:
a <- ggplot(dat, aes(x = A, y = B)) + geom_point()
ggsave("Structure.pdf",plot=a)

Resources