def test_dither_spike_train_empty_train(self): st = neo.SpikeTrain([] * pq.ms, t_stop=500 * pq.ms) shift = 10 * pq.ms surrog = surr.dither_spike_train(st, shift=shift, n=1)[0] self.assertEqual(len(surrog), 0)
def test_dither_spike_train_empty_train(self): spiketrain = neo.SpikeTrain([] * pq.ms, t_stop=500 * pq.ms) shift = 10 * pq.ms surrogate_train = surr.dither_spike_train( spiketrain, shift=shift, n_surrogates=1)[0] self.assertEqual(len(surrogate_train), 0)
def test_dither_spike_train_output_decimals(self): st = neo.SpikeTrain([90, 150, 180, 350] * pq.ms, t_stop=500 * pq.ms) nr_surr = 2 shift = 10 * pq.ms surrs = surr.dither_spike_train(st, shift=shift, n=nr_surr, decimals=3) for surrog in surrs: for i in range(len(surrog)): self.assertNotEqual(surrog[i] - int(surrog[i]) * pq.ms, surrog[i] - surrog[i])
def test_dither_spike_train_false_edges(self): st = neo.SpikeTrain([90, 150, 180, 350] * pq.ms, t_stop=500 * pq.ms) nr_surr = 2 shift = 10 * pq.ms surrs = surr.dither_spike_train(st, shift=shift, n=nr_surr, edges=False) for surrog in surrs: for i in range(len(surrog)): self.assertLessEqual(surrog[i], st.t_stop)
def test_dither_spike_train_false_edges(self): spiketrain = neo.SpikeTrain( [90, 150, 180, 350] * pq.ms, t_stop=500 * pq.ms) n_surrogates = 2 shift = 10 * pq.ms surrogate_trains = surr.dither_spike_train( spiketrain, shift=shift, n_surrogates=n_surrogates, edges=False) for surrogate_train in surrogate_trains: for i in range(len(surrogate_train)): self.assertLessEqual(surrogate_train[i], spiketrain.t_stop)
def test_dither_spike_train_output_format(self): st = neo.SpikeTrain([90, 150, 180, 350] * pq.ms, t_stop=500 * pq.ms) nr_surr = 2 shift = 10 * pq.ms surrs = surr.dither_spike_train(st, shift=shift, n=nr_surr) self.assertIsInstance(surrs, list) self.assertEqual(len(surrs), nr_surr) for surrog in surrs: self.assertIsInstance(surrs[0], neo.SpikeTrain) self.assertEqual(surrog.units, st.units) self.assertEqual(surrog.t_start, st.t_start) self.assertEqual(surrog.t_stop, st.t_stop) self.assertEqual(len(surrog), len(st))
def test_dither_spike_train_output_format(self): spiketrain = neo.SpikeTrain( [90, 150, 180, 350] * pq.ms, t_stop=500 * pq.ms) n_surrogates = 2 shift = 10 * pq.ms surrogate_trains = surr.dither_spike_train( spiketrain, shift=shift, n_surrogates=n_surrogates) self.assertIsInstance(surrogate_trains, list) self.assertEqual(len(surrogate_trains), n_surrogates) self.assertIsInstance(surrogate_trains[0], neo.SpikeTrain) for surrogate_train in surrogate_trains: self.assertEqual(surrogate_train.units, spiketrain.units) self.assertEqual(surrogate_train.t_start, spiketrain.t_start) self.assertEqual(surrogate_train.t_stop, spiketrain.t_stop) self.assertEqual(len(surrogate_train), len(spiketrain))
def compound_poisson_process(rate, A, t_stop, shift=None, t_start=0 * ms): """ Generate a Compound Poisson Process (CPP; see [1]) with a given amplitude distribution A and stationary marginal rates r. The CPP process is a model for parallel, correlated processes with Poisson spiking statistics at pre-defined firing rates. It is composed of len(A)-1 spike trains with a correlation structure determined by the amplitude distribution A: A[j] is the probability that a spike occurs synchronously in any j spike trains. The CPP is generated by creating a hidden mother Poisson process, and then copying spikes of the mother process to j of the output spike trains with probability A[j]. Note that this function decorrelates the firing rate of each SpikeTrain from the probability for that SpikeTrain to participate in a synchronous event (which is uniform across SpikeTrains). Parameters ---------- rate : quantities.Quantity Average rate of each spike train generated. Can be: - a single value, all spike trains will have same rate rate - an array of values (of length len(A)-1), each indicating the firing rate of one process in output A : array CPP's amplitude distribution. A[j] represents the probability of a synchronous event of size j among the generated spike trains. The sum over all entries of A must be equal to one. t_stop : quantities.Quantity The end time of the output spike trains. shift : None or quantities.Quantity, optional If None, the injected synchrony is exact. If shift is a Quantity, all the spike trains are shifted independently by a random amount in the interval [-shift, +shift]. Default: None t_start : quantities.Quantity, optional The t_start time of the output spike trains. Default: 0 s Returns ------- List of neo.SpikeTrains SpikeTrains with specified firing rates forming the CPP with amplitude distribution A. References ---------- [1] Staude, Rotter, Gruen (2010) J Comput Neurosci 29:327-350. """ # Check A is a probability distribution (it sums to 1 and is positive) if abs(sum(A) - 1) > np.finfo('float').eps: raise ValueError('A must be a probability vector, sum(A)= %f !=1' % (sum(A))) if any([a < 0 for a in A]): raise ValueError( 'A must be a probability vector, all the elements of must be >0') # Check that the rate is not an empty Quantity if rate.ndim == 1 and len(rate.magnitude) == 0: raise ValueError('Rate is an empty Quantity array') # Return empty spike trains for specific parameters elif A[0] == 1 or np.sum(np.abs(rate.magnitude)) == 0: return [ SpikeTrain([] * t_stop.units, t_stop=t_stop, t_start=t_start) for i in range(len(A) - 1) ] else: # Homogeneous rates if rate.ndim == 0: cpp = _cpp_hom_stat(A=A, t_stop=t_stop, rate=rate, t_start=t_start) # Heterogeneous rates else: cpp = _cpp_het_stat(A=A, t_stop=t_stop, rate=rate, t_start=t_start) if shift is None: return cpp # Dither the output spiketrains else: cpp = [ dither_spike_train(cp, shift=shift, edges=True)[0] for cp in cpp ] return cpp
def compound_poisson_process(rate, A, t_stop, shift=None, t_start=0 * ms): """ Generate a Compound Poisson Process (CPP; see [1]) with a given amplitude distribution A and stationary marginal rates r. The CPP process is a model for parallel, correlated processes with Poisson spiking statistics at pre-defined firing rates. It is composed of len(A)-1 spike trains with a correlation structure determined by the amplitude distribution A: A[j] is the probability that a spike occurs synchronously in any j spike trains. The CPP is generated by creating a hidden mother Poisson process, and then copying spikes of the mother process to j of the output spike trains with probability A[j]. Note that this function decorrelates the firing rate of each SpikeTrain from the probability for that SpikeTrain to participate in a synchronous event (which is uniform across SpikeTrains). Parameters ---------- rate : quantities.Quantity Average rate of each spike train generated. Can be: - a single value, all spike trains will have same rate rate - an array of values (of length len(A)-1), each indicating the firing rate of one process in output A : array CPP's amplitude distribution. A[j] represents the probability of a synchronous event of size j among the generated spike trains. The sum over all entries of A must be equal to one. t_stop : quantities.Quantity The end time of the output spike trains. shift : None or quantities.Quantity, optional If None, the injected synchrony is exact. If shift is a Quantity, all the spike trains are shifted independently by a random amount in the interval [-shift, +shift]. Default: None t_start : quantities.Quantity, optional The t_start time of the output spike trains. Default: 0 s Returns ------- List of neo.SpikeTrains SpikeTrains with specified firing rates forming the CPP with amplitude distribution A. References ---------- [1] Staude, Rotter, Gruen (2010) J Comput Neurosci 29:327-350. """ # Check A is a probability distribution (it sums to 1 and is positive) if abs(sum(A) - 1) > np.finfo('float').eps: raise ValueError( 'A must be a probability vector, sum(A)= %f !=1' % (sum(A))) if any([a < 0 for a in A]): raise ValueError( 'A must be a probability vector, all the elements of must be >0') # Check that the rate is not an empty Quantity if rate.ndim == 1 and len(rate.magnitude) == 0: raise ValueError('Rate is an empty Quantity array') # Return empty spike trains for specific parameters elif A[0] == 1 or np.sum(np.abs(rate.magnitude)) == 0: return [ SpikeTrain([] * t_stop.units, t_stop=t_stop, t_start=t_start) for i in range(len(A) - 1)] else: # Homogeneous rates if rate.ndim == 0: cpp = _cpp_hom_stat(A=A, t_stop=t_stop, rate=rate, t_start=t_start) # Heterogeneous rates else: cpp = _cpp_het_stat(A=A, t_stop=t_stop, rate=rate, t_start=t_start) if shift is None: return cpp # Dither the output spiketrains else: cpp = [ dither_spike_train(cp, shift=shift, edges=True)[0] for cp in cpp] return cpp