import numpy as np from neuron import h from .psd import PSD class GluPSD(PSD): """ Glutamatergic PSD with ionotropic AMPA / NMDA receptors This creates a set of postsynaptoc NMDA and AMPA receptors, one pair per terminal release site. Receptors are connected to the XMTR range variable of the terminal release mechanisms. Parameters ---------- section : Section instance The postsynaptic section into which the receptor mechanisms should be attached terminal : Terminal instance The presynaptic terminal that provides input to the receptor XMTR variables. ampa_gmax : float Maximum conductance of AMPARs nmda_gmax : float Maximum conductance of NMDARs gvar : float Coefficient of variation for randomly adjusting ampa_gmax and nmda_gmax. Note that ampa and nmda maximum conductances will be scaled together, but the scale values will be selected randomly for each pair of receptor mechanisms. eRev : float Reversal potential to use for both receptor types. ampa_params : dict Dictionary containing kinetic parameters for AMPA mechanism. Suggested keys are Ro1, Ro2, Rc1, Rc2, and PA. Notes ----- *ampa_gmax* and *nmda_gmax* should be provided as the maximum *measured* conductances; these will be automatically corrected for the maximum open probability of the receptor mechanisms. GluPSD does not include a cleft mechanism because AMPATRUSSELL implements its own cleft and NMDA_Kampa is slow enough that a cleft would have insignificant effect. """ def __init__( self, section, terminal, ampa_gmax, nmda_gmax, gvar=0, eRev=0, nmda_vshift=0, ampa_params=None, loc=0.5, ): PSD.__init__(self, section, terminal) # print('\033[0;33;40m ^^^^^ GVAR = %.4f ^^^^^\033[0;37;40m ' % gvar) ampa_params = {} if ampa_params is None else ampa_params # and then make a set of postsynaptic receptor mechanisms ampa_psd = [] nmda_psd = [] relsite = terminal.relsite self.section.push() for i in range(0, terminal.n_rzones): # create mechanisms ampa = h.AMPATRUSSELL( loc, self.section ) # raman/trussell AMPA with rectification nmda = h.NMDA_Kampa(loc, self.section) # Kampa state model NMDA receptors # Connect terminal to psd h.setpointer(relsite._ref_XMTR[i], "XMTR", ampa) h.setpointer(relsite._ref_XMTR[i], "XMTR", nmda) # Set any extra ampa parameters provided by the caller # (Ro1, Ro2, Rc1, Rc2, PA, ...) for k, v in ampa_params.items(): setattr(ampa, k, v) # add a little variability - gvar is CV of amplitudes v = 1.0 + gvar * np.random.standard_normal() # set gmax and eRev for each postsynaptic receptor mechanism ampa.gmax = ampa_gmax * v ampa.Erev = eRev nmda.gmax = nmda_gmax * v nmda.Erev = eRev nmda.vshift = nmda_vshift ampa_psd.append(ampa) nmda_psd.append(nmda) h.pop_section() self.ampa_psd = ampa_psd self.nmda_psd = nmda_psd self.all_psd = nmda_psd + ampa_psd @property def n_psd(self): """The number of postsynaptic densities represented by this object. """ return len(self.ampa_psd) def record(self, *args): """Create a new set of vectors to record parameters for each release site. Parameters ---------- \*args : Allowed parameters are 'i' (current), 'g' (conductance), and 'Open' (open probability). """ self.vectors = {"ampa": [], "nmda": []} for receptor in self.vectors: for mech in getattr(self, receptor + "_psd"): vec = {} for var in args: vec[var] = h.Vector() vec[var].record(getattr(mech, "_ref_" + var)) self.vectors[receptor].append(vec) def get_vector(self, receptor, var, i=0): """Return an array from a previously recorded vector. Parameters ---------- receptor : str May be 'ampa' or 'nmda' var : str Allowed parameters are 'i' (current), 'g' (conductance), and 'Open' (open probability). i : int, default=0 The integer index of the psd (if this is a multi-site synapse) """ v = self.vectors[receptor][i][var] return np.array(v)