How to interact with plot using keyboard arros? - plot

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

Related

How to move object across axis?

I have an interactive plot and I want to move topoplot position across the x-axis according to the slider (or red vertical bar) position.
How can I do that?
In an ideal situation, the topoplot moves until some border (so it would be partially out of the screen).
Also, is it possible to put a line connecting the topolot with a red vertical line?
This is my script with prerequisite functions:
using Makie
using GLMakie
using PyMNE
using JLD2 # loading data
using TopoPlots
using StatsBase # mean/std
using Pipe
using ColorSchemes
using Colors
using LinearAlgebra
function eegHeadMatrix(positions, center, radius)
oldCenter = mean(positions)
oldRadius, _ = findmax(x-> LinearAlgebra.norm(x .- oldCenter),
positions)
radF = radius/oldRadius
return Makie.Mat4f(radF, 0, 0, 0,
0, radF, 0, 0,
0, 0, 1, 0,
center[1]-oldCenter[1]*radF, center[2]-
oldCenter[2]*radF, 0, 1)
end
struct NullInterpolator <: TopoPlots.Interpolator
end
function (ni::NullInterpolator)(
xrange::LinRange, yrange::LinRange,
positions::AbstractVector{<: Point{2}}, data::AbstractVector{<:Number})
return zeros(length(xrange),length(yrange))
end
function posToColor(pos)
cx = 0.5 - pos[1]
cy = 0.5 - pos[2]
rx = cx * 0.7071068 + cy * 0.7071068
ry = cx * -0.7071068 + cy * 0.7071068
b = 1.0 - (2*sqrt(cx^2+cy^2))^2
return RGB(0.5 - rx*1.414, 0.5 - ry*1.414, b)
end
This is the main function
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700))
# interaction
xs = range(-0.3, length=size(dat_e, 2), step=1 ./ 128)
sg = SliderGrid(f[4, 1:2],
(label="time", range=xs, format = "{:.3f} ms", startvalue = 0),
)
time = sg.sliders[1].value
str = lift(t -> "[$(round(t, digits = 3)) ms]", time)
topo_slice = lift((t, data) -> mean(data[1:30, indexin(t, xs), :], dims=2)[:,1], time, dat_e)
# butterfly plot
ax = Axis(f[2:3, 1:2], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]")
N = 1:length(pos) #1:4
hidespines!(ax, :t, :r)
GLMakie.xlims!(-0.3, 1.2)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
times = range(-0.3, length=size(dat_e,2), step=1 ./ 128)
specialColors = ColorScheme(vcat(RGB(1,1,1.),[posToColor(pos) for pos in pos[N]]...))
for i in N
mean_trial = mean(dat_e[i,:,:], dims=2)[:,1]
lines!(times, mean_trial, color = specialColors[i])
end
hidedecorations!(ax, label = false, ticks = false, ticklabels = false)
# text
vlines!(time, color = :red, linewidth = 1)
text!(time, 8, text = str, align = (:center, :center))
# topoplot
topo_axis = Axis(f[1, 1:2], width = 178, height = 178, aspect = DataAspect())
Makie.xlims!(low = -0.2, high = 1.2)
Makie.ylims!(low = -0.2, high = 1.2)
topoMatrix = eegHeadMatrix(pos[N], (0.5, 0.5), 0.5)
topo = eeg_topoplot!(topo_axis, topo_slice, # averaging all trial of 30 participants on Xth msec
raw.ch_names[1:30];
positions=pos, # produced automatically from ch_names
#interpolation=DelaunayMesh(),
enlarge=1,
extrapolation=GeomExtrapolation(enlarge=1.0, geometry=Circle),
label_text=false)
hidedecorations!(current_axis())
hidespines!(current_axis())
f

Does Makie have linked brushing capability similar to Holoviews?

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

Flow chart using R

