Beispiel #1
0
    def __init__(self, filename, simtime, delta, stabilization_time=0):
        """Create spike times for IG using firing rate over time from
        filename.

        This disregards stimulus onset and duration, and only uses the
        information from the file.

        """
        spikerate = np.load(filename)
        interp = interpolate.interp1d(spikerate['t'], spikerate['Vm'])
        rate_fn = lambda t: interp(t)
        spike_times = nhpp.nhpp_thinning(rate_fn, simtime, delta) * 1e3  # second to millisecond
        spike_times = spike_times[spike_times > stabilization_time].copy()
        self.stimvec = h.Vector(spike_times)
        self.vecstim = h.VecStim()
        self.vecstim.play(self.stimvec)
Beispiel #2
0
def create_pn_output(params):
    """This attempts to create inputs a KC receives from its presynaptic PNs
    References: Mazor and Laurent, 2005; Jortner, et al., 2007.

    Here the assumption is `odor_exc_frac` fraction of all PNs is
    activated by a specific odor, i.e. there firing rate goes up
    (exact formula in code).

    On the other hand, spont_exc_frac of the cells are spontaneously
    active.
    
    npn: total number of PNs

    odor_exc_frac: fraction of PNs that spike in response to odor

    spont_exc_frac: fraction of PNs that spike spontaneously

    stim_rate: baseline firing rate of a PN during odor stimulation

    spont_rate: baseline firing rate of a PN without odor 

    osc_freq: frequency of LFP oscillation


    osc_amp_scale: The amplitude of oscillation as a fraction of
    baseline firing rate (default 0.3 from data from 50000 PNs).
    

    Returns a list of array quantitities containing spike times of
    each PN.

    """
    onset = Q_(params['onset']).to('s').m
    duration = Q_(params['duration']).to('s').m
    tail = Q_(params['tail']).to('s').m
    delta = Q_(params['delta']).to('s').m
    npn = params['npn']
    odor_exc_frac = params['odor_exc_frac']
    spont_exc_frac = params['spont_exc_frac']
    odor_inh_frac = params['odor_inh_frac']
    stim_rate = Q_(params['stim_rate']).to('Hz').m
    spont_rate = Q_(params['spont_rate']).to('Hz').m
    osc_freq = Q_(params['osc_freq']).to('Hz').m
    osc_amp_scale = params['osc_amp_scale']

    assert (odor_exc_frac + odor_inh_frac) <= 1

    spont_amp = spont_rate * osc_amp_scale
    stim_amp = stim_rate * osc_amp_scale
    # Rate function for spontaneously active, excited by odor
    rate_fn_spont_odor = lambda t: \
                         stim_rate + stim_amp * np.sin(2 * np.pi * osc_freq * t) \
                         if (onset < t < (onset + duration)) \
                            else spont_rate + spont_amp * np.sin(2 * np.pi * osc_freq * t)
    # Odor inhibited, but spontaneously active
    rate_fn_odor_inh = lambda t: \
                       0.0 if (onset < t < (onset + duration)) \
                       else spont_rate + spont_amp * np.sin(2 * np.pi * osc_freq * t)
    # Rate function for spontaneously active, unaffected by odor
    rate_fn_spont = lambda t: \
                    spont_rate + spont_amp * np.sin(2 * np.pi * osc_freq * t)
    # rate function for spontaneously silent, activated by odor
    rate_fn_odor = lambda t: \
                   stim_rate + stim_amp * np.sin(2 * np.pi * osc_freq * t) \
                   if (onset < t < (onset + duration)) \
                      else 0.0
    n_spont_odor = int(npn * spont_exc_frac * odor_exc_frac +
                       0.5)  # spontanously active, excited by odor
    n_odor = int(npn * (1 - spont_exc_frac) * odor_exc_frac +
                 0.5)  # silent, activated by odor
    n_odor_inh = int(npn * spont_exc_frac * odor_inh_frac +
                     0.5)  # spontaneously active inhibited by odor
    n_spont = int(npn * spont_exc_frac * (1 - odor_exc_frac - odor_inh_frac) +
                  0.5)
    # Ignore those that are neither spontaneously active nor activated
    # by a given odor: how many such PNs?
    pn_output = []
    start = timer()
    for ii in range(n_spont_odor):
        spike_times = nhpp.nhpp_thinning(rate_fn_spont_odor,
                                         onset + duration + tail, delta)
        pn_output.append(Q_(np.array(spike_times), 's'))
    for ii in range(n_odor):
        spike_times = nhpp.nhpp_thinning(rate_fn_odor, onset + duration + tail,
                                         delta)
        pn_output.append(Q_(np.array(spike_times), 's'))
    for ii in range(n_spont):
        spike_times = nhpp.nhpp_thinning(rate_fn_spont,
                                         onset + duration + tail, delta)
        pn_output.append(Q_(np.array(spike_times), 's'))
    for ii in range(n_odor_inh):
        spike_times = nhpp.nhpp_thinning(rate_fn_odor_inh,
                                         onset + duration + tail, delta)
        pn_output.append(Q_(np.array(spike_times), 's'))
    end = timer()
    logger.info('Time to create {} PN spiketrains {} s'.format(
        len(pn_output), end - start))
    silent = npn - len(pn_output)
    for ii in range(silent):
        pn_output.append(Q_(np.array([]), 's'))
    return pn_output
