From 466552e8aa91b802fc821d409a1856a515aa2c06 Mon Sep 17 00:00:00 2001 From: agchesebro <76024790+agchesebro@users.noreply.github.com> Date: Fri, 4 Oct 2024 02:24:32 -0400 Subject: [PATCH] PING tutorial - GraphDynamics version (#428) * Initial cleanup to switch to GraphDynamics * Need connection rule for PING network Don't know how I overlooked this earlier * Need access to abstract type * Oops * Never mind I'm dumb * Big oops * Ok it mostly does the figure Had to tweak some parameters to get the dynamics working but what else is new in papers not replicating exactly * Fix code per Mason's comment Also start adding some of the Markdown formatting * Everything except illustrations are done * Final (for now) tutorial * Oops the sequel (more docs I should've read) * Update docs/src/tutorials/ping_tutorial/ping_network_tutorial.jl Also yes I'm still dumb Co-authored-by: Mason Protter * Fix paths and illustration locations * Oops typo * Plot in single image with 2 panels * Fix plots * Update to rasterplot to give custom titles * Redo example images * Supress outputs and remove result .png * Cleanup imports --------- Co-authored-by: Mason Protter --- docs/src/assets/basic_ping_illustration.png | Bin 0 -> 67853 bytes docs/src/tutorials/ping_network_tutorial.jl | 122 ++++++++++++++++++++ ext/MakieExtension.jl | 4 +- src/Neuroblox.jl | 2 + src/blox/connections.jl | 2 +- src/blox/ping_neuron_examples.jl | 4 +- test/ping_network_tutorial.jl | 55 --------- 7 files changed, 130 insertions(+), 59 deletions(-) create mode 100644 docs/src/assets/basic_ping_illustration.png create mode 100644 docs/src/tutorials/ping_network_tutorial.jl delete mode 100644 test/ping_network_tutorial.jl diff --git a/docs/src/assets/basic_ping_illustration.png b/docs/src/assets/basic_ping_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..43391c949da73b62166186010e965c19f7423a6d GIT binary patch literal 67853 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 A5C8xG literal 0 HcmV?d00001 diff --git a/docs/src/tutorials/ping_network_tutorial.jl b/docs/src/tutorials/ping_network_tutorial.jl new file mode 100644 index 00000000..cbf6e1f0 --- /dev/null +++ b/docs/src/tutorials/ping_network_tutorial.jl @@ -0,0 +1,122 @@ +# # Introduction + +# This tutorial provides a simple example of how to use the Neuroblox package to simulate a pyramidal-interneuron gamma (PING) network. +# These networks are generally useful in modeling cortical oscillations and are used in a variety of contexts. +# This particular example is based on Börgers, Epstein, and Kopell [1] and is a simple example of how to replicate their initial network in Neuroblox. + +# ## PING network - conceptual definition +# The PING network is a simple model of a cortical network that consists of two populations of neurons: excitatory and inhibitory. +# We omit the detailed equations of the neurons here, but note they are Hodgkin-Huxley-like equations with a few modifications. +# Excitatory neurons are reduced Traub-Miles cells [2] and inhibitory neurons are Wang-Buzasaki cells [3]. +# Both follow Hodgkin-Huxley formalism, i.e., the membrane voltage is governed by the sum of the currents through the sodium, potassium, and leak channels, along with external drive, such that: +# ```math +# \begin{equation*} +# C \frac{dV}{dt} = g_{\text{Na}} m^3 h (V_{\text{Na}} - V) + g_\text{K} n^4 (V_\text{K} - V) + g_\text{L} (V_\text{L} - V) + I_{\text{ext}} +# \end{equation*} +# ``` +# For full details of the model, see Eq. 12-14 on p. 7 of the SI Appendix of Börgers et al. [1]. +# Here is a visual representation of the network structure and which neurons receive the driving input: +# ![PING network structure](../assets/basic_ping_illustration.png) + +# # Model setup +# This section sets up the model parameters and the network structure. The network consists of 200 neurons: 40 driven excitatory neurons, 120 other excitatory neurons, and 40 inhibitory neurons. +# The network is set up as a directed graph with excitatory neurons driving inhibitory neurons and vice versa, with self-inhibition but not self-excitation present. + +# ## Import the necessary packages +# Reasons for each non-Neuroblox package are given in the comments after each +using Neuroblox +using OrdinaryDiffEq ## to build the ODE problem and solve it, gain access to multiple solvers from this +using Distributions ## for statistical distributions +using Random ## for random number generation +using CairoMakie ## for plotting + +# ## Initialization +# Set the random seed to reproduce the plots as shown here exactly. If you want to probe how random variability changes the network, simply omit this line. +Random.seed!(42); + +# Setup the hyperparameters for the PING network simulation. The comments note where these parameters are taken from in the Börgers et al. paper [1] or +# if they were manually tuned for this particular simulation. +μ_E = 0.8 ## mean of the excitatory neurons' external current, manually tuned from the value on p. 8 of the Appendix +σ_E = 0.15 ## standard deviation of the excitatory neurons' external current, given on p. 8 of the Appendix +μ_I = 0.8 ## mean of the inhibitory neurons' external current, given on p. 9 of the Appendix +σ_I = 0.08 ## standard deviation of the inhibitory neurons' external current, given on p. 9 of the Appendix + +NE_driven = 40 ## number of driven excitatory neurons, given on p. 8 of the Appendix. Note all receive constant rather than half stochastic drives. +NE_other = 120 ## number of non-driven excitatory neurons, given in the Methods section +NI_driven = 40 ## number of inhibitory neurons (all driven), given in the Methods section +N_total = NE_driven + NE_other + NI_driven ## total number of neurons in the network + +N = N_total ## convenience redefinition to improve the readability of the connection weights +g_II = 0.2 ## inhibitory-inhibitory connection weight, given on p. 8 of the Appendix +g_IE = 0.6 ## inhibitory-excitatory connection weight, given on p. 8 of the Appendix +g_EI = 0.8; ## excitatory-inhibitory connection weight, manually tuned from values given on p. 8 of the Appendix + +# Finally, setup the driving currents. All neurons receive a base external current, and the inhibitory and driven excitatory populations receive a second external stimulus current. +# The undriven excitatory neurons receive a small addition to the base current in lieu of the stochastic current in the original implementation. +# There is also an external inhibitory bath for the inhibitory neurons - for the importance of this bath see the SI Appendix of Börgers et al. [1]. + +I_base = Normal(0, 0.1) ## base external current for all neurons +I_driveE = Normal(μ_E, σ_E) ## External current for driven excitatory neurons +I_driveI = Normal(μ_I, σ_I) ## External current for driven inhibitory neurons +I_undriven = Normal(0, 0.4) ## Additional noise current for undriven excitatory neurons. Manually tuned. +I_bath = -0.7; ## External inhibitory bath for inhibitory neurons - value from p. 11 of the SI Appendix + +# # Creating a network in Neuroblox +# Creating and running a network of neurons in Neuroblox consists of three steps: defining the neurons, defining the graph of connections between the neurons, and simulating the system represented by the graph. + +# ## Define the neurons +# The neurons from Börgers et al. [1] are implemented in Neuroblox as `PINGNeuronExci` and `PINGNeuronInhib`. We can specify their initial current drives and create the neurons as follows: + +exci_driven = [PINGNeuronExci(name=Symbol("ED$i"), I_ext=rand(I_driveE) + rand(I_base)) for i in 1:NE_driven] ## In-line loop to create the driven excitatory neurons, named ED1, ED2, etc. +exci_other = [PINGNeuronExci(name=Symbol("EO$i"), I_ext=rand(I_base) + rand(I_undriven)) for i in 1:NE_other] ## In-line loop to create the undriven excitatory neurons, named EO1, EO2, etc. +exci = [exci_driven; exci_other] ## Concatenate the driven and undriven excitatory neurons into a single vector for convenience +inhib = [PINGNeuronInhib(name=Symbol("ID$i"), I_ext=rand(I_driveI) + rand(I_base) + I_bath) for i in 1:NI_driven]; ## In-line loop to create the inhibitory neurons, named ID1, ID2, etc. + +# ## Define the graph of network connections +# This portion illustrates how we go about creating a network of neuronal connections. + +g = MetaDiGraph() ## Initialize the graph + +## Add the E -> I and I -> E connections +for ne ∈ exci + for ni ∈ inhib + add_edge!(g, ne => ni; weight=g_EI/N) + add_edge!(g, ni => ne; weight=g_IE/N) + end +end + +## Add the I -> I connections +for ni1 ∈ inhib + for ni2 ∈ inhib + add_edge!(g, ni1 => ni2; weight=g_II/N); + end +end + +# ## Simulate the network +# Now that we have the neurons and the graph, we can simulate the network. We use the `system_from_graph` function to create a system of ODEs from the graph and then solve it using the DifferentialEquations.jl package. + +tspan = (0.0, 300.0) ## Time span for the simulation - run for 300ms to match the Börgers et al. [1] Figure 1. +@named sys = system_from_graph(g, graphdynamics=true) ## Use GraphDynamics.jl otherwise this can be a very slow simulation +prob = ODEProblem(sys, [], tspan) ## Create the problem to solve +sol = solve(prob, Tsit5(), saveat=0.1); ## Solve the problem and save at 0.1ms resolution. + +# # Plotting the results +# Now that we have a whole simulation, let's plot the results and see how they line up with the original figures. We're looking to reproduce the dynamics shown in Figure 1 of Börgers et al. [1]. +# To create raster plots in Neuroblox for the excitatory and inhibitory populations, it is as simple as: + +fig = Figure() +rasterplot(fig[1,1], exci, sol; threshold=20.0, title="Excitatory Neurons") +rasterplot(fig[2,1], inhib, sol; threshold=20.0, title="Inhibitory Neurons") +fig + +# The upper panel should show the dynamics in Figure 1.C, with a clear population of excitatory neurons firing together from the external driving current, and the other excitatory neurons exhibiting more stochastic bursts. +# The lower panel should show the dynamics in Figure 1.A, with the inhibitory neurons firing in a more synchronous manner than the excitatory neurons. + +# # Conclusion +# And there you have it! A complete PING demonstration that reproduces the dynamics of a published paper in a matter of 30 seconds, give or take. Have fun making your own! + +# # References +# 1. Börgers C, Epstein S, Kopell NJ. Gamma oscillations mediate stimulus competition and attentional selection in a cortical network model. +# Proc Natl Acad Sci U S A. 2008 Nov 18;105(46):18023-8. DOI: [10.1073/pnas.0809511105](https://www.doi.org/10.1073/pnas.0809511105). +# 2. Traub, RD, Miles, R. Neuronal Networks of the Hippocampus. Cambridge University Press, Cambridge, UK, 1991. +# 3. Wang, X-J, Buzsáki, G. Gamma oscillation by synaptic inhibition in a hippocampal interneuronal network model. J. Neurosci., 16:6402–6413, 1996. diff --git a/ext/MakieExtension.jl b/ext/MakieExtension.jl index 4b5877ce..d26fb753 100644 --- a/ext/MakieExtension.jl +++ b/ext/MakieExtension.jl @@ -90,9 +90,10 @@ end Theme( color = :black, threshold = nothing, + title = "", Axis = ( xlabel = "Time (ms)", - ylabel = "Neurons", + ylabel = "Neurons" ) ) end @@ -108,6 +109,7 @@ function Makie.plot!(p::RasterPlot) ax = current_axis() ax.xlabel = p.Axis.xlabel[] ax.ylabel = p.Axis.ylabel[] + ax.title = p.title[] spikes = detect_spikes(blox, sol; threshold=threshold) spike_times, neuron_indices = findnz(spikes) diff --git a/src/Neuroblox.jl b/src/Neuroblox.jl index 41388fd4..dbbaa616 100644 --- a/src/Neuroblox.jl +++ b/src/Neuroblox.jl @@ -61,6 +61,8 @@ abstract type NeuralMassBlox <: AbstractBlox end abstract type CompositeBlox <: AbstractBlox end abstract type StimulusBlox <: AbstractBlox end abstract type ObserverBlox end # not AbstractBlox since it should not show up in the GUI +abstract type AbstractPINGNeuron <: AbstractNeuronBlox end + # we define these in neural_mass.jl # abstract type HarmonicOscillatorBlox <: NeuralMassBlox end diff --git a/src/blox/connections.jl b/src/blox/connections.jl index c3eb4c86..d7dc5307 100644 --- a/src/blox/connections.jl +++ b/src/blox/connections.jl @@ -993,4 +993,4 @@ function (bc::BloxConnector)( eq = sys_in.jcn ~ w*x accumulate_equation!(bc, eq) -end \ No newline at end of file +end diff --git a/src/blox/ping_neuron_examples.jl b/src/blox/ping_neuron_examples.jl index cb3f936e..b239aea2 100644 --- a/src/blox/ping_neuron_examples.jl +++ b/src/blox/ping_neuron_examples.jl @@ -28,7 +28,7 @@ struct PINGNeuronExci <: AbstractPINGNeuron a_m(v) = 0.32*(v+54.0)/(1.0 - exp(-(v+54.0)/4.0)) b_m(v) = 0.28*(v+27.0)/(exp((v+27.0)/5.0) - 1.0) a_n(v) = 0.032*(v+52.0)/(1.0 - exp(-(v+52.0)/5.0)) - b_n(v) = 0.5*exp((v+57.0)/40.0) + b_n(v) = 0.5*exp(-(v+57.0)/40.0) a_h(v) = 0.128*exp((v+50.0)/18.0) b_h(v) = 4.0/(1.0 + exp(-(v+27.0)/5.0)) @@ -75,7 +75,7 @@ struct PINGNeuronInhib <: AbstractPINGNeuron b_h(v) = 5.0/(1.0 + exp(-(v+28.0)/10.0)) m∞(v) = a_m(v)/(a_m(v) + b_m(v)) - eqs = [D(V) ~ g_Na*m∞(V)^3*h*(V_Na - V) + g_K*(n^4)*(V_K - V) + g_L*(V_L - V) + I_ext, + eqs = [D(V) ~ g_Na*m∞(V)^3*h*(V_Na - V) + g_K*(n^4)*(V_K - V) + g_L*(V_L - V) + I_ext + jcn, D(n) ~ (a_n(V)*(1.0 - n) - b_n(V)*n), D(h) ~ (a_h(V)*(1.0 - h) - b_h(V)*h), D(s) ~ ((1+tanh(V/10.0))/2.0)*((1.0 - s)/τ_R) - s/τ_D diff --git a/test/ping_network_tutorial.jl b/test/ping_network_tutorial.jl deleted file mode 100644 index a5d28313..00000000 --- a/test/ping_network_tutorial.jl +++ /dev/null @@ -1,55 +0,0 @@ -using Neuroblox, DifferentialEquations, Distributions, Graphs, MetaGraphs, Random - -# First focus is on producing panels from Figure 1 of the PING network paper. - -# Setup parameters from the supplemental material -μ_E = 1.5 -σ_E = 0.15 -μ_I = 0.8 -σ_I = 0.08 - -# Define the PING network neuron numbers -NE_driven = 2 -NE_other = 14 -NI_driven = 4 -N_total = NE_driven + NE_other + NI_driven - -# First, create the 20 driven excitatory neurons -exci_driven = [PINGNeuronExci(name=Symbol("ED$i"), I_ext=rand(Normal(μ_I, σ_I))) for i in 1:NE_driven] -exci_other = [PINGNeuronExci(name=Symbol("EO$i")) for i in 1:NE_other] -inhib = [PINGNeuronInhib(name=Symbol("ID$i"), I_ext=rand(Normal(μ_I, σ_I))) for i in 1:NI_driven] - -# Create the network -g = MetaDiGraph() -add_blox!.(Ref(g), vcat(exci_driven, exci_other, inhib)) - -# Extra parameters -p = @parameters N=N_total g_II=0.2 g_IE=0.6 g_EI=0.6 - -for i = 1:NE_driven+NE_other - for j = NE_driven+NE_other+1:N_total - add_edge!(g, i, j, Dict(:weight => g_EI/N)) - add_edge!(g, j, i, Dict(:weight => g_IE/N)) - end -end - -for i = NE_driven+NE_other+1:N_total - for j = NE_driven+NE_other+1:N_total - add_edge!(g, i, j, Dict(:weight => g_II/N)) - end -end - -@named sys = system_from_graph(g, p) -sys = structural_simplify(sys) -prob = ODEProblem(sys, [], (0.0, 20.0)) -@time sol = solve(prob, Tsit5(), saveat=0.1) - -using Peaks, Plots - -exci_voltages = reduce(hcat, ModelingToolkit.getu(sol, vcat([Symbol("ED$i"*"₊V") for i in 1:NE_driven], [Symbol("EO$i"*"₊V") for i in 1:NE_other]))(sol))' -inhib_voltages = reduce(hcat, ModelingToolkit.getu(sol, [Symbol("ID$i"*"₊V") for i in 1:NI_driven])(sol))' - -plot(exci_voltages) -plot(inhib_voltages) - -maxima(inhib_voltages[:, 1]) \ No newline at end of file