You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
397 lines
13 KiB
397 lines
13 KiB
""" |
|
The Assumptions of this cell are modified to the test_sgc_input_PSTH.py but should be identical in function |
|
|
|
synapse type = simple |
|
synapse type = single |
|
species = mouse |
|
sgc = dummy SGC lacks cell body |
|
cell connection = pyramidal |
|
|
|
|
|
|
|
""" |
|
|
|
import sys |
|
import numpy as np |
|
import pyqtgraph as pg |
|
from neuron import h |
|
from cnmodel.protocols import Protocol |
|
from cnmodel import cells |
|
from cnmodel.util import sound |
|
from cnmodel.util import custom_init |
|
import cnmodel.util.pynrnutilities as PU |
|
from cnmodel import data |
|
|
|
synapseType = "simple" # no other options exist |
|
species = "mouse" # tables for other species do not yet exist |
|
|
|
|
|
def main(): |
|
prot = SGCInputTestPSTH(seed=1233451898) |
|
prot.run() |
|
prot.show() |
|
if sys.flags.interactive == 0: |
|
pg.QtGui.QApplication.exec_() |
|
|
|
|
|
class SGCInputTestPSTH(Protocol): |
|
def __init__(self, temp=34.0, dt=0.025, seed=575982035): |
|
""" |
|
:param temp: Celcius |
|
:param dt: resolution in ms |
|
:param seed: seed should be generated randomly |
|
|
|
Pre-determined variables that can be changed by editing the value next to them |
|
|
|
AMPA_gmax and n_sgc = loaded from data that is kept in cnmodel/data dir |
|
|
|
Defines a single tone parameters with which to test the neuron complex |
|
""" |
|
# super only defines reset function |
|
super(SGCInputTestPSTH, self).__init__() |
|
# |
|
self.temp = temp |
|
self.dt = dt |
|
self.seed = seed |
|
self.simulator = "cochlea" |
|
# predetermined variables |
|
self.cell = "pyramidal" |
|
self.nrep = 50 # number of repetitions |
|
self.stimulus = "tone" |
|
self.Fs = 100e3 # in Hz |
|
self.f0 = 4000.0 # stimulus in Hz |
|
self.cf = 4000.0 # SGCs in Hz |
|
self.fMod = 100.0 # mod freq, Hz |
|
self.dMod = 0.0 # % mod depth, Hz |
|
self.dbspl = 50.0 |
|
self.sr = 2 # set SR group |
|
|
|
# variables loaded from data |
|
AMPA_gmax, n_sgc = self.load_variables_from_data() |
|
self.n_sgc = int(np.round(n_sgc)) |
|
|
|
# value needed for simple synapses |
|
self.AMPA_gmax = AMPA_gmax |
|
|
|
# the stimulation delivered is a Tone |
|
self.run_duration = 0.20 # in seconds |
|
self.pip_duration = 0.05 # in seconds |
|
self.pip_start = [0.1] # in seconds |
|
self.f0 = 4000.0 |
|
self.cf = 4000.0 |
|
self.stim = sound.TonePip( |
|
rate=self.Fs, |
|
duration=self.run_duration, |
|
f0=self.f0, |
|
dbspl=self.dbspl, |
|
ramp_duration=2.5e-3, |
|
pip_duration=self.pip_duration, |
|
pip_start=self.pip_start, |
|
) |
|
|
|
# creates empty lists that will contain the results of each rep |
|
self.vms = [None for n in range(self.nrep)] |
|
self.synapses = [None for n in range(self.nrep)] |
|
self.xmtrs = [None for n in range(self.nrep)] |
|
self.pre_cells = [None for n in range(self.nrep)] |
|
self.time = [None for n in range(self.nrep)] |
|
|
|
def load_variables_from_data(self): |
|
AMPA_gmax = ( |
|
data.get( |
|
"sgc_synapse", species=species, post_type=self.cell, field="AMPA_gmax" |
|
)[0] |
|
/ 1e3 |
|
) |
|
n_sgc = data.get( |
|
"convergence", species=species, post_type=self.cell, pre_type="sgc" |
|
)[0] |
|
print(n_sgc) |
|
return AMPA_gmax, n_sgc |
|
|
|
def check_assertations(self): |
|
assert self.cell in [ |
|
"bushy", |
|
"tstellate", |
|
"octopus", |
|
"dstellate", |
|
"tuberculoventral", |
|
"pyramidal", |
|
] |
|
assert self.stimulus == "tone" # cases available |
|
assert synapseType == "simple" |
|
|
|
def run(self): |
|
self.check_assertations() |
|
# info based on the parameters set in the __init__ statement |
|
info = { |
|
"n_sgc": self.n_sgc, |
|
"gmax": self.AMPA_gmax, |
|
"stim": self.stim, |
|
"simulator": self.simulator, |
|
"cf": self.cf, |
|
"sr": self.sr, |
|
"seed": self.seed, |
|
"run_duration": self.run_duration, |
|
"temp": self.temp, |
|
"dt": self.dt, |
|
"init": custom_init, |
|
} |
|
|
|
# run number of trials based on nrep defined in __init__ statement |
|
for nr in range(self.nrep): |
|
info["seed"] = self.seed + 3 * self.n_sgc * nr |
|
res = run_trial(info) |
|
# res contains: {'time': time, 'vm': Vm, 'xmtr': xmtr, 'pre_cells': pre_cells, 'post_cell': post_cell} |
|
|
|
# unpacks the res dict returned from the run_trial() into refrenceable variables |
|
self.pre_cells[nr] = res["pre_cells"] |
|
self.time[nr] = res["time"] |
|
self.xmtr = {k: v.to_python() for k, v in res["xmtr"].items()} |
|
self.vms[nr] = res["vm"] |
|
self.synapses[nr] = res["synapses"] |
|
self.xmtrs[nr] = self.xmtr |
|
|
|
def show(self): |
|
""" |
|
Creates a single page graph that contains all of the graphs based on the graphical functions in the class |
|
|
|
""" |
|
self.win = pg.GraphicsWindow() |
|
self.win.setBackground("w") |
|
p1 = self.stimulus_graph() |
|
p2 = self.an_spikes_graph() |
|
p3 = self.cell_spikes_graph() |
|
p4 = self.voltage_graph() |
|
p5 = self.xmtr_graph() |
|
p6 = ( |
|
self.an_psth_graph() |
|
) # requires that an_spikes_graph() has been called before |
|
p7 = ( |
|
self.cell_psth_graph() |
|
) # requires that cell_spikes_graph() has been called before |
|
|
|
# links x axis |
|
p1.setXLink(p1) |
|
p2.setXLink(p1) |
|
p3.setXLink(p1) |
|
p4.setXLink(p1) |
|
p5.setXLink(p1) |
|
self.win.show() |
|
|
|
############# Graph options to be included in the show() method ################### |
|
def stimulus_graph(self): |
|
p1 = self.win.addPlot( |
|
title="Stimulus", row=0, col=0, labels={"bottom": "T (ms)", "left": "V"} |
|
) |
|
p1.plot( |
|
self.stim.time * 1000, self.stim.sound, pen=pg.mkPen("k", width=0.75) |
|
) |
|
return p1 |
|
|
|
def an_spikes_graph(self): |
|
p2 = self.win.addPlot( |
|
title="AN spikes", |
|
row=1, |
|
col=0, |
|
labels={"bottom": "T (ms)", "left": "AN spikes (first trial)"}, |
|
) |
|
for nr in range(self.nrep): |
|
xan = [] |
|
yan = [] |
|
for k in range(len(self.pre_cells[nr])): |
|
r = self.pre_cells[nr][k]._spiketrain |
|
xan.extend(r) |
|
yr = k + np.zeros_like(r) + 0.2 |
|
yan.extend(yr) |
|
c = pg.PlotCurveItem() |
|
xp = np.repeat(np.array(xan), 2) |
|
yp = np.repeat(np.array(yan), 2) |
|
yp[1::2] = yp[::2] + 0.6 |
|
c.setData( |
|
xp.flatten(), |
|
yp.flatten(), |
|
connect="pairs", |
|
pen=pg.mkPen(pg.intColor(nr, self.nrep), hues=self.nrep, width=1.0), |
|
) |
|
self.xan = xan |
|
self.yan = yan |
|
p2.addItem(c) |
|
return p2 |
|
|
|
def cell_spikes_graph(self): |
|
p3 = self.win.addPlot( |
|
title="%s Spikes" % self.cell, |
|
row=2, |
|
col=0, |
|
labels={"bottom": "T (ms)", "left": "Trial #"}, |
|
) |
|
xcn = [] |
|
ycn = [] |
|
xspks = [] |
|
for k in range(self.nrep): |
|
bspk = PU.findspikes(self.time[k], self.vms[k], -35.0) |
|
xcn.extend(bspk) |
|
yr = k + np.zeros_like(bspk) + 0.2 |
|
ycn.extend(yr) |
|
d = pg.PlotCurveItem() |
|
xp = np.repeat(np.array(xcn), 2) |
|
yp = np.repeat(np.array(ycn), 2) |
|
yp[1::2] = yp[::2] + 0.6 |
|
d.setData( |
|
xp.flatten(), |
|
yp.flatten(), |
|
connect="pairs", |
|
pen=pg.mkPen("k", width=1.5), |
|
) |
|
self.xcn = xcn |
|
self.ycn = ycn |
|
p3.addItem(d) |
|
|
|
return p3 |
|
|
|
def voltage_graph(self): |
|
p4 = self.win.addPlot( |
|
title="%s Vm" % self.cell, |
|
row=3, |
|
col=0, |
|
labels={"bottom": "T (ms)", "left": "Vm (mV)"}, |
|
) |
|
for nr in range(self.nrep): |
|
p4.plot( |
|
self.time[nr], |
|
self.vms[nr], |
|
pen=pg.mkPen(pg.intColor(nr, self.nrep), hues=self.nrep, width=1.0), |
|
) |
|
return p4 |
|
|
|
def xmtr_graph(self): |
|
p5 = self.win.addPlot( |
|
title="xmtr", row=0, col=1, labels={"bottom": "T (ms)", "left": "gSyn"} |
|
) |
|
if synapseType == "multisite": |
|
for nr in [0]: |
|
syn = self.synapses[nr] |
|
j = 0 |
|
for k in range(self.n_sgc): |
|
synapse = syn[k] |
|
for i in range(synapse.terminal.n_rzones): |
|
p5.plot( |
|
self.time[nr], |
|
self.xmtrs[nr]["xmtr%04d" % j], |
|
pen=pg.mkPen( |
|
pg.intColor(nr, self.nrep), |
|
hues=self.nrep, |
|
width=1.0, |
|
), |
|
) |
|
j = j + 1 |
|
return p5 |
|
|
|
def an_psth_graph(self): |
|
p6 = self.win.addPlot( |
|
title="AN PSTH", |
|
row=1, |
|
col=1, |
|
labels={"bottom": "T (ms)", "left": "Sp/ms/trial"}, |
|
) |
|
bins = np.arange(0, 200, 1) |
|
(hist, binedges) = np.histogram(self.xan, bins) |
|
curve6 = p6.plot( |
|
binedges, |
|
hist, |
|
stepMode=True, |
|
fillBrush=(0, 0, 0, 255), |
|
brush=pg.mkBrush("k"), |
|
fillLevel=0, |
|
) |
|
return p6 |
|
|
|
def cell_psth_graph(self): |
|
p7 = self.win.addPlot( |
|
title="%s PSTH" % self.cell, |
|
row=2, |
|
col=1, |
|
labels={"bottom": "T (ms)", "left": "Sp/ms/trial"}, |
|
) |
|
bins = np.arange(0, 200, 1) |
|
(hist, binedges) = np.histogram(self.xcn, bins) |
|
curve7 = p7.plot( |
|
binedges, |
|
hist, |
|
stepMode=True, |
|
fillBrush=(0, 0, 0, 255), |
|
brush=pg.mkBrush("k"), |
|
fillLevel=0, |
|
) |
|
return p7 |
|
|
|
|
|
def run_trial(info): |
|
""" |
|
This function is really the bread |
|
and butter of the run and determines the layout |
|
of the model and the stimulus is |
|
created and delivered by the SGC. |
|
|
|
Runs a single trial and returns it |
|
into another dictionary that is stored |
|
before the next trial is run. |
|
|
|
:param info: dict containing :'n_sgc': self.n_sgc, |
|
'gmax': self.AMPA_gmax, |
|
'stim': self.stim, |
|
'simulator': self.simulator, |
|
'cf': self.cf, 'sr': self.sr, |
|
'seed': self.seed, |
|
'run_duration': self.run_duration, |
|
'temp': self.temp, |
|
'dt': self.dt, |
|
'init': custom_init |
|
|
|
post cell allowed to use defaults in the case of things like pyramidal cells are guinea pigs instead of a mouse |
|
""" |
|
# for the model to change the post_cell needs to be changed here otherwise the model will not be changed. |
|
# special consideration needs to be taken because not all cell parameters are universal |
|
# ex: Pyramidal does not have a species='mouse', nothing just assumes a default and not all defaults are the same |
|
post_cell = cells.Pyramidal.create() |
|
pre_cells = [] |
|
synapses = [] |
|
xmtr = {} |
|
|
|
# connects all of the SGC fibers to the post_cell using simple synapses and then generates a sound stim based on a |
|
# seed the number of repetitions desired |
|
for nsgc, sgc in enumerate(range(info["n_sgc"])): |
|
pre_cells.append(cells.DummySGC(cf=info["cf"], sr=info["sr"])) |
|
synapses.append(pre_cells[-1].connect(post_cell, type="simple")) |
|
synapses[-1].terminal.netcon.weight[0] = info["gmax"] |
|
|
|
# sets sounds stim for each of the SGC fibers independently |
|
pre_cells[-1].set_sound_stim( |
|
info["stim"], seed=info["seed"] + nsgc, simulator=info["simulator"] |
|
) |
|
|
|
# Recording each trial and returning it as a dictionary |
|
Vm = h.Vector() |
|
Vm.record(post_cell.soma(0.5)._ref_v) |
|
rtime = h.Vector() |
|
rtime.record(h._ref_t) |
|
h.tstop = 1e3 * info["run_duration"] # duration of a run |
|
h.celsius = info["temp"] |
|
h.dt = info["dt"] |
|
post_cell.cell_initialize() |
|
info["init"]() |
|
h.t = 0.0 |
|
h.run() |
|
return { |
|
"time": np.array(rtime), |
|
"vm": Vm.to_python(), |
|
"xmtr": xmtr, |
|
"pre_cells": pre_cells, |
|
"post_cell": post_cell, |
|
"synapses": synapses, |
|
} |
|
|
|
|
|
if __name__ == "__main__": |
|
main()
|
|
|