Beispiel #3
0
def create_shifting_response(params):
    """Create a response pattern with a shifting window into PN population
    over the LFP cycles.

    The step by step process to arrive at this design is in
    try_pn_output.ipynb.
    
    params should have the following key value pairs:

    onset: stimulus / activity onset 
    duration: duration of stimulus
    offdur: duration of off response
    tail: simulation time after the stimulus is over
    trials(=1): number of trials (only `tail` interval between successive stimuli.
    delta: interval at which the Poisson rate is considered.
    npn(=830): total number of PNs    
    odor_exc_shift(=0.1): fraction of excited PN changing state in each LFP cycle
    stim_rate(=20.0Hz): firing rate of excited PN upon odor, i.e. 1 spike in 50 ms    
    spont_rate(=2.6Hz): spontaneous firing rate of a PN
    osc_freq(=20.0Hz): LFP oscillation frequency    
    start_frac: fraction of cells in each group that start spiking simultaneously at the excitation phase of the group

    Returns: 

    pn_spikes - list of lists: i-th entry is a list spike
    times of i-th PN.

    clusters - dict: list of PNs mapped to their stimulus response
    start time. The entries against off response time include bith EI
    and II PNs.

    response_types  - dict: {
      'EE': indices of PNs that spike throughout odor presentation,
      'EI': indices of PNs that spike during first half of odor presentation,
      'IE': indices of PNs that spike during last half of odor presentation,
      'II': indices of PNs that do not spike during  of odor presentation
      'U': spntaneously active and unresponsive to odor stimulus
    }

    """
    npn = params['npn']
    lfp_bin = 50e-3  # second
    spont_rate = params['spont_rate'].to('Hz').m
    delta = params['delta'].to('s').m
    onset = params['onset'].to('s').m
    dur = params['duration'].to('s').m
    tail = params['tail'].to('s').m
    offdur = params['offdur'].to('s').m
    osc_freq = params['osc_freq'].to('Hz').m
    stim_rate = params['stim_rate'].to('Hz').m
    osc_amp_scale = params['osc_amp_scale']
    start_frac = params['start_frac']
    # Indices of different kinds of PNs.
    unresponsive = range(0, int(npn / 3.0))
    EE = list(
        range(unresponsive[-1] + 1, int(unresponsive[-1] + 1 + npn / 6.0)))
    EI = list(range(EE[-1] + 1, int(EE[-1] + 1 + npn / 6.0)))
    IE = list(range(EI[-1] + 1, int(EI[-1] + 1 + npn / 6.0)))
    II = list(range(IE[-1] + 1, npn))
    response_types = {
        'EE': EE,
        'EI': EI,
        'IE': IE,
        'II': II,
        'U': unresponsive
    }
    clusters = defaultdict(list)
    pn_spikes = []
    start = timer()
    # Spontaneous activity in all neurons
    spont_rate_fn = lambda t: spont_rate
    for ii in range(params['npn']):
        st1 = nhpp.nhpp_thinning(spont_rate_fn, onset, delta)
        st2 = nhpp.nhpp_thinning(spont_rate_fn, tail,
                                 delta) + onset + dur + offdur
        pn_spikes.append(list(st1) + list(st2))

    # Unresponsive PNs - first 1/3rd
    for jj, index in enumerate(unresponsive):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(spont_rate_fn, dur + offdur, delta) + onset)

    # Excited throughout odor

    # The rate function: python has dynamic binding - so ee_rate_fn
    # sees the value of `start` at evaluation time.
    ee_rate_fn = lambda t: stim_rate + osc_fn((dur - t) * stim_rate * osc_amp_scale / dur, osc_freq, t)  \
                 if  t > start else 0
    start = 0
    # After every `pnclus` PNs, increase the start time.
    pnclus = round(params['shifting_frac'] * len(EE))
    for jj, index in enumerate(EE):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(ee_rate_fn, dur, delta) + onset)
        clusters[onset + start].append(index)
        diff = jj - len(EE) * start_frac
        if (diff > 0) and (round(diff) % pnclus == 0):
            start += lfp_bin
    # PNs active only in first half of odour presentation
    ei_rate_fn = lambda t: stim_rate + osc_fn((dur - t) * stim_rate * osc_amp_scale / dur, osc_freq, t)  \
                 if  (t > start) and (t < dur/2.0) else 0
    start = 0
    pnclus = round(
        params['shifting_frac'] *
        len(EI))  # How many PNs should share the same starting time?
    for jj, index in enumerate(EI):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(ei_rate_fn, dur, delta) + onset)
        clusters[onset + start].append(index)
        diff = jj - len(EI) * start_frac
        if (diff > 0) and (round(diff) % pnclus == 0):
            start += lfp_bin

    # PNs active only in last half of odour presentation
    ie_rate_fn = lambda t: stim_rate + osc_fn((dur - t) * 2.0 * stim_rate * osc_amp_scale / dur, osc_freq, t) \
                 if  (t > start) else 0
    start = dur / 2.0
    pnclus = round(
        params['shifting_frac'] *
        len(IE))  # How many PNs should share the same starting time?
    for jj, index in enumerate(IE):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(ie_rate_fn, dur, delta) + onset)
        clusters[onset + start].append(index)
        diff = jj - len(IE) * start_frac
        if (diff > 0) and (round(diff) % pnclus == 0):
            start += lfp_bin
    # off response
    off_rate_fn =  lambda t: stim_rate + osc_fn((offdur - t) * stim_rate * osc_amp_scale / offdur, osc_freq, t)  \
                   if  (t > start) else 0
    start = 0
    pnclus = round(
        params['shifting_frac'] *
        len(EI))  # How many PNs should share the same starting time?
    for jj, index in enumerate(EI):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(off_rate_fn, offdur, delta) + onset + dur)
        clusters[onset + dur + start].append(index)
        diff = jj - len(EI) * start_frac
        if (diff > 0) and (round(diff) % pnclus == 0):
            start += lfp_bin
    start = 0
    pnclus = round(
        params['shifting_frac'] *
        len(II))  # How many PNs should share the same starting time?
    for jj, index in enumerate(II):
        pn_spikes[index] += list(
            nhpp.nhpp_thinning(off_rate_fn, offdur, delta) + onset + dur)
        clusters[onset + dur + start].append(index)
        diff = jj - len(II) * start_frac
        if (diff > 0) and (round(diff) % pnclus == 0):
            start += lfp_bin
    qst = []
    for ii, st in enumerate(pn_spikes):
        st = np.array(st)
        st.sort()
        qst.append(Q_(st, 's'))
    pn_spikes = qst
    end = timer()
    logger.info('Finished PN output creation in {} s'.format(end - start))
    return pn_spikes, clusters, response_types
