Skip to content

Define Experiments

Introduction#

This example demonstrates how to use the CompNeuroExp class to combine simulations, model and recordings in an experiment. It is shown how to define an experiment, how to run it and how to get the results.

Code#

from CompNeuroPy import (
    CompNeuroExp,
    CompNeuroSim,
    CompNeuroMonitors,
    CompNeuroModel,
    current_step,
    current_ramp,
    PlotRecordings,
)
from CompNeuroPy.full_models import HHmodelBischop
from ANNarchy import dt, setup, get_population


### combine both simulations and recordings in an experiment
class MyExp(CompNeuroExp):
    """
    Define an experiment by inheriting from CompNeuroExp.

    CompNeuroExp provides the attributes:

        monitors (CompNeuroMonitors):
            a CompNeuroMonitors object to do recordings, define during init otherwise
            None
        data (dict):
            a dictionary for storing any optional data

    and the functions:
        reset():
            resets the model and monitors
        results():
            returns a results object
    """

    def __init__(
        self,
        model: CompNeuroModel,
        sim_step: CompNeuroSim,
        sim_ramp: CompNeuroSim,
        monitors: CompNeuroMonitors,
    ):
        """
        Initialize the experiment and additionally store the model and simulations.

        Args:
            model (CompNeuroModel):
                a CompNeuroModel object
            sim_step (CompNeuroSim):
                a CompNeuroSim object for the step simulation
            sim_ramp (CompNeuroSim):
                a CompNeuroSim object for the ramp simulation
            monitors (CompNeuroMonitors):
                a CompNeuroMonitors object
        """
        self.model = model
        self.sim_step = sim_step
        self.sim_ramp = sim_ramp
        super().__init__(monitors)

    def run(self, E_L: float = -68.0):
        """
        Do the simulations and recordings.

        To use the CompNeuroExp class, you need to define a run function which
        does the simulations and recordings. The run function should return the
        results object which can be obtained by calling self.results().

        Args:
            E_L (float, optional):
                leak reversal potential of the population, which is set at the beginning
                of the experiment run. Default: -68 mV

        Returns:
            results (CompNeuroExp._ResultsCl):
                results object with attributes:
                    recordings (list):
                        list of recordings
                    recording_times (recording_times_cl):
                        recording times object
                    mon_dict (dict):
                        dict of recorded variables of the monitors
                    data (dict):
                        dict with optional data stored during the experiment
        """
        ### call reset at the beginning of the experiment to ensure that the model
        ### is in the same state at the beginning of each experiment run
        self.reset()

        ### also always start the monitors, they are stopped automatically at the end
        self.monitors.start()

        ### set the leak reversal potential of the population, be aware that this
        ### will be undone by the reset function if you don't set the parameters
        ### argument to False
        get_population(self.model.populations[0]).E_L = E_L

        ### SIMULATION START
        sim_step.run()
        ### if you want to reset the model, you should use the objects reset()
        ### it's the same as the ANNarchy reset + it resets the CompNeuroMonitors
        ### creating a new chunk, optionally not changing the parameters
        self.reset(parameters=False)
        sim_ramp.run()
        ### SIMULATION END

        ### optional: store anything you want in the data dict, for example information
        ### about the simulations
        self.data["sim"] = [sim_step.simulation_info(), sim_ramp.simulation_info()]
        self.data["population_name"] = self.model.populations[0]
        self.data["time_step"] = dt()

        ### return results using self.results()
        return self.results()


if __name__ == "__main__":
    ### create and compile a model
    setup(dt=0.01)
    model = HHmodelBischop()

    ### define recordings before experiment
    monitors = CompNeuroMonitors({model.populations[0]: ["v"]})

    ### define some simulations e.g. using CompNeuroSim
    sim_step = CompNeuroSim(
        simulation_function=current_step,
        simulation_kwargs={
            "pop": model.populations[0],
            "t1": 500,
            "t2": 500,
            "a1": 0,
            "a2": 50,
        },
    )
    sim_ramp = CompNeuroSim(
        simulation_function=current_ramp,
        simulation_kwargs={
            "pop": model.populations[0],
            "a0": 0,
            "a1": 100,
            "dur": 1000,
            "n": 50,
        },
    )

    ### init and run the experiment
    my_exp = MyExp(monitors=monitors, model=model, sim_step=sim_step, sim_ramp=sim_ramp)

    ### one use case is to run an experiment multiple times e.g. with different
    ### parameters
    results_run1 = my_exp.run()
    results_run2 = my_exp.run(E_L=-90.0)

    ### plot of the membrane potential from the first and second chunk using results
    ### experiment run 1
    PlotRecordings(
        figname="example_experiment_sim_step.png",
        recordings=results_run1.recordings,
        recording_times=results_run1.recording_times,
        chunk=0,
        shape=(1, 1),
        plan={
            "position": [1],
            "compartment": [results_run1.data["population_name"]],
            "variable": ["v"],
            "format": ["line"],
        },
    )
    PlotRecordings(
        figname="example_experiment_sim_ramp.png",
        recordings=results_run1.recordings,
        recording_times=results_run1.recording_times,
        chunk=1,
        shape=(1, 1),
        plan={
            "position": [1],
            "compartment": [results_run1.data["population_name"]],
            "variable": ["v"],
            "format": ["line"],
        },
    )
    ### experiment run 2
    PlotRecordings(
        figname="example_experiment2_sim_step.png",
        recordings=results_run2.recordings,
        recording_times=results_run2.recording_times,
        chunk=0,
        shape=(1, 1),
        plan={
            "position": [1],
            "compartment": [results_run2.data["population_name"]],
            "variable": ["v"],
            "format": ["line"],
        },
    )
    PlotRecordings(
        figname="example_experiment2_sim_ramp.png",
        recordings=results_run2.recordings,
        recording_times=results_run2.recording_times,
        chunk=1,
        shape=(1, 1),
        plan={
            "position": [1],
            "compartment": [results_run2.data["population_name"]],
            "variable": ["v"],
            "format": ["line"],
        },
    )

    ### print data and mon_dict from results
    print("\nrun1:")
    print("    data:")
    for key, value in results_run1.data.items():
        print(f"        {key}:", value)
    print("    mon_dict:")
    for key, value in results_run1.mon_dict.items():
        print(f"        {key}:", value)
    print("\nrun2:")
    print("    data:")
    for key, value in results_run2.data.items():
        print(f"        {key}:", value)
    print("    mon_dict:")
    for key, value in results_run2.mon_dict.items():
        print(f"        {key}:", value)

Console Output#

$ python experiment.py 
ANNarchy 4.7 (4.7.3b) on linux (posix).
Compiling ...  OK 
Generate fig example_experiment_sim_step.png... Done

Generate fig example_experiment_sim_ramp.png... Done

Generate fig example_experiment2_sim_step.png... Done

Generate fig example_experiment2_sim_ramp.png... Done


run1:
    data:
        sim: [<CompNeuroPy.generate_simulation.SimInfo object at 0x7f4798dfb700>, <CompNeuroPy.generate_simulation.SimInfo object at 0x7f4798dfad40>]
        population_name: HH_Bischop
        time_step: 0.01
    mon_dict:
        HH_Bischop: ['v']

run2:
    data:
        sim: [<CompNeuroPy.generate_simulation.SimInfo object at 0x7f4798dfb700>, <CompNeuroPy.generate_simulation.SimInfo object at 0x7f4798dfad40>]
        population_name: HH_Bischop
        time_step: 0.01
    mon_dict:
        HH_Bischop: ['v']