NOTE: once PR #59 is merged, the two examples below will be part of the recipes. Currently here: https://github.com/Vindaar/ggplotnim/blob/arraymancerBackend/recipes.org#creating-a-neural-spike-plot-in-ggplotnim
I’m not sure if this is what you had in mind, but I googled and found this:
https://pythontic.com/visualization/charts/spikerasterplot
which is easy to do in ggplotnim
using geom_linerange
.
I’ll show two ways to do it. One “elegant” way (in terms of what’s considered typical usage of ggplot) and one rather weird way, which allows to use custom color codes.
The first version relies on creating a long format data frame, with one column for spike numbers, one for the time axis, containing when a neuron spiked and finally a line size column for (what I assume is) the amplitude of the spike.
# first start with auto selection of colors
import ggplotnim, sequtils
const numx = 50
const numy = 8
const lineSizes = [0.4, 0.3, 0.2, 0.8, 0.5, 0.6, 0.7, 0.9]
# NOTE: The creation of the data here could surely be done in a nicer
# way...
var spikes = newSeq[float]()
var sizes = newSeq[float]()
for y in 0 ..< numy:
for x in 0 ..< numx:
spikes.add y.float
sizes.add lineSizes[y]
var df = newDataFrame()
df["spikes"] = toColumn spikes
df["neurons"] = toColumn randomTensor(numx * numy, 1.0)
df["lineSize"] = toColumn sizes
ggplot(df, aes("neurons", "spikes", color = "lineSize")) +
geom_linerange(aes(ymin = f{c"spikes" - c"lineSize" / 2.0},
ymax = f{c"spikes" + c"lineSize" / 2.0})) +
scale_y_continuous() + # make sure y is considered cont.
ylim(-1, 8) + # at the moment ymin, ymax are not considered for the plot range (that's a bug)
ggtitle("Spike raster plot") +
ggsave("spike_raster.pdf")
This gives us the plot below (see the first reply to this gist).
In constrast this version only has a data frame with one column for each neuron containing the times when they spiked. The spike number, line size and color are all constant for each neuron.
import ggplotnim, sequtils
const numx = 50
const numy = 8
const lineSizes = [0.4, 0.3, 0.2, 0.8, 0.5, 0.6, 0.7, 0.9]
# alternatively using fixed colors and one geom_linerange for each color
let colorCodes = @[color(0, 0, 0),
color(1, 0, 0),
color(0, 1, 0),
color(0, 0, 1),
color(1 , 1, 0),
color(1, 0, 1),
color(0, 1, 1),
color(1, 0, 1)]
var df = newDataFrame()
for nr in 0 ..< numy:
df["neuron " & $nr] = toColumn randomTensor(numx, 1.0)
var plt = ggplot(df)
for nr in 0 ..< numy:
# could combine with above loop, but for clarity
plt = plt + geom_linerange(aes(x = ("neuron " & $nr),
y = f{nr},
ymin = f{nr.float - lineSizes[nr] / 2.0},
ymax = f{nr.float + lineSizes[nr] / 2.0}),
color = some(colorCodes[nr]))
# finally add scales, title and plot
plt + scale_y_continuous() + # make sure y is considered cont.
ylim(-1, 8) + # at the moment ymin, ymax are not considered for the plot range (that's a bug)
xlab("Neurons") +
ylab("Spikes") +
ggtitle("Spike raster plot, manual colors") +
ggsave("spike_raster_manual_color.pdf")
This results in the plot below (second reply).