A layer 5 pyramidal neuron implemented with NEURON

In this example we illustrate how we can subclass a NeuronModel to customize the methods. We select a set of reduced models of layer 5 pyramidal neurons (Bahl et al., 2012). The code for this example is found in /examples/bahl/uq_bahl.py. To be able to run this example you require both the NEURON simulator, as well as the layer 5 pyramidal neuron model saved in the folder /bahl_model/.

Since the model is implemented in NEURON, we use the NeuronModel. The problem is that this model require us to recalculate certain properties of the model after the parameters have been set. We therefore have to make change to the NeuronModel class so we recalculate these properties. The standard run() method implemented in NeuronModel calls set_parameters() to set the parameters. We therefore only need to change this method in the NeuronModel. First we subclass NeuronModel. For ease of use, we hardcode in the path to the Bahl model.

# Subclassing NeuronModel
class NeuronModelBahl(un.NeuronModel):
    def __init__(self, stimulus_start=None, stimulus_end=None):
        # Hardcode the path of the Bahl neuron model
        super(NeuronModelBahl, self).__init__(interpolate=True,
                                              path="bahl_model",
                                              stimulus_start=stimulus_start,
                                              stimulus_end=stimulus_end)

We then implement a new set_parameters method, that recalculates the required properties after the parameters have been set.

    # Reimplement the set_parameters method used by run
    def set_parameters(self, parameters):
        for parameter in parameters:
            self.h(parameter + " = " + str(parameters[parameter]))

        # These commands must be added for this specific
        # model to recalculate the parameters after they have been set
        self.h("recalculate_passive_properties()")
        self.h("recalculate_channel_densities()")

Now we can initialize our new model.

# Initialize the model with the start and end time of the stimulus
model = NeuronModelBahl(stimulus_start=100, stimulus_end=600)

We can then create the uncertain parameters, which we here set to be "e_pas" and "apical Ra". Here we do not create a Parameter object, but use the parameter list directly, to show that this option exists.

# Define a parameter list and use it directly
parameters = {"e_pas": cp.Uniform(-60, -85),
              "apical Ra": cp.Uniform(150, 300)}

The we use SpikingFeatures.

# Initialize the features
features = un.SpikingFeatures()

Lastly we set up and perform the uncertainty quantification and sensitivity analysis.

# Perform the uncertainty quantification
UQ = un.UncertaintyQuantification(model=model,
                                  parameters=parameters,
                                  features=features)
data = UQ.quantify()

The complete code becomes:

import uncertainpy as un
import chaospy as cp

# Subclassing NeuronModel
class NeuronModelBahl(un.NeuronModel):
    def __init__(self, stimulus_start=None, stimulus_end=None):
        # Hardcode the path of the Bahl neuron model
        super(NeuronModelBahl, self).__init__(interpolate=True,
                                              path="bahl_model",
                                              stimulus_start=stimulus_start,
                                              stimulus_end=stimulus_end)

    # Reimplement the set_parameters method used by run
    def set_parameters(self, parameters):
        for parameter in parameters:
            self.h(parameter + " = " + str(parameters[parameter]))

        # These commands must be added for this specific
        # model to recalculate the parameters after they have been set
        self.h("recalculate_passive_properties()")
        self.h("recalculate_channel_densities()")


# Initialize the model with the start and end time of the stimulus
model = NeuronModelBahl(stimulus_start=100, stimulus_end=600)

# Define a parameter list and use it directly
parameters = {"e_pas": cp.Uniform(-60, -85),
              "apical Ra": cp.Uniform(150, 300)}

# Initialize the features
features = un.SpikingFeatures()

# Perform the uncertainty quantification
UQ = un.UncertaintyQuantification(model=model,
                                  parameters=parameters,
                                  features=features)
data = UQ.quantify()