Dealing with objects defined in functions

When Python is the interpreter, what is a good
design for the interface to the basic NEURON
concepts.

Moderator: hines

Post Reply
genis
Posts: 1
Joined: Fri Oct 20, 2023 12:19 pm

Dealing with objects defined in functions

Post by genis »

Hi,
I would like to create a simple function that given a population of neurons, it creates the neuron objects to records its spikes. However, when I put the code in a functions it does not record the spikes but if I run the same code in the main script it actually records the spikes. What is the best way to build such a function? How can let Neuron know of these objects defined inside a function?

Thank you very much in advance.

Code: Select all

# Create a list to hold the Poisson neurons
poisson_neurons = []

# Define the parameters
num_neurons = 50  # Number of Poisson neurons
rate_poisson = 10  # Firing rate (in Hz)
simulation_duration = 1000  # Simulation duration (in ms)


def create_spike_recorder(neurons):
    num_neurons = len(neurons)
    global spike_times, spike_detector
    spike_times = [h.Vector() for i in range(num_neurons)]
    spike_detector = [h.NetCon(neurons[i], None) for i in range(num_neurons)]
    for i in range(num_neurons): spike_detector[i].record(spike_times[i])
    return spike_detector, spike_times


poisson_neurons = []
for i in range(num_neurons):
    syn = h.NetStim()
    syn.interval = 1000.0 / rate_poisson  # Inter-spike interval in ms
    syn.noise = 1
    poisson_neurons.append(syn)

spike_detector_poisson, spike_times_poisson = create_spike_recorder(poisson_neurons)

# Create a spike recorder
spike_times = [h.Vector() for i in range(num_neurons)]
spike_detector = [h.NetCon(poisson_neurons[i], None) for i in range(num_neurons)]
for i in range(num_neurons): spike_detector[i].record(spike_times[i])

# Create a run control for the simulation
h.stdinit()
h.tstop = simulation_duration
h.run()

ted
Site Admin
Posts: 6300
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Dealing with objects defined in functions

Post by ted »

Here's an implementation that does almost everything via procedures, and contains some (not so) latent hints.

Imports and definitions first

Code: Select all

from neuron import h, gui

### Model and simulation parameters

# KISS when developing/debugging
# this means small nets, short run times, few spikes

# make symbolic constants easy to see
FIRST_SPIKE_TIME = 5
MEAN_ISI = 10
DETERMINISTIC = True # for devel/debugging
NUM_CELLS = 3

STIM_DUR = 30
Next

Code: Select all

# be pythonistic but not so pythonistic that C and MATLAB users don't get it 

# create the cell instances and return a list that contains them
def makecells(number):
  clist = []
  for i in range(number):
    cell = h.NetStim()
    cell.start = FIRST_SPIKE_TIME + i
    cell.interval = MEAN_ISI
    cell.nose = 1
    if (DETERMINISTIC): cell.noise = 0
    # for reproducible randomness each NetStim needs to be paired
    # with its own Random123 pseudorandom sequence generator--
    # see guide to Randomness in NEURON models at nrn.readthedocs.io
    clist.append(cell)
  return clist

cells = makecells(NUM_CELLS)
print("cells:")
print(cells) # make sure we got what we expected
Now instrumentation

Code: Select all

# record the cells' spike times and corresponding cell IDs
# to a pair of Vectors
def record_spikes(celllist):
  tspike = h.Vector()
  cid = h.Vector()
  # do things in a way that avoids burying symbolic constants deep in the program
  for cell in celllist:
    nc = h.NetCon(cell, None)
    nc.record(tspike, cid)
    # read NetCon record() docs to discover why
    # this instance of "overwriting nc" is OK
  return tspike, cid

spiketimes, cellids = record_spikes(cells)

# make it easy to see results
def reportspikes(tspike,cid):
  print("total number of spikes", spiketimes.size())
  if (spiketimes.size()>0):
    print(" time\t   \tcell")
    for t, cid in zip(spiketimes, cellids):
      print(f"{t:7.3f} \t{cid}")
  print(" ")
Finally

Code: Select all

# simulation control
h.tstop = STIM_DUR # the only symbolic constant buried so deep in the code
h.run()
reportspikes(spiketimes, cellids)
Post Reply