Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inhomogeneous TC activity #142

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions mesocircuit/parameterization/base_network_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,21 @@
# parameters for external stimulus
# optional thalamic input
# options are:
# False: thalamic neurons are created and connected, but they are not
# active
# 'poisson': persistent thalamic poisson input for a given duration to
# all thalamic neurons
# 'pulses': repetitive pulses from stimulating thalamic neurons in the
# center of the network
# False:
# thalamic neurons are created and connected, but they are not
# active
# 'poisson':
# persistent thalamic poisson input for a given duration to
# all thalamic neurons
# 'pulses':
# repetitive pulses from stimulating thalamic neurons in the
# center of the network
# 'inhomogeneous':
# create a n x n grid layer of inhomogeneous poisson processes
# connecting to the thalamac population using square masks
# of dimension L/n x L/n. The rate profile of each process
# is generated as 1/f^2 noise across the spatial and temporal
# dimensions.
'thalamic_input': False,

# thalamic_input = 'poisson'
Expand All @@ -289,6 +298,24 @@
# delay between the pulse spike generator and the thalamic neurons
'th_delay_pulse_generator': 1.0,

# thalamic_input = 'inhomogeneous'
# set up nx x ny grid of inhomogeneous poisson generators
# with a time-variable rate profile for each.
# number of generators across each axis:
'th_inhomogeneous_n': 32,
# mean rate
'th_inhomogeneous_mean': -5,
# standard deviation
'th_inhomogeneous_std' : 10,
# start time
'th_inhomogeneous_start': 100.,
# time resolution (ms)
'th_inhomogeneous_dt' : 1.,
# period (timesteps)
'th_inhomogeneous_nt': 250,
# repeats
'th_inhomogeneous_repeats': 20,

# optional DC input
# turn DC input on or off (True or False)
'dc_input': False,
Expand Down
134 changes: 134 additions & 0 deletions mesocircuit/simulation/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,122 @@ def __create_thalamic_stim_input(self):
positions=nest.spatial.grid(
shape=[1, 1],
edge_wrap=True))
elif self.net_dict['thalamic_input'] == 'inhomogeneous':
self.nonstationary_poisson_input_th = nest.Create(
'inhomogeneous_poisson_generator',
positions=nest.spatial.grid(
shape=[self.net_dict['th_inhomogeneous_n']] * 2,
extent=[self.net_dict['extent']] * 2,
center=[0., 0.],
edge_wrap=True,
),
)

# create spatiotemporally periodic filtered noise (1/f**2 like)
rates, times = self._create_th_inhomogeneous_rates_periodic_noise()

# set rate and time steps
for i in range(self.net_dict['th_inhomogeneous_n']**2):
nest.SetStatus(
self.nonstationary_poisson_input_th[i],
params=dict(
rate_times=times,
rate_values=rates[:, i]
)
)

return

def _create_th_inhomogeneous_rates_periodic_noise(
self,
min_denominator=1E1,
time_scaling=1E-1,
power_exponent=2,
save_rates_times=True):
'''Create rates profiles for each thalamic (or perhaps retinal)
inhomogeneous_poisson_generator node on Rank 0.

This function returns filtered random noise in the Fourier domain
that in the time domain is periodic in both time and space

Parameters
----------
min_denominator: float
positive factor added to the denominator
time_scaling: float
factor
power_exponent: float
factor

save_rates_times: bool
if True (default), save rates and times in output dir

Returns
-------
rates: ndarray
shape (nt * repeats, n**2) array, where the first axis is time,
second over n x n nodes feeding into the TC parrot neuron layer
times: ndarray
shape (nt * repeats, ) ndarray of monotonically increasing
time points corresponding to each piecewise constant rate
'''
nt = self.net_dict['th_inhomogeneous_nt']
nx, ny = [self.net_dict['th_inhomogeneous_n']] * 2
if nest.Rank() == 0:
# create noise in Fourier domain:
NU = np.zeros((nx, ny), dtype=complex)
x, t, y = np.meshgrid(np.arange(nx),
np.arange(nt),
np.arange(ny))
NU = np.exp(
1j * np.random.uniform(0, 2 * np.pi, (nt, nx, ny))
) / (min_denominator + x**2 +
time_scaling * t**2 +
y**2)**power_exponent
# transform to time domain:
nu = np.fft.ifftn(NU).real
# normalize:
nu -= nu.mean()
nu /= nu.std()
# rescale:
nu *= self.net_dict['th_inhomogeneous_std']
nu += self.net_dict['th_inhomogeneous_mean']
# truncate and reshape:
nu[nu < 0] = 0.
nu = nu.reshape((nt, -1))
else:
nu = np.empty((nt, nx * ny), dtype=float)