Beispiel #4
0
                                        replace=True)
 synsecs = [g.nodes[n]['orig'] for n in synnodes]
 synsegs = [sec(1.0) for sec in synsecs]
 # Create the exp2syn
 # ereversal = 0 for glutamatergic synapse
 synlist = nu.insert_exp2syn(synsegs, args.rise_t, args.decay_t, 0.0)
 print('Number of synapses', syncount, 'synlist', len(synlist))
 # Create stimulation system
 t_stop = args.simtime
 delta_t = 10.0
 # Build a rate function which linearly goes down from maxrate at
 # t=0 to 0 at t = t_stop.
 rate_fn = lambda t: maxrate * (args.dur - t) / (args.dur)
 spiketimes_list = []
 for syn in synlist:
     spiketimes = nhpp_thinning(rate_fn, args.dur, delta_t)
     spiketimes_list.append(spiketimes + args.onset)
 netcons, stimlist, stimvecs = connect_independent_stimuli(spiketimes_list,
                                                           synlist,
                                                           threshold=-20.0,
                                                           delay=0.0,
                                                           weight=args.gmax)
 if args.rec <= 0:
     rec = [(n, data['orig']) for n, data in g.nodes(data=True)
            if data['orig'] is not None]
 else:
     rec = [(n, g.nodes[n]['orig']) for n in nu.select_good_nodes_by_sid(
         g, stype_node_map.keys(), [args.rec] * len(stype_node_map))]
 syn = zip(synnodes, synsecs)
 rec = list(set(rec + syn))
 recnodes, recsecs = zip(*rec)