I've been struggling the whole day with creating a flow chart to represent some patients we included in a study.
I already have a rough version ready in a Power Point presentation, depicting what kind of arrangement I'm looking for.
Now, I've got all my boxes ready, but what I need is the same alignment and connection to the arrows as in the picture attached. I have tried to somewhat copy and paste the guide on this page https://cran.r-project.org/web/packages/Gmisc/vignettes/Grid-based_flowcharts.html, but now I'm stuck. Since I have little expertise using R and only work with it occasionally, there might be something easy you might see, that I don't.
Here's my code:
install.packages("Gmisc")
library(Gmisc, quietly = TRUE)
library(glue)
library(htmlTable)
library(grid)
library(magrittr)
org_cohort <- boxGrob(glue("Patients with pancreatic cancer admitted to the University Clinic of Essen",
"from 01/2002 to 08/2020",
"n = {pop}",
pop = txtInt(909),
.sep = "\n"))
included <- boxGrob(glue("Patients with genetic sequencing and survival data",
"n = {incl}",
incl = txtInt(412),
.sep = "\n"))
grp_a <- boxGrob(glue("Patients treated with FOLFIRINOX or Gemcitabine / nab-Paclitaxel",
"n = {recr}",
recr = txtInt(179),
.sep = "\n"))
grp_b <- boxGrob(glue("Patients with genetic sequencing data via MAPK-TRON panel",
"n = {recr}",
recr = txtInt(185),
.sep = "\n"))
excluded_1 <- boxGrob(glue("Excluded (n = {tot}):",
" - No survival data: {NoSurv}",
" - No MAPK-Tron panel and early available abdominal CT-scan: {NoMAPKCT}",
tot = 506,
NoSurv = 300,
NoMAPKCT = 206,
.sep = "\n"),
just = "left")
excluded_2 <- boxGrob(glue("Excluded (n = {NoFGP}):",
" - No FOLFIRINOX or Gemcitabine / nab-Paclitaxel as 1st line: {NoFGP}",
NoFGP = 233,
.sep = "\n"),
just = "left")
excluded_3 <- boxGrob(glue("Excluded (n = {NoMAPK}):",
" - No sequencing data available: {NoMAPK}",
NoMAPK = 227,
.sep = "\n"),
just = "left")
grid.newpage()
vert <- spreadVertical(org_cohort = org_cohort,
included = included,
grps = grp_a)
grps <- alignVertical(reference = vert$grp_a,
grp_a, grp_b) %>%
spreadHorizontal()
vert$grps <- NULL
excluded_1 <- moveBox(excluded_1,
x = .8,
y = coords(vert$included)$top + distance(vert$included, vert$org_cohort, half = TRUE, center = FALSE))
excluded_2 <- moveBox(excluded_2,
x = .8,
y = coords(vert$grp_a)$top + distance(vert$included, vert$grp_a, half = TRUE, center = FALSE))
excluded_3 <- moveBox(excluded_3,
x = .8,
y = coords(vert$grp_b)$bottom + distance(vert$included, vert$grp_b, half = TRUE, center = FALSE))
## already facing problems here: R gives me the following error message: Error in coords(vert$grp_a/b) :
#Assertion on 'box' failed: Must inherit from class 'box', but has class 'NULL'..
for (i in 1:(length(vert) - 1)) {
connectGrob(vert[[i]], vert[[i + 1]], type = "vert") %>%
print
}
connectGrob(vert$included, grps[[1]], type = "N")
connectGrob(vert$included, grps[[2]], type = "N")
connectGrob(vert$included, excluded_1, type = "L")
connectGrob(vert$grp_a, excluded_2, type = "L")
# Print boxes
vert
grps
excluded_1
excluded_2
excluded_3
I'll be honest: I don't really get the code after the "grid.newpage()" thing. Therefore I'm constantly trying something to understand what the components of the code actually do, but every time I think I understood how it works, another setback is waiting for me around the corner.
R basically gives me a plot with arrows and boxes all over the place, but not the way I want them to look like. Then sometimes my boxes are even too large or something? Especially the boxes of the two subgroups at the end of the chart are cut-off oftentimes...
Do you have an idea how to "force" R replicating that kind of chart (see picture) for me?
Your help is extremely appreciated and would bring me a step closer to finally finish my thesis...!
Thank you in advance!!
Here is something to get your started with DiagrammeR.
Use splines = ortho to get 90 degree angles and straight lines.
Add line breaks with <br/> in the labels of nodes.
Use blank nodes to get branches for exclusion boxes. Then use rank
to get the hidden blank nodes to line up with exclusion boxes.
Hope this is helpful.
library(DiagrammeR)
grViz(
"digraph my_flowchart {
graph[splines = ortho]
node [fontname = Helvetica, shape = box, width = 4, height = 1]
node1[label = <Pancreatic cancer patients treated at our center<br/>diagnosed 2002-2020<br/>(n = 909)>]
node2[label = <Patients with MAPK-TRON panel and/or<br/>early available abdominal CT scan (n = 412)>]
blank1[label = '', width = 0.01, height = 0.01]
excluded1[label = <Exclusion of patients without<br/>(1) MARK-TRON panel and early available abdominal CT scan, and<br/>(2) survival data<br/>(n = 506)>]
node1 -> blank1[dir = none];
blank1 -> excluded1[minlen = 2];
blank1 -> node2;
{ rank = same; blank1 excluded1 }
node3[label = <FOLFIRINOX or Gemcitabine/nab-Paclitaxel as first CTx<br/>(n = 179)>]
node4[label = <Patients with MAPK-TRON panel regardless of CT scans<br/>(n = 185)>]
blank2[label = '', width = 0.01, height = 0.01]
excluded2[label = <Exclusion of patients that did not receive<br/>FOLFIRINOX or Gemcitabine/nab Paclitaxel as first CTx<br/>(n = 233)>]
blank3[label = '', width = 0.01, height = 0.01]
excluded3[label = <Exclusion of patients without MAPK-TRON panel<br/>(n = 227)>]
node2 -> blank2[dir = none];
node2 -> blank3[dir = none];
blank2 -> excluded2[minlen = 2];
blank3 -> excluded3[minlen = 2];
blank2 -> node3;
blank3 -> node4;
{ rank = same; blank2 excluded2 blank3 excluded3 }
}"
)
Diagram

'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")

Resources