# broadcast
if MPI.COMM_WORLD.Get_size() > 1:
MPI.COMM_WORLD.Bcast(nu, root=0)

# repeat the time series a certain number of times
nu = np.repeat(
nu, self.net_dict['th_inhomogeneous_repeats'],
axis=0)
times = np.arange(nu.shape[0]) * \
self.net_dict['th_inhomogeneous_dt'] + \
self.net_dict['th_inhomogeneous_start']

if save_rates_times:
# store rate profiles
if MPI.COMM_WORLD.Get_rank() == 0:
np.save(
os.path.join(
self.data_dir_circuit,
'th_inhomogeneous_rates.npy'),
nu)
# store times
np.save(
os.path.join(
self.data_dir_circuit,
'th_inhomogeneous_times.npy'),
times)
MPI.COMM_WORLD.Barrier()

return nu, times

def __create_dc_stim_input(self):
""" Creates DC generators for external stimulation if specified
in ``net_dict``.
Expand Down Expand Up @@ -669,6 +783,26 @@ def __connect_thalamic_stim_input(self):
nest.Connect(self.spike_pulse_input_th, self.pops[-1],
conn_spec=conn_dict_pulse_th,
syn_spec=syn_dict_pulse_th)
elif self.net_dict['thalamic_input'] == 'inhomogeneous':
d = self.net_dict['extent'] / self.net_dict['th_inhomogeneous_n']
conn_spec_inhomogeneous = {
'rule': 'fixed_indegree',
'indegree': 1,
'mask': {
'rectangular': {
'lower_left': [-d / 2, -d / 2],
'upper_right': [d / 2, d / 2]
}
}
}
nest.Connect(
self.nonstationary_poisson_input_th,
self.pops[-1],
conn_spec=conn_spec_inhomogeneous,
)
else:
mssg = f'self.net_dict["thalamic_input"]={self.net_dict["thalamic_input"]} not supported' # noqa 501
raise NotImplementedError(mssg)
return

def __connect_dc_stim_input(self):
Expand Down
33 changes: 33 additions & 0 deletions scripts/parametersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@
'sys_dict': {'hpc': {'network': {'num_nodes': 16}}}
},

# inhomogeneous thalamic activity
'mesocircuit_MAMV1_th_imhomogeneous': {
'net_dict': {
**net_dict_mesocircuit_MAMV1,
'thalamic_input': 'inhomogeneous',
'ext_indegree_scaling': np.array([
#[2, 0.95], # L4E
#[3, 0.95], # L4I
[6, 0.95], # L6E
# [7, 0.95] # L6I
])
},
'sys_dict': {'hpc': {'network': {'num_nodes': 16}}}
},
# Potjans & Diesmann (2014) microcircuit
'microcircuit_PD': {
'net_dict': {
Expand All @@ -65,6 +79,25 @@
'K_scaling': 0.5,
},
},

# inhomogeneous thalamic activity
'local_mesocircuit_MAMV1_th_imhomogeneous': {
'sim_dict': {
**local_sim_dict,
},
'net_dict': {
**net_dict_mesocircuit_MAMV1,
'N_scaling': 0.1,
'K_scaling': 0.5,
'thalamic_input': 'inhomogeneous',
'ext_indegree_scaling': np.array([
[2, 1], # L4E
[3, 0.9], # L4I
[6, 0.9], # L6E
[7, 0.9] # L6I
])
},
},

# MAM V1 microcircuit
'microcircuit_MAMV1': {
Expand Down
9 changes: 5 additions & 4 deletions scripts/run_mesocircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
# choices. These models base on the original microcircuit
# (Potjans and Diesmann, 2014) and are downscaled for execution on a laptop.

name = 'mesocircuit_MAMV1'
# name = 'mesocircuit_MAMV1'
# name = 'local_mesocircuit_PD'
name = 'mesocircuit_MAMV1_th_imhomogeneous'
custom_params = parametersets.ps_dicts[name]

################################################################################
Expand Down Expand Up @@ -65,9 +66,9 @@
jobs=[
'network',
'analysis_and_plotting',
# 'lfp_simulation',
# 'lfp_postprocess',
# 'lfp_plotting',
#'lfp_simulation',
#'lfp_postprocess',
'lfp_plotting',
],
machine='hpc',
# machine='local'
Expand Down