## LFP CALCULATION AND PLOTTING POWER SPECTRA
## - built from referencing 'spike_train_correlation' in utilities.jl
## ---------------------------------------------
include("utilities.jl");
default(show=false)
default(fontfamily="Computer Modern")
# HYPERPARAMS
n_runs = 3
patterns = 0:12
duration = 2000
labels = ["theta" , "ftheta", "alpha", "beta", "gamma"]
freqlabels = [L"\theta" L"\theta_{fast}" L"\alpha" L"\beta" L"\gamma"]
fig_ext = ".png"
# CREATE NECESSARY DIRECTORIES
create_directories_if_not_exist()
# IDENTIFY NEURON POPULATION RANGES
populations = Dict(
"DG" => [0, 500],
"BC" => [500,506],
"MC" => [506, 521],
"HIPP" => [521, 527]
)
# FUNCTIONS
function makechunks(convolution::Vector, n_neurons::Integer)
chunks = length(convolution) ÷ n_neurons
return [convolution[1+chunks*k:(k == n_neurons-1 ? end : chunks*k+chunks)] for k = 0:n_neurons-1]
end
function compute_LFP(
spike_train::DataFrame,
n_neurons::Int64;
delta::Int64=5,
n_bins::Int64=1,
duration::Float64=2000.0)
# Create kernel
tri_rng = collect(1:round(Int64, delta/n_bins))
triangular_kernel = [tri_rng; reverse(tri_rng)[2:end]]'
# Create bins for histograms
bins = collect(1:n_bins:(duration + n_bins))
convolved_series = zeros(round(Int64, n_neurons * duration / n_bins))
for i ∈ 1:n_neurons
s = spike_train[spike_train.Neuron .== (i-1), "Time"]
timeseries, _ = np.histogram(s, bins)
idx_low = round(Int64, (i-1)*duration/n_bins + 1)
idx_high = round(Int64, i*duration/n_bins)
convolved_series[idx_low:idx_high] = np.convolve(timeseries, triangular_kernel, "same") #TODO: consider scipy.signal.fftconvolve as alt.
end
LFP = makechunks(convolved_series, n_neurons)
return sum(LFP)
end
global ppsave = []
global gcsave = []
lfp_save_pp = OrderedDict("theta"=>[], "ftheta"=>[], "alpha"=>[], "beta"=>[], "gamma"=>[])
lfp_save_gc = OrderedDict("theta"=>[], "ftheta"=>[], "alpha"=>[], "beta"=>[], "gamma"=>[])
for run_ ∈ 1:n_runs
for i ∈ 1:length(labels)
spikes = load_spike_files(patterns, labels[i]*"-$run_", populations)
for p ∈ unique(spikes.Pattern)
# TODO: change so this works ∀ neurons
pp = spikes[(spikes.Population .== "PP") .& (spikes.Pattern .== p), :]
gc = spikes[(spikes.Population .== "DG") .& (spikes.Pattern .== p), :]
#compute LFP
pp_lfp = [compute_LFP(pp, 100)]
gc_lfp = [compute_LFP(gc, 500)]
#save LFP for each pattern:
global ppsave = append!(ppsave, pp_lfp)
global gcsave = append!(gcsave, gc_lfp)
end
# average LFP across all patterns
sum_lfp_pat_pp = [sum(ppsave)/length(ppsave[1])]
sum_lfp_pat_gc = [sum(gcsave)/length(gcsave[1])]
# save summated lfp/freq band
append!(lfp_save_pp[labels[i]], sum_lfp_pat_pp)
append!(lfp_save_gc[labels[i]], sum_lfp_pat_gc)
end
end
#### GC Raster plots only ####
gcs = Dict(
"DG" => [0, 500],
)
for run_ ∈ 1:n_runs
for i ∈ 1:length(labels)
spikes = load_spike_files(patterns, labels[i]*"-$run_", populations)
# CREATE RASTER PLOTS
for p ∈ unique(spikes.Pattern)
stimin = spikes[(spikes.Population .== "PP") .& (spikes.Pattern .== p), :]
plots = []
append!(plots, [raster_plot(stimin; ylab="PP")])
for pop ∈ keys(gcs)
lb, ub = populations[pop]
popspikes = spikes[(spikes.Population .== pop) .& (spikes.Pattern .== p),:]
append!(plots, [raster_plot(popspikes; xlab="", ylab=pop)])
end
fig = plot(reverse(plots)..., layout=grid(2, 1, heights=[0.8, 0.2]), size=(500, 400), dpi = 300)
savefig(fig, "figures/raster-plots/raster-gconly--"*string(p)*"-"*labels[i]*"-$run_"*".png")
end
end
end
#-------PLOT LFPS
l = @layout [grid(2,1, heights=[0.8, 0.2])]
theta_lfp_pp = plot(lfp_save_pp["theta"][1],
color = :black,
xlabel = "Time (ms)",
ylabel = "PP",
label = nothing,
)
theta_lfp_gc = plot(lfp_save_gc["theta"][1],
color = :black,
ylabel = "DG",
label = nothing,
)
sumfig = plot(theta_lfp_gc, theta_lfp_pp, layout=l, size=(500, 400), dpi=300)
savefig(sumfig, "figures/lfp/lfps_gcs_pp.png")
#-------POWER SPECTRA
restruct_gclfps = zeros((duration, length(labels)))
restruct_pplfps = zeros((duration, length(labels)))
for i ∈ 1:length(labels)
restruct_gclfps[:,i] = lfp_save_gc[labels[i]][n_runs]
restruct_pplfps[:,i] = lfp_save_pp[labels[i]][n_runs]
end
# Calculate power spectra
S = spectra(restruct_gclfps, 500, duration; tapering=hamming) #TODO: learn what this 'tapering' is.
# Calculate power spectra
S = spectra(restruct_gclfps, 500, duration; tapering=hamming) #TODO: learn what this 'tapering' is.
# SUM LOW GAMMA POWER FOR 30Hz-60Hz
norm_gamma_pwrL = OrderedDict("theta"=>0.0, "ftheta"=>0.0, "alpha"=>0.0, "beta"=>0.0, "gamma"=>0.0)
for freq ∈ 1:length(labels)
norm_gamma_pwrL[labels[freq]] =sum(S.y[30:39,freq])
end
# SUM MED GAMMA POWER FOR 30Hz-60Hz
norm_gamma_pwrM = OrderedDict("theta"=>0.0, "ftheta"=>0.0, "alpha"=>0.0, "beta"=>0.0, "gamma"=>0.0)
for freq ∈ 1:length(labels)
norm_gamma_pwrM[labels[freq]] =sum(S.y[40:59,freq])
end
# SUM HIGH GAMMA POWER FOR 60-200Hz
norm_gamma_pwrH = OrderedDict("theta"=>0.0, "ftheta"=>0.0, "alpha"=>0.0, "beta"=>0.0, "gamma"=>0.0)
for freq ∈ 1:length(labels)
norm_gamma_pwrH[labels[freq]] =sum(S.y[60:200,freq])
end
CSV.write("figures/lfp/gamma_pwr_low.csv", norm_gamma_pwrL)
CSV.write("figures/lfp/gamma_pwr_med.csv", norm_gamma_pwrM)
CSV.write("figures/lfp/gamma_pwr_high.csv", norm_gamma_pwrH)
# PLOT GAMMA POWER BAR GRAPH
gamma_pwr = bar(vec(freqlabels), [[norm_gamma_pwrM[i] for i ∈ labels] [norm_gamma_pwrL[i] for i ∈ labels] [norm_gamma_pwrH[i] for i ∈ labels]],
labels = ["Low "*L"\gamma" "Med. "*L"\gamma" "High "*L"\gamma"],
color = [:grey75 :grey50 :black], xlabel = "Frequency Band", ylabel = L"\gamma"*" Power",
xtickfont=font(12), size = (350,350), legend = :topleft, dpi=300)
savefig(gamma_pwr, "figures/lfp/gamma_pwr_bar.png")
# PLOT GAMMA POWER LINE GRAPH
gamma_pwr_line = plot(vec(freqlabels), [[norm_gamma_pwrL[i] for i ∈ labels] [norm_gamma_pwrM[i] for i ∈ labels] [norm_gamma_pwrH[i] for i ∈ labels]],
labels = ["Low "*L"\gamma" "Med. "*L"\gamma" "High "*L"\gamma"], xtickfont=font(12),
color = [:grey75 :grey50 :black], ylims = (0, 40), linewidth = 2, xlabel = "Input Frequency Band", ylabel = L"\gamma"*" Power",
size = (350,350), legend = :topleft, dpi=300)
savefig(gamma_pwr_line, "figures/lfp/gamma_pwr_line.png")
# PLOT RAW SPECTRA
powerfig = plot(S, fmax = 50, label = freqlabels, legend = :topright, ylabel = "Power "*L"(\mu V^2)", dpi=300)
savefig(powerfig, "figures/lfp/powerspectra_gcs.png")
# PLOT HIGH FREQ RAW SPECTRA SEPERATELY
powerfigstack = plot(S, layout=grid(5,1, heights=[0.2,0.2,0.2,0.2,0.2]), xticks = (collect(0:5:50)),
xlims = (0,50), ylims=(0,35),label = freqlabels, linewidth = 3,
legend = :topright, ylabel = "Power "*L"(\mu V^2)",
xlabel = "Frequency (Hz)", size=(500, 800), c=:black, grid=:none, dpi=300)
savefig(powerfigstack, "figures/lfp/powerspectra_gcs_stacked.png")
# PLOT FREQUENCY-TIME HEATMAP
A = TFamplitude(lfp_save_gc["theta"][n_runs], 400, duration; fmax=40)
freqtime = heatmap(A.y, xlabel = "Time (ms)", ylabel = "Frequency (Hz)", dpi=300)
savefig(freqtime, "figures/lfp/gcs_freqtime.png")