Search code examples
pythonobjectneuron-simulator

Storing output from Python function necessary despite not using output


I am trying to understand why I must store the output of a Python function (regardless of the name of the variable I use, and regardless of whether I subsequently use that variable). I think this is more general to Python and not specifically to the software NEURON, thus I put it here on Stackoverflow.

The line of interest is here:

clamp_output = attach_current_clamp(cell)

If I just write attach_current_clamp(cell), without storing the output of the function into a variable, the code does not work (plot is empty), and yet I don't use clamp_output at all. Why cannot I not just call the function? Why must I use a variable to store the output even without using the output?

import sys
import numpy
sys.path.append('/Applications/NEURON-7.4/nrn/lib/python')
from neuron import h, gui
from matplotlib import pyplot

#SET UP CELL
class SingleCell(object):
    def __init__(self):
        self.soma = h.Section(name='soma', cell=self)
        self.soma.L = self.soma.diam = 12.6517
        self.all = h.SectionList()
        self.all.wholetree(sec=self.soma)
        self.soma.insert('pas')
        self.soma.e_pas = -65

        for sec in self.all:
            sec.cm = 20
#CURRENT CLAMP
def attach_current_clamp(cell):
    stim = h.IClamp(cell.soma(1))
    stim.delay = 100
    stim.dur = 300
    stim.amp = 0.2
    return stim

cell = SingleCell()

#IF I CALL THIS FUNCTION WITHOUT STORING THE OUTPUT, THEN IT DOES NOT WORK
clamp_output = attach_current_clamp(cell)

#RECORD AND PLOT
soma_v_vec = h.Vector()
t_vec = h.Vector()
soma_v_vec.record(cell.soma(0.5)._ref_v)
t_vec.record(h._ref_t)
h.tstop = 800
h.run()
pyplot.figure(figsize=(8,4))
soma_plot = pyplot.plot(t_vec,soma_v_vec)
pyplot.show()

Solution

  • This is a NEURON+Python specific bug/feature. It has to do with Python garbage collection and the way NEURON implements the Python-HOC interface.

    When there are no more references to a NEURON object (e.g. the IClamp) from within Python or HOC, the object is removed from NEURON.

    Saving the IClamp as a property of the cell averts the problem in the same way as saving the result, so that could be an option for you:

    # In __init__:
    self.IClamps = []
    
    # In attach_current_clamp:
    stim.amp = 0.2
    cell.IClamps.append(stim)
    #return stim