From caebae3f093afa1921ea9e668c103ba2ddd6003e Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:03:20 +0300 Subject: [PATCH 01/15] split voltage getter and NaN filter function --- src/blox/blox_utilities.jl | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 24d46ad8..35556883 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -369,42 +369,40 @@ to_vector(v) = [v] nanmean(x) = mean(filter(!isnan,x)) -function voltage_timeseries(sol::SciMLBase.AbstractSolution, blox::AbstractNeuronBlox) +function replace_refractory!(V, blox::Union{LIFExciNeuron, LIFInhNeuron}, sol::SciMLBase.AbstractSolution) namespaced_name = string(namespaceof(blox), nameof(blox)) - state_name = Symbol(namespaced_name, "₊V") + reset_param_name = Symbol(namespaced_name, "₊V_reset") + p = only(@parameters $(reset_param_name)) - s = only(@variables $(state_name)(t)) + get_reset = getp(sol, p) + reset_value = get_reset(sol) - return sol[s] + V[V .== reset_value] .= NaN + + return V end -function voltage_timeseries(sol::SciMLBase.AbstractSolution, blox::Union{LIFExciNeuron, LIFInhNeuron}) +replace_refractory!(V, blox, sol::SciMLBase.AbstractSolution) = V + +function voltage_timeseries(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution; nan_refractory=false) namespaced_name = namespaced_nameof(blox) state_name = Symbol(namespaced_name, "₊V") - reset_param_name = Symbol(namespaced_name, "₊V_reset") - s = only(@variables $(state_name)(t)) - p = only(@parameters $(reset_param_name)) - - get_reset = getp(sol, p) - reset_value = get_reset(sol) - V = sol[s] - - V[V .== reset_value] .= NaN - return V + return sol[s] end -function voltage_timeseries(sol::SciMLBase.AbstractSolution, cb::CompositeBlox) +function voltage_timeseries(cb::CompositeBlox, sol::SciMLBase.AbstractSolution) return mapreduce(hcat, get_neurons(cb)) do neuron - voltage_timeseries(sol, neuron) + voltage_timeseries(neuron, sol) end end -function average_voltage_timeseries(sol::SciMLBase.AbstractSolution, cb::CompositeBlox) - V = voltage_timeseries(sol, cb) +function meanfield_timeseries(cb::CompositeBlox, sol::SciMLBase.AbstractSolution) + V = voltage_timeseries(cb, sol) + replace_refractory!(V, cb, sol) return vec(mapslices(nanmean, V; dims = 2)) end From 044cdfbf0a6b72b35da849359cb19fa4349ca556 Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:03:41 +0300 Subject: [PATCH 02/15] update Project.toml --- Project.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 680e1e4c..a90450d9 100644 --- a/Project.toml +++ b/Project.toml @@ -28,7 +28,6 @@ LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" MAT = "23992714-dd62-5051-b70f-ba57cb901cac" MKL = "33e6dc65-8f57-5167-99aa-e5a354878fb2" MLJ = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7" -MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b" MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" ModelingToolkitStandardLibrary = "16a59e39-deab-5bd0-87e4-056b12336739" @@ -44,6 +43,7 @@ Peaks = "18e31ff7-3703-566c-8e60-38913d67486b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +Requires = "ae029012-a4dd-5104-9daa-d747884805df" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -60,6 +60,12 @@ ToeplitzMatrices = "c751599d-da0a-543b-9d20-d0a503d91d24" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Turing = "fce5fe82-541a-59a6-adf8-730c64b5f9a0" +[weakdeps] +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + +[extensions] +MakieExtension = "Makie" + [compat] AbstractFFTs = "1" Combinatorics = "1" @@ -110,6 +116,7 @@ Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MAT = "23992714-dd62-5051-b70f-ba57cb901cac" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Optim = "429524aa-4258-5aef-a3af-852621145aeb" Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba" OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e" From 08050f7d7645a57293058f1d8445c4289eb43eac Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:03:56 +0300 Subject: [PATCH 03/15] remove old recipes folder --- src/plot_recipes/composite_recipes.jl | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/plot_recipes/composite_recipes.jl diff --git a/src/plot_recipes/composite_recipes.jl b/src/plot_recipes/composite_recipes.jl deleted file mode 100644 index c2d97a3c..00000000 --- a/src/plot_recipes/composite_recipes.jl +++ /dev/null @@ -1,5 +0,0 @@ -function MakieCore.convert_arguments(::MakieCore.PointBased, sol::SciMLBase.AbstractSolution, cb::CompositeBlox) - V = average_voltage_timeseries(sol, cb) - - return (sol.t, vec(V)) -end \ No newline at end of file From 705db078763eaed6cca4da376b5327c6deb54f3d Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:04:16 +0300 Subject: [PATCH 04/15] add spike detection --- src/blox/blox_utilities.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 35556883..59b955a0 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -406,3 +406,29 @@ function meanfield_timeseries(cb::CompositeBlox, sol::SciMLBase.AbstractSolution return vec(mapslices(nanmean, V; dims = 2)) end + +function detect_spikes(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution) + namespaced_name = namespaced_nameof(blox) + reset_param_name = Symbol(namespaced_name, "₊V_reset") + threshold_param_name = Symbol(namespaced_name, "₊θ") + + reset = only(@parameters $(reset_param_name)) + thrs = only(@parameters $(threshold_param_name)) + + get_reset = getp(sol, reset) + reset_value = get_reset(sol) + + get_thrs = getp(sol, thrs) + thrs_value = get_thrs(sol) + + V = voltage_timeseries(blox, sol) + + spike_idxs = Int[] + for (i, vi) in enumerate(V[1:end-1]) + if (abs(vi - thrs_value) <= 1e-3) && (abs(V[i+1] - reset_value) <= 1e-3) + push!(spike_idxs, i) + end + end + + return spike_idxs +end From 7218d0f94db659b107f7a17e2494c6c2690d3080 Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:05:03 +0300 Subject: [PATCH 05/15] update tests --- test/utils.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/utils.jl b/test/utils.jl index 1a212295..9af46e97 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -14,7 +14,7 @@ using Statistics prob = ODEProblem(ss, [], (0, 200.0)) sol = solve(prob, Tsit5()) - @test all(sol[ss.n.V] .== Neuroblox.voltage_timeseries(sol, n)) + @test all(sol[ss.n.V] .== Neuroblox.voltage_timeseries(n, sol)) end @testset "Voltage timeseries + Composite average [LIFExciCircuitBloxz]" begin @@ -40,12 +40,12 @@ end V = hcat(sol[ss.n.neuron1.V], sol[ss.n.neuron2.V], sol[ss.n.neuron3.V]) V[V .== V_reset] .= NaN - @test all(isequal(V, Neuroblox.voltage_timeseries(sol, n))) + @test all(isequal(V, Neuroblox.voltage_timeseries(n, sol))) V_filtered = map(eachrow(V)) do V_t v = filter(!isnan, V_t) mean(v) end - @test all(isequal(V_filtered, Neuroblox.average_voltage_timeseries(sol, n))) + @test all(isequal(V_filtered, Neuroblox.meanfield_timeseries(n, sol))) end From 0bad72f87dfb45789d450a5fce6b0236d607932b Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:05:17 +0300 Subject: [PATCH 06/15] add Makie extension --- ext/MakieExtension.jl | 56 +++++++++++++++++++++++++++++++++++++++++++ src/Neuroblox.jl | 20 +++++++++++++--- 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 ext/MakieExtension.jl diff --git a/ext/MakieExtension.jl b/ext/MakieExtension.jl new file mode 100644 index 00000000..06b9397d --- /dev/null +++ b/ext/MakieExtension.jl @@ -0,0 +1,56 @@ +module MakieExtension + +isdefined(Base, :get_extension) ? using Makie : using ..Makie + +using Neuroblox +using Neuroblox: CompositeBlox, meanfield_timeseries, detect_spikes, get_neurons +using SciMLBase: AbstractSolution + +import Neuroblox: meanfield, meanfield!, rasterplot, rasterplot! + +function Makie.convert_arguments(::Makie.PointBased, cb::CompositeBlox, sol::AbstractSolution) + V = meanfield_timeseries(cb, sol) + + return (sol.t, vec(V)) +end + +@recipe(MeanField, blox, sol) do scene + Theme() +end + +argument_names(::Type{<: MeanField}) = (:blox, :sol) + +function Makie.plot!(p::MeanField) + sol = p.sol[] + blox = p.blox[] + + V = meanfield_timeseries(blox, sol) + + lines!(p, sol.t, vec(V)) + + return p +end + +@recipe(RasterPlot, blox, sol) do scene + Theme( + color = :black + ) +end + +argument_names(::Type{<: RasterPlot}) = (:blox, :sol) + +function Makie.plot!(p::RasterPlot) + sol = p.sol[] + t = sol.t + blox = p.blox[] + neurons = get_neurons(blox) + + for (i, n) in enumerate(neurons) + spike_idxs = detect_spikes(n, sol) + scatter!(p, t[spike_idxs], fill(i, length(spike_idxs)); color=p.color[]) + end + + return p +end + +end \ No newline at end of file diff --git a/src/Neuroblox.jl b/src/Neuroblox.jl index 0f0495bf..fd89a5f7 100644 --- a/src/Neuroblox.jl +++ b/src/Neuroblox.jl @@ -1,5 +1,9 @@ module Neuroblox +if !isdefined(Base, :get_extension) + using Requires +end + using Reexport @reexport using ModelingToolkit const t = ModelingToolkit.t_nounits @@ -53,8 +57,6 @@ using Peaks: argmaxima, peakproms!, peakheights! using LogExpFunctions: logistic -using MakieCore - # define abstract types for Neuroblox abstract type AbstractBlox end # Blox is the abstract type for Blox that are displayed in the GUI abstract type AbstractComponent end @@ -119,7 +121,6 @@ include("gui/GUI.jl") include("blox/connections.jl") include("blox/blox_utilities.jl") include("Neurographs.jl") -include("./plot_recipes/composite_recipes.jl") function simulate(sys::ODESystem, u0, timespan, p, solver = AutoVern7(Rodas4()); kwargs...) prob = ODEProblem(sys, u0, timespan, p) @@ -186,10 +187,22 @@ https://github.com/Neuroblox/NeurobloxIssues. """) end +function meanfield end +function meanfield! end + +function rasterplot end +function rasterplot! end + function __init__() #if Preferences.@load_preference("PrintLicense", true) print_license() #end + + @static if !isdefined(Base, :get_extension) + @require Makie="ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" begin + include("../ext/MakieExtension.jl") + end + end end export JansenRitSPM12, next_generation, qif_neuron, if_neuron, hh_neuron_excitatory, @@ -219,5 +232,6 @@ export run_experiment!, run_trial! export addnontunableparams export get_weights, get_dynamic_states, get_idx_tagged_vars, get_eqidx_tagged_vars export BalloonModel,LeadField, boldsignal_endo_balloon +export meanfield, meanfield!, rasterplot, rasterplot! end From 32ede9ea62f05209e9a8e8c9fec0ef005719130b Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 18:11:04 +0300 Subject: [PATCH 07/15] remove old recipe --- ext/MakieExtension.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ext/MakieExtension.jl b/ext/MakieExtension.jl index 06b9397d..0219d59b 100644 --- a/ext/MakieExtension.jl +++ b/ext/MakieExtension.jl @@ -8,12 +8,6 @@ using SciMLBase: AbstractSolution import Neuroblox: meanfield, meanfield!, rasterplot, rasterplot! -function Makie.convert_arguments(::Makie.PointBased, cb::CompositeBlox, sol::AbstractSolution) - V = meanfield_timeseries(cb, sol) - - return (sol.t, vec(V)) -end - @recipe(MeanField, blox, sol) do scene Theme() end From d8e6692a03fe895c565d9789c2915256eee2a252 Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 19:17:14 +0300 Subject: [PATCH 08/15] fix namespaced name --- src/blox/blox_utilities.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 59b955a0..744652b4 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -370,7 +370,7 @@ to_vector(v) = [v] nanmean(x) = mean(filter(!isnan,x)) function replace_refractory!(V, blox::Union{LIFExciNeuron, LIFInhNeuron}, sol::SciMLBase.AbstractSolution) - namespaced_name = string(namespaceof(blox), nameof(blox)) + namespaced_name = namespaced_nameof(blox) reset_param_name = Symbol(namespaced_name, "₊V_reset") p = only(@parameters $(reset_param_name)) From 8ed4dc12ee9627f3703d433e45473fe6712244c4 Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 19:17:40 +0300 Subject: [PATCH 09/15] add `replace_refractory` dispatch for CompositeBlox --- src/blox/blox_utilities.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 744652b4..2210d4f3 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -382,6 +382,14 @@ function replace_refractory!(V, blox::Union{LIFExciNeuron, LIFInhNeuron}, sol::S return V end +function replace_refractory!(V, blox::CompositeBlox, sol::SciMLBase.AbstractSolution) + neurons = get_neurons(blox) + + for (i, n) in enumerate(neurons) + V[:, i] = replace_refractory!(V[:,i], n, sol) + end +end + replace_refractory!(V, blox, sol::SciMLBase.AbstractSolution) = V function voltage_timeseries(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution; nan_refractory=false) From 7518b15551934db8693ed8f0828cd040d83f3a11 Mon Sep 17 00:00:00 2001 From: Haris Orgn Date: Wed, 4 Sep 2024 20:32:02 +0300 Subject: [PATCH 10/15] fix tests --- test/utils.jl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/test/utils.jl b/test/utils.jl index 9af46e97..bab0e860 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -21,27 +21,29 @@ end global_ns = :g tspan = (0, 200) V_reset = -55 - + @named s = PoissonSpikeTrain(3, tspan; namespace = global_ns) @named n = LIFExciCircuitBlox(; V_reset, namespace = global_ns, N_neurons = 3, weight=1) - + neurons = [s, n] - + g = MetaDiGraph() add_blox!.(Ref(g), neurons) - + add_edge!(g, 1, 2, Dict(:weight => 1)) - + sys = system_from_graph(g; name = global_ns) ss = structural_simplify(sys) prob = ODEProblem(ss, [], (0, 200.0)) sol = solve(prob, Tsit5()) - + V = hcat(sol[ss.n.neuron1.V], sol[ss.n.neuron2.V], sol[ss.n.neuron3.V]) V[V .== V_reset] .= NaN - - @test all(isequal(V, Neuroblox.voltage_timeseries(n, sol))) - + + V_nb = Neuroblox.voltage_timeseries(n, sol) + Neuroblox.replace_refractory!(V_nb, n, sol) + @test all(isequal(V, V_nb)) + V_filtered = map(eachrow(V)) do V_t v = filter(!isnan, V_t) mean(v) @@ -49,3 +51,4 @@ end @test all(isequal(V_filtered, Neuroblox.meanfield_timeseries(n, sol))) end + From 3341909c14eee4bc3ab88e64715c7f36257d0dfa Mon Sep 17 00:00:00 2001 From: harisorgn Date: Thu, 5 Sep 2024 20:32:51 +0300 Subject: [PATCH 11/15] add stackplot recipe and its figure making function --- ext/MakieExtension.jl | 47 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/ext/MakieExtension.jl b/ext/MakieExtension.jl index 0219d59b..feec904e 100644 --- a/ext/MakieExtension.jl +++ b/ext/MakieExtension.jl @@ -3,10 +3,11 @@ module MakieExtension isdefined(Base, :get_extension) ? using Makie : using ..Makie using Neuroblox -using Neuroblox: CompositeBlox, meanfield_timeseries, detect_spikes, get_neurons +using Neuroblox: AbstractNeuronBlox, CompositeBlox +using Neuroblox: meanfield_timeseries, voltage_timeseries, detect_spikes, get_neurons using SciMLBase: AbstractSolution -import Neuroblox: meanfield, meanfield!, rasterplot, rasterplot! +import Neuroblox: meanfield, meanfield!, rasterplot, rasterplot!, stackplot, stackplot!, voltage_stack @recipe(MeanField, blox, sol) do scene Theme() @@ -47,4 +48,46 @@ function Makie.plot!(p::RasterPlot) return p end +@recipe(StackPlot, blox, sol) do scene + Theme( + color = :black + ) +end + +argument_names(::Type{<: StackPlot}) = (:blox, :sol) + +function Makie.plot!(p::StackPlot) + sol = p.sol[] + blox = p.blox[] + + V = voltage_timeseries(blox, sol) + + offset = 20 + for (i,V_neuron) in enumerate(eachcol(V)) + lines!(p, sol.t, (i-1)*offset .+ V_neuron; color=p.color[]) + end + + return p +end + +function Makie.convert_arguments(::Makie.PointBased, blox::AbstractNeuronBlox, sol::AbstractSolution) + V = voltage_timeseries(blox, sol) + + return (sol.t, V) +end + +function voltage_stack(blox::CompositeBlox, sol::AbstractSolution; N_neurons=10, fontsize=8, color=:black) + neurons = get_neurons(blox) + N_ax = min(length(neurons), N_neurons) + + fig = Figure() + ax = Axis(fig[1,1], xlabel="Time", ylabel="Neurons") + + hideydecorations!(ax) + + stackplot!(ax, blox, sol) + + display(fig) +end + end \ No newline at end of file From 6a6a6472266c5fdb6ea4b4e72f5078a035fb9e57 Mon Sep 17 00:00:00 2001 From: harisorgn Date: Thu, 5 Sep 2024 20:33:03 +0300 Subject: [PATCH 12/15] export new recipes --- src/Neuroblox.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Neuroblox.jl b/src/Neuroblox.jl index fd89a5f7..f8457f8e 100644 --- a/src/Neuroblox.jl +++ b/src/Neuroblox.jl @@ -193,6 +193,11 @@ function meanfield! end function rasterplot end function rasterplot! end +function stackplot end +function stackplot! end + +function voltage_stack end + function __init__() #if Preferences.@load_preference("PrintLicense", true) print_license() @@ -232,6 +237,6 @@ export run_experiment!, run_trial! export addnontunableparams export get_weights, get_dynamic_states, get_idx_tagged_vars, get_eqidx_tagged_vars export BalloonModel,LeadField, boldsignal_endo_balloon -export meanfield, meanfield!, rasterplot, rasterplot! +export meanfield, meanfield!, rasterplot, rasterplot!, stackplot, stackplot!, voltage_stack end From e2497dca99664032c163748ac1e905db18b19345 Mon Sep 17 00:00:00 2001 From: harisorgn Date: Thu, 5 Sep 2024 20:33:38 +0300 Subject: [PATCH 13/15] use the old way (Peaks.jl) for spike detection --- src/blox/blox_utilities.jl | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 84def8a0..70855c19 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -251,9 +251,9 @@ function get_weights(agent::Agent, blox_out, blox_in) end function find_spikes(x::AbstractVector{T}; minprom=zero(T), maxprom=nothing, minheight=zero(T), maxheight=nothing) where {T} - spikes, _ = argmaxima(x) - peakproms!(spikes, x; minprom, maxheight) - peakheights!(spikes, xx[spikes]; minheight, maxheight) + spikes = argmaxima(x) + peakproms!(spikes, x; minprom, maxprom) + peakheights!(spikes, x[spikes]; minheight, maxheight) return spikes end @@ -264,6 +264,27 @@ function count_spikes(x::AbstractVector{T}; minprom=zero(T), maxprom=nothing, mi return length(spikes) end +function detect_spikes(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution; tolerance = 1e-3) + namespaced_name = namespaced_nameof(blox) + reset_param_name = Symbol(namespaced_name, "₊V_reset") + threshold_param_name = Symbol(namespaced_name, "₊θ") + + reset = only(@parameters $(reset_param_name)) + thrs = only(@parameters $(threshold_param_name)) + + get_reset = getp(sol, reset) + reset_value = get_reset(sol) + + get_thrs = getp(sol, thrs) + thrs_value = get_thrs(sol) + + V = voltage_timeseries(blox, sol) + + spikes = find_spikes(V; minheight = thrs_value - tolerance) + + return spikes +end + """ function get_dynamic_states(sys) From 4b44ecccb3636d9ba16255c4a6b5bfba1fe00592 Mon Sep 17 00:00:00 2001 From: harisorgn Date: Thu, 5 Sep 2024 20:34:00 +0300 Subject: [PATCH 14/15] remove unused kwarg --- src/blox/blox_utilities.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 70855c19..64a7f0a8 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -419,7 +419,7 @@ end replace_refractory!(V, blox, sol::SciMLBase.AbstractSolution) = V -function voltage_timeseries(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution; nan_refractory=false) +function voltage_timeseries(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution) namespaced_name = namespaced_nameof(blox) state_name = Symbol(namespaced_name, "₊V") From 1e821c84713d466f41732481beb26d2d53194ad3 Mon Sep 17 00:00:00 2001 From: harisorgn Date: Thu, 5 Sep 2024 20:34:12 +0300 Subject: [PATCH 15/15] move spike detection function --- src/blox/blox_utilities.jl | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/blox/blox_utilities.jl b/src/blox/blox_utilities.jl index 64a7f0a8..a2260cf7 100644 --- a/src/blox/blox_utilities.jl +++ b/src/blox/blox_utilities.jl @@ -441,29 +441,3 @@ function meanfield_timeseries(cb::CompositeBlox, sol::SciMLBase.AbstractSolution return vec(mapslices(nanmean, V; dims = 2)) end - -function detect_spikes(blox::AbstractNeuronBlox, sol::SciMLBase.AbstractSolution) - namespaced_name = namespaced_nameof(blox) - reset_param_name = Symbol(namespaced_name, "₊V_reset") - threshold_param_name = Symbol(namespaced_name, "₊θ") - - reset = only(@parameters $(reset_param_name)) - thrs = only(@parameters $(threshold_param_name)) - - get_reset = getp(sol, reset) - reset_value = get_reset(sol) - - get_thrs = getp(sol, thrs) - thrs_value = get_thrs(sol) - - V = voltage_timeseries(blox, sol) - - spike_idxs = Int[] - for (i, vi) in enumerate(V[1:end-1]) - if (abs(vi - thrs_value) <= 1e-3) && (abs(V[i+1] - reset_value) <= 1e-3) - push!(spike_idxs, i) - end - end - - return spike_idxs -end