Skip to content

Instantly share code, notes, and snippets.

@Vindaar
Last active May 29, 2024 15:34
Show Gist options
  • Save Vindaar/9c32c0676ffddec9078e4c0917861fcd to your computer and use it in GitHub Desktop.
Save Vindaar/9c32c0676ffddec9078e4c0917861fcd to your computer and use it in GitHub Desktop.
Raster plots for neuroscience in ggplotnim

Creating a neural spike plot in ggplotnim

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).

@Vindaar
Copy link
Author

Vindaar commented Apr 1, 2020

spike_raster

@Vindaar
Copy link
Author

Vindaar commented Apr 1, 2020

spike_raster_manual_color

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment