示例#1
0
def plot_latent_compartment_state(t, z, state, compartment, axs=None, colors=['k'], linewidth=1):
    dtype = compartment.latent_dtype
    lb = compartment.latent_lb
    ub = compartment.latent_ub
    D = sz_dtype(dtype)
    z_comp = get_item_at_path(z, compartment.path)
    z = as_matrix(z_comp, D)
    z_names = extract_names_from_dtype(dtype)

    # Compute the channel currents
    s_comp = get_item_at_path(state, compartment.path)
    N_ch = len(compartment.channels)
    Is = [s_comp[ch.name]['I'] for ch in compartment.channels]

    # if fig is None:
    #     fig,axs = plt.subplots(D,1)
    # else:
    #     axs = fig.get_axes()
    # # Make sure axs is a list of axes, even if it is length 1
    # if not isinstance(axs, (list, np.ndarray)):
    #     axs = [axs]


    if axs is None:
        axs = []

        for d in np.arange(D):
            ax = plt.subplot2grid((D,3), (d,0), colspan=2)
            axs.append(ax)

        ax = plt.subplot2grid((D,3), (0,2), rowspan=D)
        axs.append(ax)

    for d in np.arange(D):
        axs[d].plot(t, z[d,:], color=colors[d % len(colors)], linewidth=linewidth)
        axs[d].set_ylabel(z_names[d])

        yl = list(axs[d].get_ylim())
        if np.isfinite(lb[d]):
            yl[0] = lb[d]
        if np.isfinite(ub[d]):
            yl[1] = ub[d]
        axs[d].set_ylim(yl)

    # Plot the channel densities
    C = len(compartment.channels)
    gs = [ch.g.value for ch in compartment.channels]
    names = [ch.name for ch in compartment.channels]


    axs[-1].bar(np.arange(C), gs, facecolor=colors[0], alpha=0.5)
    axs[-1].set_xticks(np.arange(C))
    axs[-1].set_xticklabels(map(lambda n: '$g_%s$' % n, names))
    axs[-1].set_title('Channel densities')
    axs[-1].set_ylim([0,30])

    # if not fig_given:
    #     plt.show()

    return axs
示例#2
0
    def simple_logp(self, latent, observations):
        """
        We want to compute the log probability of a set of observations given
        the latent trajectories up to time t. This is challenging (especially
        in our current particle MCMC framework, since we are not set up for
        observation models that depend on previous as well as current states),
        so for now we'll just do something simple as an approximation.

        :param latent:
        :param observations:
        :return:
        """
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        latent_V = x_comp['V']

        o = utils.get_item_at_path(observations, self.path)
        observed_V = o['V']

        # Set the effective variance to be 'filterbins' times the variance
        # of the mean. This is motivated by thinking of each instantaneous
        # voltage measurement as an i.i.d. sample whose mean is the measured
        # fluorescence
        sigma_eff = np.sqrt(self.filterbins) * self.sigma.value
        logp = -0.5/sigma_eff**2 * (observed_V-latent_V)**2
        return logp
示例#3
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)
        n = x_ch['n']

        # Compute the alpha and beta as a function of V
        alpha, beta = self.alpha_beta(x_comp)

        # Compute the channel state updates
        dxdt['n'] = alpha * (1.0-n) - beta*n

        return dxdt
示例#4
0
    def simple_logp(self, latent, observations):
        """
        We want to compute the log probability of a set of observations given
        the latent trajectories up to time t. This is challenging (especially
        in our current particle MCMC framework, since we are not set up for
        observation models that depend on previous as well as current states),
        so for now we'll just do something simple as an approximation.

        :param latent:
        :param observations:
        :return:
        """
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        latent_V = x_comp['V']

        o = utils.get_item_at_path(observations, self.path)
        observed_V = o['V']

        # Set the effective variance to be 'filterbins' times the variance
        # of the mean. This is motivated by thinking of each instantaneous
        # voltage measurement as an i.i.d. sample whose mean is the measured
        # fluorescence
        sigma_eff = np.sqrt(self.filterbins) * self.sigma.value
        logp = -0.5 / sigma_eff**2 * (observed_V - latent_V)**2
        return logp
示例#5
0
 def evaluate_state(self, latent, inpt):
     """
     Evaluate the state of this compartment
     """
     state = np.zeros(latent.shape, dtype=self.state_dtype)
     x_comp = get_item_at_path(latent, self.compartment.path)
     x_ch = get_item_at_path(latent, self.path)
     state['I'] = x_ch['a'] * x_ch['b'] * (x_comp['V'] - self.E.value)
     return state
示例#6
0
 def evaluate_state(self, latent, inpt):
     """
     Evaluate the state of this compartment
     """
     state = np.zeros(len(latent), dtype=self.state_dtype)
     x_comp = get_item_at_path(latent, self.compartment.path)
     x_ch = get_item_at_path(latent, self.path)
     state['I'] = (x_ch['s'] ** 2) * x_ch['r'] * (x_comp['V'] - self.E.value)
     #print "x_ch: ", x_ch['s']
     return state
示例#7
0
 def evaluate_state(self, latent, inpt):
     """
     Evaluate the state of this compartment
     """
     state = np.zeros(latent.shape, dtype=self.state_dtype)
     x_comp = get_item_at_path(latent, self.compartment.path)
     x_ch = get_item_at_path(latent, self.path)
     #print "c: ", x_ch['c']
     #print "Ca: ", x_comp['[Ca]'] / 250
     #print "min: ", np.min(1, x_comp['[Ca]'] / 250)
     #print "ans: ", x_ch['c'] * np.min(1, x_comp['[Ca]'] / 250) * (x_comp['V'] - self.E.value)
     state['I'] = x_ch['c'] * np.minimum(1, x_comp['[Ca]'] / 250) * (x_comp['V'] - self.E.value)
     return state
示例#8
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        s_comp = get_item_at_path(latent, self.path)
        i_comp = get_item_at_path(inpt, self.path)

        # To compute dV/dt we need the ionic current in this compartment
        
        I_ionic   = 0
        I_calcium = 0
        for c in self.channels:
            s_ch = get_item_at_path(state, c.path)
            I_ionic += c.g.value * s_ch['I']

            if c.moves_calcium:
                I_calcium += c.g.value * s_ch['I']

        dxdt['V'] = -1.0/self.C.value * I_ionic

        # We model [Ca] as per page 83 of Traub 1994
        dxdt['[Ca]'] = -1 * I_calcium * self.Phi - s_comp['[Ca]'] * self.Beta

        # TODO Figure out how to handle coupling with other compartments
        # dxdt['V'] += 1.0/self.neuron.C*self.neuron.W(k,:)*(V-Vk)

        # Add in driving current
        dxdt['V'] += 1.0/self.C.value * i_comp['I']

        for c in self.channels:
            if not (c.latent_dtype is None or c.latent_dtype == []):
                tmp = c.kinetics(latent, inpt, state)
                dxdt[c.name] = tmp

        return dxdt
示例#9
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        s_comp = get_item_at_path(latent, self.path)
        i_comp = get_item_at_path(inpt, self.path)

        # To compute dV/dt we need the ionic current in this compartment

        I_ionic = 0
        I_calcium = 0
        for c in self.channels:
            s_ch = get_item_at_path(state, c.path)
            I_ionic += c.g.value * s_ch['I']

            if c.moves_calcium:
                I_calcium += c.g.value * s_ch['I']

        dxdt['V'] = -1.0 / self.C.value * I_ionic

        # We model [Ca] as per page 83 of Traub 1994
        dxdt['[Ca]'] = -1 * I_calcium * self.Phi - s_comp['[Ca]'] * self.Beta

        # TODO Figure out how to handle coupling with other compartments
        # dxdt['V'] += 1.0/self.neuron.C*self.neuron.W(k,:)*(V-Vk)

        # Add in driving current
        dxdt['V'] += 1.0 / self.C.value * i_comp['I']

        for c in self.channels:
            if not (c.latent_dtype is None or c.latent_dtype == []):
                tmp = c.kinetics(latent, inpt, state)
                dxdt[c.name] = tmp

        return dxdt
示例#10
0
    def update(self, model, cache=None):
        """
        TODO: Handle truncated Gaussians noise for channel params
        """
        # Keep sufficient stats for a Gaussian noise model
        N = 0
        beta_V_hat = 0
        # beta_ch_hat = 0

        # Get the latent voltages
        for ds in model.data_sequences:
            latent = as_matrix(ds.latent)
            # The transition model is a noisy Hodgkin Huxley proposal
            prop = TruncatedHodgkinHuxleyProposal(
                model.population, ds.t, ds.input,
                as_matrix(np.zeros(1, dtype=model.population.latent_dtype)))
            dt = ds.t[1:] - ds.t[:-1]
            # import pdb; pdb.set_trace()
            pred = np.zeros((latent.shape[0], ds.T - 1))
            for t in np.arange(ds.T - 1):
                pt, _, _ = prop.sample_next(t, latent[:, t, np.newaxis], t + 1)
                pred[:, t] = pt.ravel()

            # pred2,_ = prop.sample_next(np.arange(ds.T-1),
            #                           latent[:,:-1],
            #                           np.arange(1,ds.T))

            # if not np.allclose(pred, pred2):
            #     import pdb; pdb.set_trace()
            for neuron in model.population.neurons:
                for compartment in neuron.compartments:
                    V = get_item_at_path(
                        as_sarray(latent, model.population.latent_dtype),
                        compartment.path)['V']
                    Vpred = get_item_at_path(
                        as_sarray(pred, model.population.latent_dtype),
                        compartment.path)['V']
                    dV = (Vpred - V[1:]) / dt

                    # Update sufficient stats
                    N += len(dV)
                    beta_V_hat += (dV**2).sum()

        # Sample a new beta_V
        sig2_V = 1.0 / np.random.gamma(
            hypers['a_sig_V'].value + N / 2., 1.0 /
            (hypers['b_sig_V'].value + beta_V_hat / 2.))

        hypers['sig_V'].value = np.sqrt(sig2_V)
示例#11
0
    def sample(self, latent, noise=True):
        """
        Sample an observable voltage given the latent state
        :param latent_state:
        :return:
        """
        o = np.zeros(latent.shape, self.observed_dtype)
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        V = x_comp['V']
        assert V.ndim == 1, "V should be 1d"

        # Reshape into chunks of size filterbins
        V2 = V.reshape((-1,self.filterbins,))
        assert V2[0,1] == V[1], "Reshape failed!"

        # Compute the average
        Vlp = V2.sum(axis=1)/np.float(self.filterbins)

        if noise:
            # Add noise to the average
            Vlp += self.sigma.value * np.random.randn(*Vlp.shape)

        # Reshape into the size of V
        Vlp = np.repeat(Vlp, self.filterbins)
        Vlp = Vlp[:len(V)]

        o['V'] = Vlp
        return o
示例#12
0
    def logp(self, latent, observations):
        """
        Compute the log probability of the observations given the latent states

        :param latent:
        :param observations:
        :return:
        """
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        latent_V = x_comp['V']

        o = utils.get_item_at_path(observations, self.path)
        observed_V = o['V']

        logp = -0.5/self.sigma.value**2 * (observed_V-latent_V)**2
        return logp
示例#13
0
    def evaluate_state(self, latent, inpt):
        """
        Evaluate the state of this compartment
        """
        state = np.zeros(latent.shape, dtype=self.state_dtype)
        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        # Alert: Is this true?
        V = x_comp['V']

        G   = (10.6408 - 14.6408*np.exp(-V/42.7671)) / V
        gam = 0.1

        state['I'] = G * (x_ch['O1'] + gam*x_ch['O2']) * (x_comp['V'] - self.E.value)
        return state
示例#14
0
    def logp(self, latent, observations):
        """
        Compute the log probability of the observations given the latent states

        :param latent:
        :param observations:
        :return:
        """
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        latent_V = x_comp['V']

        o = utils.get_item_at_path(observations, self.path)
        observed_V = o['V']

        logp = -0.5 / self.sigma.value**2 * (observed_V - latent_V)**2
        return logp
示例#15
0
    def sample(self, latent, noise=True):
        """
        Sample an observable voltage given the latent state
        :param latent_state:
        :return:
        """
        o = np.zeros(latent.shape, self.observed_dtype)
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        V = x_comp['V']
        assert V.ndim == 1, "V should be 1d"

        # Reshape into chunks of size filterbins
        V2 = V.reshape((
            -1,
            self.filterbins,
        ))
        assert V2[0, 1] == V[1], "Reshape failed!"

        # Compute the average
        Vlp = V2.sum(axis=1) / np.float(self.filterbins)

        if noise:
            # Add noise to the average
            Vlp += self.sigma.value * np.random.randn(*Vlp.shape)

        # Reshape into the size of V
        Vlp = np.repeat(Vlp, self.filterbins)
        Vlp = Vlp[:len(V)]

        o['V'] = Vlp
        return o
示例#16
0
    def update(self, model, cache=None):
        """
        TODO: Handle truncated Gaussians noise for channel params
        """
        # Keep sufficient stats for a Gaussian noise model
        N = 0
        beta_V_hat = 0
        # beta_ch_hat = 0

        # Get the latent voltages
        for ds in model.data_sequences:
            latent = as_matrix(ds.latent)
            # The transition model is a noisy Hodgkin Huxley proposal
            prop = TruncatedHodgkinHuxleyProposal(model.population, ds.t, ds.input,
                                                  as_matrix(np.zeros(1, dtype=model.population.latent_dtype)))
            dt = ds.t[1:] - ds.t[:-1]
            # import pdb; pdb.set_trace()
            pred = np.zeros((latent.shape[0], ds.T-1))
            for t in np.arange(ds.T-1):
                pt,_,_ = prop.sample_next(t, latent[:,t,np.newaxis], t+1)
                pred[:,t] = pt.ravel()

            # pred2,_ = prop.sample_next(np.arange(ds.T-1),
            #                           latent[:,:-1],
            #                           np.arange(1,ds.T))

            # if not np.allclose(pred, pred2):
            #     import pdb; pdb.set_trace()
            for neuron in model.population.neurons:
                for compartment in neuron.compartments:
                    V = get_item_at_path(as_sarray(latent, model.population.latent_dtype),
                                         compartment.path)['V']
                    Vpred = get_item_at_path(as_sarray(pred, model.population.latent_dtype),
                                             compartment.path)['V']
                    dV = (Vpred - V[1:])/dt

                    # Update sufficient stats
                    N += len(dV)
                    beta_V_hat += (dV**2).sum()

        # Sample a new beta_V
        sig2_V = 1.0/np.random.gamma(hypers['a_sig_V'].value + N/2.,
                                     1.0/(hypers['b_sig_V'].value + beta_V_hat/2.))

        hypers['sig_V'].value = np.sqrt(sig2_V)
示例#17
0
    def evaluate_state(self, latent, inpt):
        """
        Evaluate the state of this compartment
        """
        state = np.zeros(latent.shape, dtype=self.state_dtype)
        state['V'] = get_item_at_path(latent, self.path)['V']
        for c in self.channels:
            state[c.name] = c.evaluate_state(latent, inpt)

        return state
示例#18
0
    def get_dV_and_currents(self, model):
        c = self.get_compartment(model)
        # Get the sub-structured arrays for this comp
        chs = c.channels

        dts = []
        dVc_dts = []
        Iscs = []
        for data in model.data_sequences:
            t = data.t
            T = data.T
            inpt = data.input
            state = data.states

            s_comp = get_item_at_path(state, c.path)
            i_comp = get_item_at_path(inpt, c.path)
            Vc = s_comp['V']
            dVc_dt = c.C.value * self.gradient_V(t, Vc)
            dt = np.concatenate((np.diff(t), np.array([t[-1] - t[-2]])))

            # Some of this change is due to injected current
            dVc_dt -= i_comp['I']

            dts.append(dt)
            dVc_dts.append(dVc_dt)

            # Now compute the per channel currents in this compartment
            Isc = np.zeros((T, 0))
            for ch in chs:
                if s_comp[ch.name].dtype.names is not None and \
                   'I' in s_comp[ch.name].dtype.names:
                    Isc = np.concatenate(
                        (Isc, -1.0 * s_comp[ch.name]['I'][:, np.newaxis]),
                        axis=1)

            Iscs.append(Isc)

        # Concatenate the dVs and the currents together
        dt = np.concatenate(dts, axis=0)
        dVc_dt = np.concatenate(dVc_dts, axis=0)
        Isc = np.concatenate(Iscs, axis=0)

        return dVc_dt, Isc, dt
示例#19
0
    def evaluate_state(self, latent, inpt):
        """
        Evaluate the state of this compartment
        """
        state = np.zeros(latent.shape, dtype=self.state_dtype)
        state['V'] = get_item_at_path(latent, self.path)['V']
        for c in self.channels:
            state[c.name] = c.evaluate_state(latent, inpt)

        return state
示例#20
0
    def get_dV_and_currents(self, model):
        c = self.get_compartment(model)
        # Get the sub-structured arrays for this comp
        chs = c.channels

        dts = []
        dVc_dts = []
        Iscs = []
        for data in model.data_sequences:
            t = data.t
            T = data.T
            inpt = data.input
            state = data.states

            s_comp = get_item_at_path(state, c.path)
            i_comp = get_item_at_path(inpt, c.path)
            Vc = s_comp['V']
            dVc_dt = c.C.value * self.gradient_V(t, Vc)
            dt = np.concatenate((np.diff(t), np.array([t[-1]-t[-2]])))

            # Some of this change is due to injected current
            dVc_dt -= i_comp['I']

            dts.append(dt)
            dVc_dts.append(dVc_dt)

            # Now compute the per channel currents in this compartment
            Isc = np.zeros((T,0))
            for ch in chs:
                if s_comp[ch.name].dtype.names is not None and \
                   'I' in s_comp[ch.name].dtype.names:
                    Isc = np.concatenate((Isc, -1.0*s_comp[ch.name]['I'][:,np.newaxis]),
                                         axis=1)

            Iscs.append(Isc)

        # Concatenate the dVs and the currents together
        dt = np.concatenate(dts, axis=0)
        dVc_dt = np.concatenate(dVc_dts, axis=0)
        Isc = np.concatenate(Iscs, axis=0)

        return dVc_dt, Isc, dt
示例#21
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        V = x_comp['V']
        # Use resting potential of zero
        V_ref = V + 60

        m = x_ch['m']
        h = x_ch['h']

        # Compute the alpha and beta as a function of V
        am1 = 0.32*(13.1-V_ref)/(exp((13.1-V_ref)/4)-1)
        ah1 = 0.128*exp((17.0-V_ref)/18.0)

        bm1 = 0.28*(V_ref-40.1)/(exp((V_ref-40.1)/5.0)-1.0)
        bh1 = 4.0/(1.0+exp((40.-V_ref)/5.0))

        # Compute the channel state updates
        dxdt['m'] = am1*(1.-m) - bm1*m
        dxdt['h'] = ah1*(1.-h) - bh1*h

        return dxdt
示例#22
0
    def set_input(self, t, inpt):
        """
        Set the current in each of the connected compartments to the stimulus
        value at time t

        :param t:
        :param inpt:
        :return:
        """
        for c in self.compartments:
            c_inpt = get_item_at_path(inpt, c.path)
            c_inpt['Irr'] = self.stimuluspattern.intensity(t)
示例#23
0
    def sample(self, latent):
        """
        Sample an observable voltage given the latent state
        :param latent_state:
        :return:
        """
        o = np.zeros(latent.shape, self.observed_dtype)
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        V = x_comp['V']

        o['V'] = V + self.sigma.value * np.random.randn(*V.shape)
        return o
示例#24
0
    def sample(self, latent):
        """
        Sample an observable voltage given the latent state
        :param latent_state:
        :return:
        """
        o = np.zeros(latent.shape, self.observed_dtype)
        x_comp = utils.get_item_at_path(latent, self.compartment.path)
        V = x_comp['V']

        o['V'] = V + self.sigma.value * np.random.randn(*V.shape)
        return o
示例#25
0
文件: stimulus.py 项目: HIPS/optofit
    def set_input(self, t, inpt):
        """
        Set the current in each of the connected compartments to the stimulus
        value at time t

        :param t:
        :param inpt:
        :return:
        """
        for c in self.compartments:
            c_inpt = get_item_at_path(inpt, c.path)
            c_inpt['Irr'] = self.stimuluspattern.intensity(t)
示例#26
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        V = x_comp['V']
        # Offset to resting potential of 0
        V_ref = 60 + V

        # Compute the alpha and beta as a function of V
        aa1 = 0.02*(13.1-V_ref)/(exp((13.1-V_ref)/10.)-1)
        ba1 = 0.0175*(V_ref-40.1)/(exp((V_ref-40.1)/10.)-1)

        # Inactivation variable b
        ab1 = 0.0016*exp((-13.0-V_ref)/18.0)
        bb1 = 0.05/(1+exp((10.1-V_ref)/5.0))

        # Compute the channel state updates
        dxdt['a'] = aa1*(1-x_ch['a']) - ba1*x_ch['a']
        dxdt['b'] = ab1*(1-x_ch['b']) - bb1*x_ch['b']

        return dxdt
示例#27
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        V = x_comp['V']
        m = x_ch['m']
        h = x_ch['h']

        # Compute the alpha and beta as a function of V
        am1 = 0.1*(V+35.)/(1-exp(-(V+35.)/10.))
        ah1 = 0.07*exp(-(V+50.)/20.)

        bm1 = 4.*exp(-(V+65.)/18.)
        bh1 = 1./(exp(-(V+35.)/10.)+1.)

        # Compute the channel state updates
        dxdt['m'] = am1*(1.-m) - bm1*m
        dxdt['h'] = ah1*(1.-h) - bh1*h

        return dxdt
示例#28
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        V = x_comp['V']
        c_Ca = x_comp['[Ca]']
        q    = x_ch['q']

        # Offset to resting potential of 0
        V_ref = 60 + V

        # % Compute the alpha and beta as a function of V
        aq1 = np.min((0.2e-4)*c_Ca, 0.01)
        bq1 = 0.001
        
        # % Compute the channel state updates
        dxdt['q'] = aq1*(1-q) - bq1*q

        return dxdt
示例#29
0
    def evaluate_state(self, latent, inpt):
        """
        Evaluate the state of this compartment
        """
        N = len(latent)
        state = np.zeros(N, dtype=self.state_dtype)
        my_latent = get_item_at_path(latent, self.path)
        state['V'] = my_latent['V']
        state['[Ca]'] = my_latent['[Ca]']

        for c in self.channels:
            if c.latent_dtype is not None:
                state[c.name] = c.evaluate_state(latent, inpt)

        return state
示例#30
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        V = x_comp['V']
        # Offset to resting potential of 0
        V_ref = 60 + V

        alpha = 1.6 / (1 + np.exp(-.072 * (V_ref - 65)))
        beta  = .02 * (V_ref - 51.1) / (np.exp((V_ref - 51.1) / 5) - 1)

        r_alpha = np.exp(-V_ref / 20) / 200
        r_alpha[V_ref <= 0] = .005
        r_beta = 0.005 - r_alpha

        dxdt['s'] = alpha * (1 - x_ch['s']) - beta * x_ch['s']
        dxdt['r'] = r_alpha * (1 - x_ch['r']) - r_beta * x_ch['r']
        return dxdt
