Does Makie have linked brushing capability similar to Holoviews? - julia

In Holoviews it is possible to link two different plots, so that when we zoom in or select parts of one plot, the other plots reflects the same zooming in or selection. Are there similar functionality available in Makie?
Edit 1
Based on the answer I tried the code below, However, I get a static image. I tired it both in Jupyter lab notebook and VSCode both of which were installed in Windows Subsystem for Linux with Ubuntu. The code I tried is:
using CairoMakie
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98),
resolution = (1000, 700))
ga = f[1, 1] = GridLayout()
gb = f[2, 1] = GridLayout()
gcd = f[1:2, 2] = GridLayout()
gc = gcd[1, 1] = GridLayout()
gd = gcd[2, 1] = GridLayout()
axtop = Axis(ga[1, 1])
axmain = Axis(ga[2, 1], xlabel = "before", ylabel = "after")
axright = Axis(ga[2, 2])
linkyaxes!(axmain, axright)
linkxaxes!(axmain, axtop)
labels = ["treatment", "placebo", "control"]
data = randn(3, 100, 2) .+ [1, 3, 5]
for (label, col) in zip(labels, eachslice(data, dims = 1))
scatter!(axmain, col, label = label)
density!(axtop, col[:, 1])
density!(axright, col[:, 2], direction = :y)
end
f
Edit 2
After suggesting that I should use GLMakie for interactive plot, I tried it in VSCode and indeed I got an interactive plot. However, in Jupyter notebook, I got a static image. The solution is to use Makie.inline!(false) and display(f) rather than using f:
using GLMakie
Makie.inline!(false)
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98),
resolution = (1000, 700))
ga = f[1, 1] = GridLayout()
gb = f[2, 1] = GridLayout()
gcd = f[1:2, 2] = GridLayout()
gc = gcd[1, 1] = GridLayout()
gd = gcd[2, 1] = GridLayout()
axtop = Axis(ga[1, 1])
axmain = Axis(ga[2, 1], xlabel = "before", ylabel = "after")
axright = Axis(ga[2, 2])
linkyaxes!(axmain, axright)
linkxaxes!(axmain, axtop)
labels = ["treatment", "placebo", "control"]
data = randn(3, 100, 2) .+ [1, 3, 5]
for (label, col) in zip(labels, eachslice(data, dims = 1))
scatter!(axmain, col, label = label)
density!(axtop, col[:, 1])
density!(axright, col[:, 2], direction = :y)
end
display(f)

You can use linkxaxes! and linkyaxes!. Here's an example: https://makie.juliaplots.org/v0.17.13/tutorials/layout-tutorial/index.html#panel_a

Related

How to interact with plot using keyboard arros?