示例#31
0
    def evaluate_state(self, latent, inpt):
        """
        Evaluate the state of this compartment
        """
        N = len(latent)
        state = np.zeros(N, dtype=self.state_dtype)
        my_latent = get_item_at_path(latent, self.path)
        state['V']    = my_latent['V']
        state['[Ca]'] = my_latent['[Ca]']

        for c in self.channels:
            if c.latent_dtype is not None:
                state[c.name] = c.evaluate_state(latent, inpt)

        return state
示例#32
0
 def get_my(self, inpt):
     if not self.name in inpt.dtype.names:
         return utils.get_item_at_path(inpt, self.compartment.path)
     else:
         return inpt[self.name]
示例#33
0
    def update(self, model, cache=None):
        """
        Sample the conductances of the neuron given its latent state variables
        """
        # c = self.compartment
        c = self.get_compartment(model)
        # Get the sub-structured arrays for this comp
        chs = c.channels

        # Get a list of conductances for this compartment
        gs = [ch.g for ch in chs]
        gsc = np.array([g.value for g in gs])

        dVc_dts = []
        Iscs = []
        for data in model.data_sequences:
            t = data.t
            T = data.T
            inpt = data.input
            state = data.states

            s_comp = get_item_at_path(state, c.path)
            i_comp = get_item_at_path(inpt, c.path)
            Vc = s_comp['V']
            dVc_dt = c.C.value * self.gradient_V(t, Vc)
            dt = np.concatenate((np.diff(t), np.array([t[-1]-t[-2]])))

            # Some of this change is due to injected current
            dVc_dt -= i_comp['I'][:-1]

            dVc_dts.append(dVc_dt)

            # Now compute the per channel currents in this compartment
            Isc = np.zeros((T-1,0))
            for ch in chs:
                if s_comp[ch.name].dtype.names is not None and \
                   'I' in s_comp[ch.name].dtype.names:
                    Isc = np.concatenate((Isc, -1.0*s_comp[ch.name]['I'][:-1,np.newaxis]),
                                         axis=1)

            Iscs.append(Isc)

        # Concatenate the dVs and the currents together
        dVc_dt = np.concatenate(dVc_dts, axis=0)
        Isc = np.concatenate(Iscs, axis=0)

        # Sample each conductance in turn given that
        # C*dVc_dt ~ N(I_in - np.dot(gsc, Isc), sig_V^2)
        for (i,ch) in enumerate(chs):
            i_rem = np.concatenate((np.arange(i), np.arange(i+1,len(chs))))
            gsc_rem = gsc[i_rem]
            Isc_rem = Isc[:,i_rem]

            # prior = gamma(alphas[ch], scale=1.0/betas[ch])
            prior = ch.g.distribution

            dV_resid = dVc_dt - np.dot(Isc_rem, gsc_rem).ravel()

            from scipy.stats import norm
            sig_V = np.asscalar(hypers['sig_V'].value)
            # lkhd = norm(dV_resid[:,np.newaxis], sig_V)

            lkhd = lambda g: (-0.5/sig_V**2 * (np.dot(Isc[:,i][:,np.newaxis], g) - dV_resid[:,np.newaxis])**2).sum(axis=0)

            def _logp(g):
                sh = g.shape
                g2 = np.atleast_2d(g)
                lp = prior.logp(g2)
                # lp += lkhd.logpdf(np.dot(Isc[:,i][:, np.newaxis], g2)).sum(0)
                lp += lkhd(g2)
                return lp.reshape(sh)

            # Evaluate at a few points around the prior mode to seed the ARS
            xs = np.array([.0001, .001, .01, .05, .1, 1.0, 2.0, 4.0, 7.0, 10.0])
            v_xs = _logp(xs)
            assert np.all(np.isfinite(v_xs))

            # Try for a few attempts to find the right bound
            gsc[i] = adaptive_rejection_sample(_logp, xs, v_xs, [ch.g.lower_bound, ch.g.upper_bound])
            
            # Update the channel conductance parameter
            ch.g.value = gsc[i]
示例#34
0
 def get_my(self, inpt):
     if not self.name in inpt.dtype.names:
         return utils.get_item_at_path(inpt, self.compartment.path)
     else:
         return inpt[self.name]