My interactive plot (topoplot) reacts to mouse signals, but how to make it reacting to keyboard signals?
Here is my code:
f = Figure()
xs = 1:1:193 #range(-30, 120, length = size(dat_e, 2))
sg = SliderGrid(f[2, 1],
(label="time", range=xs, format = "{:d} ms", startvalue = 100),
)
time = sg.sliders[1].value
str = lift(t -> "[$t ms]", time)
topo_slice = lift((t, data) -> mean(data[1:30, t, :], dims=2)[:,1], time, dat_e)
topo_axis = Axis(f[1, 1], aspect = DataAspect())
topo = eeg_topoplot!(topo_axis, topo_slice,
raw.ch_names[1:30];
positions=pos, # produced automatically from ch_names
label_text=true) # aspect ratio, correlation of height and width
text!(topo_axis, 1, 1, text = str, align = (:center, :center))
#topo_slice = lift((t, data) -> data[:, :, t], time, topo)
xlims!(-0.2, 1.1)
ylims!(-0.2, 1.2)
hidedecorations!(topo_axis)
hidespines!(topo_axis)
f
There is an official instruction https://docs.juliahub.com/AbstractPlotting/6fydZ/0.12.11/interaction.html, but as usual with Julia documentations, there is no example and I have no idea how implement it in my code.
How my plot looks like:
Expanding on the answer from before:
T = 10
pts = range(-1, 1, length=100)
ts = reshape(1:T, 1, 1, :)
topo = cos.(pts) .+ cos.(ts .* pts')
fig = Figure()
ax = Axis(fig[1, 1])
sg = SliderGrid(fig[2,1],
(label="time", range=1:T))
time = sg.sliders[1].value
str = lift(t -> "[$t ms]", time)
text!(ax, str)
topo_slice = lift((t, data) -> data[:, :, t], time, topo)
# decrement/increment slider with left/right keys
on(events(fig).keyboardbutton) do btn
if btn.action in (Keyboard.press, Keyboard.repeat)
if btn.key == Keyboard.left
set_close_to!(sg.sliders[1], time[] - 1)
elseif btn.key == Keyboard.right
set_close_to!(sg.sliders[1], time[] + 1)
end
end
end
contour!(ax, topo_slice)
hidedecorations!(ax)
hidespines!(ax)
fig

'overlay' is not an exported object from 'namespace:sp' [duplicate]

This question already has an answer here:
How should I deal with "'someFunction' is not an exported object from 'namespace:somePackage'" error? [closed]
(1 answer)
Closed 2 years ago.
I have some code showing this error, but, I haven't called "overlay", maybe it's a library function that is calling it
Code:
d.mle=likfit(P, ini.cov.pars = c(1,30), cov.model = 'matern', kappa = 0.5)
d.mle
Xb = c(1, size, size, 1)
Yb = c(1, 1, size, size)
bordas = cbind(Xb, Yb)
polygon(bordas)
Ap = matrix(apply(bordas, 2, range))
gr <- expand.grid(x = seq(Ap[1, ], Ap[2, ], by = 1), y = seq(Ap[3, ], Ap[4, ], by = 1))
require(splancs)
gi <- polygrid(gr, borders = bordas) # delimita a area para interpolação
points(gi, pch = "+", col = 2)
KC = krige.control(obj = d.mle, type.krige = "ok", lam = 1)
d.k = krige.conv(P, loc = gr, krige = KC) #Realiza a interpolação por krigagem
valores_preditos = d.k$predict
Ze = matrix(valores_preditos, size, size) # Transforma os valores preditos em matriz
plot(Ze)
plot(image(X, Y, Ze, col = gray((0 : 4) / 4), breaks = c(a., b., c., d., e., f.)))
If you do this:
??overlay
... you should get a list of all the functions in packages that mention the word "overlay". When I do it, I see two functions with that name but I strongly suspect that it is the raster-package's version that is expected by the code you are using. So do this:
install.packages('raster')
library(raster)
#re-run code

custom ztick labels on surf plot, using PyPlot

Looking for custom zticklabels and fontsize too on the z-axis. Most notably the intuitive approach of using zticks([-(R+r),0,R+r],["-R-r","0","R+r"],fontsize=16) does not work. I am using Julia 4.3.0 because this is an older project which I cannot fully convert to a newer version at this time. The commented lines below include additional commands I tried which were unsuccessful.
My final goal here is to get the -0.8, 0, 0.8 values on the z-axis to instead say "-r", and "0" and "r" respectively.
using PyPlot
colormapp = "nipy_spectral"
R = 1.6;
r = 0.8;
N = 256;
dx = 2*pi/(N-1);
y = zeros(N,1); # y = phi (col) toroidal
x = y.'; # x = theta (row) poloidal
for ix = 2:N; y[ix] = (ix-1)*dx; x[ix] = (ix-1)*dx; end
cosxsqr = cos(x) .+ 0.0*y;
sinxsqr = sin(x) .+ 0.0*y;
sinysqr = 0.0*x .+ sin(y);
cosysqr = 0.0*x .+ cos(y);
Rrcosxsqr = R+r*cosxsqr;
rRrcosx = r*Rrcosxsqr[:];
Xsqr = Rrcosxsqr.*cosysqr;
Ysqr = Rrcosxsqr.*sinysqr;
Zsqr = r*sinxsqr;
figure(98)
clf()
pmeshtor = pcolormesh(x,y,Zsqr+r,cmap=colormapp);
cb = colorbar();
colorvals = Zsqr+r;
colorvals = colorvals/maximum(colorvals[:])
ax = figure(99)
clf()
srf = surf(Xsqr,Ysqr,Zsqr,cstride=10,rstride=10,facecolors=get_cmap(colormapp).o((colorvals)))
cb = colorbar(pmeshtor,ticks=[0,0.8,1.6])
cb[:ax][:set_yticklabels](["-r","0","r"], fontsize=16)
xlabel("x",fontsize=16)
ylabel("y",fontsize=16)
zlabel("z",fontsize=16)
xlim([-(R+r)-0.3,R+r+0.3])
ylim([-(R+r)-0.3,R+r+0.3])
zlim([-(R+r)-0.3,R+r+0.3])
xticks([-(R+r),0,R+r],["-R-r","0","R+r"],fontsize=16)
yticks([-(R+r),0,R+r],["-R-r","0","R+r"],fontsize=16)
zticks([-r,0,r])
#zticklabels([-r,0,r],["-r","0","r"])
#setp(ax[:get_zticklabels](),fontsize=16);
#setp(ax[:set_zticklabels](["-r","0","r"]))#,fontsize=16);
Here is the resulting image.
The commented command
setp(ax[:set_zticklabels](["-r","0","r"]),fontsize=16);
does work, but only if insert missing projection option as follows in Fig 99
figure(99)
ax = subplot(111, projection="3d")

Changing axes labels for biplot() in R

I am trying to visualize the results of a PCoA{ape} by making a biplot in R.
The axes now get the default labels axis 1 and axis 2, but I want to edit this.
This is the code I have tried:
biplot(pcoa.ntK, Y=NULL, plot.axes=c(1,2), rn=ntnames,
xlabs="PC1 (%)", ylabs="PC2 (%)")
But the labels don't change.
Can someone tell me what I'm doing wrong here?
And I also would like to edit the title, anyone tips for this?
My data:
ntK <- matrix(
c(0.00000, 0.01500, 0.01832, 0.02061, 0.01902, 0.01270, 0.02111, 0.01655, 0.01520, 0.01691,
0.01667, 0.00000, 0.01175, 0.01911, 0.01759, 0.01127, 0.01854, 0.01041, 0.00741, 0.02007,
0.02432, 0.01404, 0.00000, 0.02551, 0.01972, 0.01838, 0.02505, 0.01484, 0.01391, 0.02687,
0.01501, 0.01252, 0.01399, 0.00000, 0.01442, 0.01294, 0.01402, 0.01132, 0.01239, 0.01455,
0.02343, 0.01951, 0.01830, 0.02440, 0.00000, 0.01727, 0.02470, 0.02021, 0.01699, 0.02482,
0.01320, 0.01054, 0.01439, 0.01847, 0.01457, 0.00000, 0.01818, 0.01366, 0.00977, 0.01394,
0.02468, 0.01950, 0.02206, 0.02251, 0.02343, 0.02040, 0.00000, 0.02028, 0.01875, 0.02558,
0.02254, 0.01276, 0.01522, 0.02117, 0.02234, 0.01790, 0.02363, 0.00000, 0.01152, 0.02557,
0.01804, 0.00792, 0.01244, 0.02019, 0.01637, 0.01116, 0.01904, 0.01004, 0.00000, 0.02099,
0.01862, 0.01988, 0.02227, 0.02200, 0.02218, 0.01476, 0.02408, 0.02066, 0.01947, 0.00000),
nrow=10,
ncol=10)
library(ape)
ntnames <- c("A","B","C","D","E","F","G","H","I","J")
pcoa.ntK <- pcoa(ntK)
biplot is a generic function. The default method and the method for use with objects that come from using the prcomp function in the stats package do allow you to specify axis labels and a title, but for some reason the person that wrote the method that is called with objects of class pcoa hasn't allowed you to specify them. I think your only option would be to write your own version of biplot.pcoa (or ask the package maintainer to add this option).
This is a very quick and dirty hack of the function in the ape package that might do what you want, but no promises that it won't have broken something else!
biplot.pcoa <- function (x, Y = NULL, plot.axes = c(1, 2), dir.axis1 = 1, dir.axis2 = 1,
rn = NULL, xlabs = NULL, ylabs = NULL, main = NULL, ...)
{
k <- ncol(x$vectors)
if (k < 2)
stop("There is a single eigenvalue. No plot can be produced.")
if (k < plot.axes[1])
stop("Axis", plot.axes[1], "does not exist.")
if (k < plot.axes[2])
stop("Axis", plot.axes[2], "does not exist.")
if (!is.null(rn))
rownames(x$vectors) <- rn
labels = colnames(x$vectors[, plot.axes])
if (!is.null(xlabs)) labels[1] <- xlabs
if (!is.null(ylabs)) labels[2] <- ylabs
diag.dir <- diag(c(dir.axis1, dir.axis2))
x$vectors[, plot.axes] <- x$vectors[, plot.axes] %*% diag.dir
if (is.null(Y)) {
limits <- apply(x$vectors[, plot.axes], 2, range)
ran.x <- limits[2, 1] - limits[1, 1]
ran.y <- limits[2, 2] - limits[1, 2]
xlim <- c((limits[1, 1] - ran.x/10), (limits[2, 1] +
ran.x/5))
ylim <- c((limits[1, 2] - ran.y/10), (limits[2, 2] +
ran.y/10))
par(mai = c(1, 1, 1, 0.5))
plot(x$vectors[, plot.axes], xlab = labels[1], ylab = labels[2],
xlim = xlim, ylim = ylim, asp = 1)
text(x$vectors[, plot.axes], labels = rownames(x$vectors),
pos = 4, cex = 1, offset = 0.5)
if (is.null(main)){
title(main = "PCoA ordination", line = 2.5)
} else title(main = main, line = 2.5)
}
else {
n <- nrow(Y)
points.stand <- scale(x$vectors[, plot.axes])
S <- cov(Y, points.stand)
U <- S %*% diag((x$values$Eigenvalues[plot.axes]/(n -
1))^(-0.5))
colnames(U) <- colnames(x$vectors[, plot.axes])
par(mai = c(1, 0.5, 1.4, 0))
biplot(x$vectors[, plot.axes], U, xlab = labels[1], ylab = labels[2])
if (is.null(main)) {
title(main = c("PCoA biplot", "Response variables projected",
"as in PCA with scaling 1"), line = 4)
} else title(main = main, line = 4)
}
invisible()
}
biplot(pcoa.ntK, xlabs = 'My x label', ylabs = 'My y label', main = 'My title')
You can check the source code of biplot.pcoa and you'll see it's not that hard to modify. The author of the package decided to hard-code the axis labels based on the input and also the main title of the plot. Here's a modified version that will first check if values for xlab, ylab and main were used before using the pre-defined ones:
biplot.pcoa <- function (x, Y = NULL, plot.axes = c(1, 2), dir.axis1 = 1, dir.axis2 = 1,
rn = NULL, ...)
{
k <- ncol(x$vectors)
if (k < 2)
stop("There is a single eigenvalue. No plot can be produced.")
if (k < plot.axes[1])
stop("Axis", plot.axes[1], "does not exist.")
if (k < plot.axes[2])
stop("Axis", plot.axes[2], "does not exist.")
if (!is.null(rn))
rownames(x$vectors) <- rn
args <- list(...)
labels = ifelse(c("xlab", "ylab") %in% names(args), c(args$xlab, args$ylab), colnames(x$vectors[, plot.axes]))
diag.dir <- diag(c(dir.axis1, dir.axis2))
x$vectors[, plot.axes] <- x$vectors[, plot.axes] %*% diag.dir
if (is.null(Y)) {
limits <- apply(x$vectors[, plot.axes], 2, range)
ran.x <- limits[2, 1] - limits[1, 1]
ran.y <- limits[2, 2] - limits[1, 2]
xlim <- c((limits[1, 1] - ran.x/10), (limits[2, 1] +
ran.x/5))
ylim <- c((limits[1, 2] - ran.y/10), (limits[2, 2] +
ran.y/10))
par(mai = c(1, 1, 1, 0.5))
title <- ifelse("main" %in% names(args), args$main, "PCoA ordination")
plot(x$vectors[, plot.axes], xlab = labels[1], ylab = labels[2],
xlim = xlim, ylim = ylim, asp = 1,
main = title)
text(x$vectors[, plot.axes], labels = rownames(x$vectors),
pos = 4, cex = 1, offset = 0.5)
#title(main = "PCoA ordination", line = 2.5)
}
else {
n <- nrow(Y)
points.stand <- scale(x$vectors[, plot.axes])
S <- cov(Y, points.stand)
U <- S %*% diag((x$values$Eigenvalues[plot.axes]/(n -
1))^(-0.5))
colnames(U) <- colnames(x$vectors[, plot.axes])
par(mai = c(1, 0.5, 1.4, 0))
title <- ifelse("main" %in% names(args), args$main, c("PCoA biplot", "Response variables projected",
"as in PCA with scaling 1"))
biplot(x$vectors[, plot.axes], U, xlab = labels[1], ylab = labels[2], main = title)
# title(main = c("PCoA biplot", "Response variables projected",
# "as in PCA with scaling 1"), line = 4)
}
invisible()
}
Then:
biplot(pcoa.ntK, Y=NULL, plot.axes=c(1,2), rn=ntnames,
xlab="PC1 (%)", main = "Main Title")
Keep in mind this won't change the original function, so you'll need to load this modified version every time you load the package and need wish to set the labels like this.

labeling points on an archetype archmap

How might one add labels to an archmap from the archetypes package? Or alternatively, would it be possible to recreate the archmap output in ggplot?
Using code from the SportsAnalytics demo (I hope this isn't bad form)
library("SportsAnalytics")
library("archetypes")
data("NBAPlayerStatistics0910")
dat <- subset(NBAPlayerStatistics0910,
select = c(Team, Name, Position,
TotalMinutesPlayed, FieldGoalsMade))
mat <- as.matrix(subset(dat, select = c(TotalMinutesPlayed, FieldGoalsMade)))
a3 <- archetypes(mat, 3)
archmap(a3)
I'd like the player names ( NBAPlayerStatistics0910$Name ) over the points on the chart. Something like below but more readable.
If you don't mind tweaking things a bit, you can start with the archmap() function base, toss in an extra parameter and add a text() call:
amap2 <- function (object, a.names, projection = simplex_projection, projection_args = list(),
rotate = 0, cex = 1.5, col = 1, pch = 1, xlab = "", ylab = "",
axes = FALSE, asp = TRUE, ...)
{
stopifnot("archetypes" %in% class(object))
stopifnot(is.function(projection))
k <- object$k
if (k < 3) {
stop("Need at least 3 archetypes.\n")
}
cmds <- do.call(projection, c(list(parameters(object)), projection_args))
if (rotate != 0) {
a <- pi * rotate/180
A <- matrix(c(cos(a), -sin(a), sin(a), cos(a)), ncol = 2)
cmds <- cmds %*% A
}
hmds <- chull(cmds)
active <- 1:k %in% hmds
plot(cmds, type = "n", xlab = xlab, ylab = ylab, axes = axes,
asp = asp, ...)
points(coef(object) %*% cmds, col = col, pch = pch)
######################
# PLAY WITH THIS BIT #
######################
text(coef(object) %*% cmds, a.names, pos=4)
######################
rad <- ceiling(log10(k)) + 1.5
polygon(cmds[hmds, ])
points(cmds[active, ], pch = 21, cex = rad * cex, bg = "grey")
text(cmds[active, ], labels = (1:k)[active], cex = cex)
if (any(!active)) {
points(cmds[!active, , drop = FALSE], pch = 21, cex = rad *
cex, bg = "white", fg = "grey")
text(cmds[!active, , drop = FALSE], labels = (1:k)[!active],
cex = cex, col = "grey20")
}
invisible(cmds)
}
amap2(a3, dat$Name)
Obviously, my completely quick stab is not the end result you're looking for, but it should help you get on your way (if I read what you want to do correctly).

Resources