示例#35
0
    def kinetics(self, latent, inpt, state):
        """
        Compute the state kinetics, d{latent}/dt, according to the Hodgkin-Huxley eqns,
        given current state x and external or given variables y.

        latent:  latent state variables of the neuron, e.g. voltage per compartment,
                 channel activation variables, etc.

        inpt:    observations, e.g. supplied irradiance, calcium concentration, injected
                 current, etc.

        state:   evaluated state of the neuron including channel currents, etc.

        returns:
        dxdt:   Rate of change of the latent state variables.
        """
        # import pdb; pdb.set_trace()
        # Initialize dxdt for each latent state
        dxdt = np.zeros(latent.shape, dtype=self.latent_dtype)

        i_comp = get_item_at_path(inpt, self.compartment.path)
        x_comp = get_item_at_path(latent, self.compartment.path)
        x_ch = get_item_at_path(latent, self.path)

        I = i_comp['Irr']
        V = x_comp['V']
        p = x_ch['p']

        # Compute the voltage-sensitive rate constants for state transitions
        Gd1 = 0.075 + 0.043*np.tanh(-(V+20)/20)
        Gd2 = 0.05
        # Gr  = 4.34587e5 * np.exp(-0.0211539274*V)
        Gr = 0.001

        # Define a state variable for time and irradiance dependent activation
        # function for ChR2 (post isomerization)
        theta = 100*I          # Optical stimulation protocol
        tau_chr2 = 1.3         # Time constant for ChR2
        S0   =  0.5*(1+np.tanh(120*(theta-0.1)))
        dxdt['p'] = (S0-p)/tau_chr2

        # Define the light-sensitive rate constants for state transitions
        lamda = 470            # Wavelength of max absorption for retinal
        eps1 = 0.8535          # quantum efficiency for photon absorption from C1
        eps2 = 0.14            # quantum efficiency for photon absorption from C2
        w_loss = 0.77;
        F = 0.00006*I*lamda/w_loss   #Photon flux (molecules/photon/sec)
        # F = (sig_ret/hc)*I*lamda/w_loss*1e-9;   % Photon flux (molecules/photon/sec)

        # Light sensitive rates for C1->01 and C2->O2 transition
        k1 = eps1 * F * p
        k2 = eps2 * F * p

        # Light sensitive O1->02 transitions
        e12d = 0.011
        e12c1 = 0.005
        e12c2 = 0.024
        e12 = e12d + e12c1*np.log(1+I/e12c2)
        # Light sensitive O2->O1 transitions
        e21d = 0.008
        e21c1 = 0.004
        e21c2 = 0.024
        e21 = e21d + e21c1*np.log(1+I/e21c2)

        dxdt['O1'] = k1 * x_ch['C1'] - (Gd1 + e12) * x_ch['O1'] + e21 * x_ch['O2'] 
        dxdt['O2'] = k2 * x_ch['C2'] - (Gd2 + e21) * x_ch['O2'] + e12 * x_ch['O1']
        dxdt['C1'] = Gr * x_ch['C2'] + Gd1 * x_ch['O1'] - k1 * x_ch['C1']
        dxdt['C2'] = Gd2 * x_ch['O2'] + (k2 + Gr) * x_ch['C2']

        return dxdt
示例#36
0
    def update(self, model, cache=None):
        """
        Sample the conductances of the neuron given its latent state variables
        """
        # c = self.compartment
        c = self.get_compartment(model)
        # Get the sub-structured arrays for this comp
        chs = c.channels

        # Get a list of conductances for this compartment
        gs = [ch.g for ch in chs]
        gsc = np.array([g.value for g in gs])

        dVc_dts = []
        Iscs = []
        for data in model.data_sequences:
            t = data.t
            T = data.T
            inpt = data.input
            state = data.states

            s_comp = get_item_at_path(state, c.path)
            i_comp = get_item_at_path(inpt, c.path)
            Vc = s_comp['V']
            dVc_dt = c.C.value * self.gradient_V(t, Vc)
            dt = np.concatenate((np.diff(t), np.array([t[-1] - t[-2]])))

            # Some of this change is due to injected current
            dVc_dt -= i_comp['I'][:-1]

            dVc_dts.append(dVc_dt)

            # Now compute the per channel currents in this compartment
            Isc = np.zeros((T - 1, 0))
            for ch in chs:
                if s_comp[ch.name].dtype.names is not None and \
                   'I' in s_comp[ch.name].dtype.names:
                    Isc = np.concatenate(
                        (Isc, -1.0 * s_comp[ch.name]['I'][:-1, np.newaxis]),
                        axis=1)

            Iscs.append(Isc)

        # Concatenate the dVs and the currents together
        dVc_dt = np.concatenate(dVc_dts, axis=0)
        Isc = np.concatenate(Iscs, axis=0)

        # Sample each conductance in turn given that
        # C*dVc_dt ~ N(I_in - np.dot(gsc, Isc), sig_V^2)
        for (i, ch) in enumerate(chs):
            i_rem = np.concatenate((np.arange(i), np.arange(i + 1, len(chs))))
            gsc_rem = gsc[i_rem]
            Isc_rem = Isc[:, i_rem]

            # prior = gamma(alphas[ch], scale=1.0/betas[ch])
            prior = ch.g.distribution

            dV_resid = dVc_dt - np.dot(Isc_rem, gsc_rem).ravel()

            from scipy.stats import norm
            sig_V = np.asscalar(hypers['sig_V'].value)
            # lkhd = norm(dV_resid[:,np.newaxis], sig_V)

            lkhd = lambda g: (-0.5 / sig_V**2 *
                              (np.dot(Isc[:, i][:, np.newaxis], g) -
                               dV_resid[:, np.newaxis])**2).sum(axis=0)

            def _logp(g):
                sh = g.shape
                g2 = np.atleast_2d(g)
                lp = prior.logp(g2)
                # lp += lkhd.logpdf(np.dot(Isc[:,i][:, np.newaxis], g2)).sum(0)
                lp += lkhd(g2)
                return lp.reshape(sh)

            # Evaluate at a few points around the prior mode to seed the ARS
            xs = np.array(
                [.0001, .001, .01, .05, .1, 1.0, 2.0, 4.0, 7.0, 10.0])
            v_xs = _logp(xs)
            assert np.all(np.isfinite(v_xs))

            # Try for a few attempts to find the right bound
            gsc[i] = adaptive_rejection_sample(
                _logp, xs, v_xs, [ch.g.lower_bound, ch.g.upper_bound])

            # Update the channel conductance parameter
            ch.g.value = gsc[i]
示例#37
0
def plot_latent_compartment_V_and_I(t, data_sequence, compartment, observation,
                                    axs=None, colors=['k'], linewidth=1):

    Z = data_sequence.latent
    S = data_sequence.states
    O = data_sequence.observations
    V = get_item_at_path(Z, compartment.path)['V']
    Ca = get_item_at_path(Z, compartment.path)['[Ca]']

    if isinstance(observation, NewDirectCompartmentVoltage):
        F = get_item_at_path(O, observation.path)['V']
    if isinstance(observation, LowPassCompartmentVoltage):
        F = get_item_at_path(O, observation.path)['V']
    elif isinstance(observation, LinearFluorescence):
        F = get_item_at_path(O, observation.path)['Flr']
    else:
        F = None

    # Check for inputs
    I = np.zeros_like(t)
    try:
        I = get_item_at_path(data_sequence.input, compartment.path)['I']
    except:
        # No input current
        pass

    try:
        I = get_item_at_path(data_sequence.input, compartment.path)['Irr']
    except:
        # No input irradiance
        pass

    # Compute the channel currents
    s_comp = get_item_at_path(S, compartment.path)

    # Num rows = N_ch (oner per channel current) +
    # 1 (input) + 1 (voltage) + 1 (calcium)
    D = len(compartment.channels) + 3

    # Set the relative width of the time series to the conductances
    r = 3

    if axs is None:
        axs = []
        for d in np.arange(D):
            ax = plt.subplot2grid((D,r+1), (d,0), colspan=r)
            axs.append(ax)

        # Add one more axis for the concentrations
        ax = plt.subplot2grid((D,r+1), (0,r), rowspan=D)
        axs.append(ax)
    
    # Plot the voltage)
    axs[0].plot(t, I, color='b', lw=linewidth)
    axs[0].set_ylabel('$I_{%s}$' % compartment.name)

    # Plot the voltage
    axs[1].plot(t, V, color=colors[0], lw=linewidth)
    axs[1].set_ylabel('$V_{%s}$' % compartment.name)

    # Plot the calcium
    axs[2].plot(t, Ca, color=colors[0], lw=linewidth)
    axs[2].set_ylabel('$[Ca]_{%s}$' % compartment.name)

    if F is not None:
        axs[1].plot(t, F, color='b', lw=linewidth)

    for i,ch in enumerate(compartment.channels):
        I = s_comp[ch.name]['I']
        axs[i+3].plot(t, I, color=colors[i % len(colors)], linewidth=linewidth)
        axs[i+3].set_ylabel('$I_{%s}$' % ch.name)

    # Plot the channel densities
    C = len(compartment.channels)
    gs = [ch.g.value for ch in compartment.channels]
    names = [ch.name for ch in compartment.channels]

    axs[-1].bar(np.arange(C), gs, facecolor=colors[0], alpha=0.5)
    axs[-1].set_xticks(0.5+np.arange(C))
    axs[-1].set_xticklabels(map(lambda n: '$g_{%s}$' % n, names))
    axs[-1].set_title('Channel densities')

    return axs