Exemplo n.º 1
0
 def _assert_ticbase_change_raises_and_reset(self, after_call):
     """Assert that changing tic-base raises a NESTError, and reset the kernel"""
     with self.assertRaises(nest.kernel.NESTError,
                            msg=f'after calling "{after_call}"'):
         # For co-dependent properties, we use `set()` instead of kernel attributes
         nest.set(resolution=0.5, tics_per_ms=1500.0)
     nest.ResetKernel()
Exemplo n.º 2
0
    def test_multiple_synapse_deletion_one_to_one(self):
        for syn_model in nest.Models('synapses'):
            if syn_model not in self.exclude_synapse_model:
                nest.ResetKernel()
                nest.CopyModel('static_synapse', 'my_static_synapse')
                nest.SetDefaults(syn_model, {'delay': 0.5})
                syn_dict = {
                    'synapse_model': syn_model,
                    'pre_synaptic_element': 'SE1',
                    'post_synaptic_element': 'SE2'
                }
                # For co-dependent properties, we use `set()` instead of kernel attributes
                nest.set(min_delay=0.1, max_delay=1.0)
                nest.structural_plasticity_synapses = {'syn1': syn_dict}
                neurons = nest.Create(
                    'iaf_psc_alpha', 10, {
                        'synaptic_elements': {
                            'SE1': {
                                'z': 0.0,
                                'growth_rate': 0.0
                            },
                            'SE2': {
                                'z': 0.0,
                                'growth_rate': 0.0
                            }
                        }
                    })

                nest.Connect(neurons, neurons, "all_to_all", syn_dict)

                # Test if the connected synaptic elements before the simulation
                # are correct
                status = nest.GetStatus(neurons, 'synaptic_elements')
                for st_neuron in status:
                    self.assertEqual(10, st_neuron['SE1']['z_connected'])
                    self.assertEqual(10, st_neuron['SE2']['z_connected'])

                src_neurons = neurons[:5]
                tgt_neurons = neurons[5:]

                conns = nest.GetConnections(src_neurons, tgt_neurons,
                                            syn_model)
                assert conns

                conndictionary = {'rule': 'one_to_one'}
                syndictionary = {'synapse_model': syn_model}
                nest.Disconnect(src_neurons, tgt_neurons, conndictionary,
                                syndictionary)
                status = nest.GetStatus(neurons, 'synaptic_elements')
                for st_neuron in status[0:5]:
                    self.assertEqual(9, st_neuron['SE1']['z_connected'])
                    self.assertEqual(10, st_neuron['SE2']['z_connected'])
                for st_neuron in status[5:10]:
                    self.assertEqual(10, st_neuron['SE1']['z_connected'])
                    self.assertEqual(9, st_neuron['SE2']['z_connected'])
Exemplo n.º 3
0
    def test_models(self):
        """Time objects in models correctly updated"""
        # Generate a dictionary of reference values for each model.
        reference = {}
        for model in nest.Models():
            if model in self.ignored_models:
                continue
            try:
                reference[model] = nest.GetDefaults(model)
            except nest.kernel.NESTError:
                # If we can't get the defaults, we ignore the model.
                pass

        # Change the tic-base.
        nest.set(resolution=0.5, tics_per_ms=1500.0)

        # At this point, Time objects in models should have been updated to
        # account for the new tic-base. Values in model defaults should therefore
        # be equal (within a tolerance) to the reference values.

        failing_models = []
        for model in reference.keys():
            model_reference = reference[model]
            model_defaults = nest.GetDefaults(model)
            # Remove entries where the item contains more than one value, as this causes issues when comparing.
            array_keys = [
                key for key, value in model_defaults.items()
                if isinstance(value, (list, tuple, dict, np.ndarray))
            ]
            for key in array_keys:
                del model_defaults[key]
                del model_reference[key]

            keydiff = []
            for key, value in model_defaults.items():
                # value may not be a number, so we test for equality first.
                # If it's not equal to the reference value, we assume it is a number.
                if value != model_reference[key] and abs(
                        value - model_reference[key]) > self.eps:
                    print(value - model_reference[key])
                    keydiff.append([key, model_reference[key], value])
            # If any keys have values different from the reference, the model fails.
            if len(keydiff) > 0:
                print(model, keydiff)
                failing_models.append(model)

        # No models should fail for the test to pass.
        self.assertEqual([], failing_models)
Exemplo n.º 4
0
 def test_register_synapses(self):
     for syn_model in nest.synapse_models:
         if syn_model not in self.exclude_synapse_model:
             nest.ResetKernel()
             nest.SetDefaults(syn_model, {'delay': 0.5})
             syn_dict = {
                 'synapse_model': syn_model,
                 'pre_synaptic_element': 'SE1',
                 'post_synaptic_element': 'SE2'
             }
             # For co-dependent properties, we use `set()` instead of kernel attributes
             nest.set(min_delay=0.1, max_delay=1.0)
             nest.structural_plasticity_synapses = {'syn1': syn_dict}
             kernel_status = nest.structural_plasticity_synapses
             assert 'syn1' in kernel_status
             assert kernel_status['syn1'] == extract_dict_a_from_b(kernel_status['syn1'], syn_dict)
Exemplo n.º 5
0
 def test_set(self):
     """
     Test the `nest` module's `.set` function, `KernelAttribute` assignment and errors
     on unknown attribute assignment.
     """
     # Setting the value of unknown attributes should error. Prevents user errors.
     with self.assertRaises(AttributeError,
                            msg="arbitrary attribute assignment passed"):
         nest.absolutelyUnknownThingOnNestModule = 5
     # Don't allow non-KA to be replaced on the module.
     with self.assertRaises(AttributeError,
                            msg="known attribute assignment passed"):
         nest.get = 5
     nest.set(total_num_virtual_procs=2)
     self.assertEqual(2, nest.total_num_virtual_procs, 'set failed')
     nest.total_num_virtual_procs = 3
     self.assertEqual(3, nest.total_num_virtual_procs,
                      'kernelattribute set failed')
Exemplo n.º 6
0
    def run_protocol(self, pre_post_shift):
        """
        Create network and simulate for each delta value.

        Returns a dict with the synaptic weight at end of simulation for
        plain and precise parrots, one weight per delta value.

        All values for the plain parrot case should be identical, and
        the values for the precise parrot case should converge to that value
        for delta -> 0.

        All delta values must fulfill

           multiplicity * delta < resolution / 2

        so that in the plain case off-grid spike times are rounded up
        to the end of the step and thus belong to the same step as the
        corresponding precise spikes.

        :param pre_post_shift: Delay between pre- and postsynaptic trains
        :returns: {'parrot': [<weights>], 'parrot_ps': [<weights>]}
        """

        multiplicity = 2**3
        resolution = 2.**-4
        tics_per_ms = 1. / resolution * multiplicity * 4
        deltas = [resolution / multiplicity / 2**m for m in range(2, 10)]

        delay = 1.

        # k spikes will be emitted at these two times
        pre_spike_times_base = [100., 200.]

        nest.set_verbosity("M_WARNING")

        post_weights = {'parrot': [], 'parrot_ps': []}

        for delta in deltas:
            assert multiplicity * delta < resolution / 2., "Test inconsistent."

            nest.ResetKernel()
            # For co-dependent properties, we use `set()` instead of kernel attributes
            nest.set(resolution=resolution, tics_per_ms=tics_per_ms)

            pre_times = sorted(t_base - k * delta
                               for t_base in pre_spike_times_base
                               for k in range(multiplicity))
            post_times = [pre_time + pre_post_shift for pre_time in pre_times]

            # create spike_generators with these times
            pre_sg = nest.Create("spike_generator",
                                 params={
                                     "spike_times": pre_times,
                                     'allow_offgrid_times': True
                                 })
            post_sg = nest.Create("spike_generator",
                                  params={
                                      "spike_times": post_times,
                                      'allow_offgrid_times': True
                                  })
            pre_sg_ps = nest.Create("spike_generator",
                                    params={
                                        "spike_times": pre_times,
                                        'precise_times': True
                                    })
            post_sg_ps = nest.Create("spike_generator",
                                     params={
                                         "spike_times": post_times,
                                         'precise_times': True
                                     })

            # create parrot neurons and connect spike_generators
            pre_parrot = nest.Create("parrot_neuron")
            post_parrot = nest.Create("parrot_neuron")
            pre_parrot_ps = nest.Create("parrot_neuron_ps")
            post_parrot_ps = nest.Create("parrot_neuron_ps")

            nest.Connect(pre_sg, pre_parrot, syn_spec={"delay": delay})
            nest.Connect(post_sg, post_parrot, syn_spec={"delay": delay})
            nest.Connect(pre_sg_ps, pre_parrot_ps, syn_spec={"delay": delay})
            nest.Connect(post_sg_ps, post_parrot_ps, syn_spec={"delay": delay})

            # create spike recorder --- debugging only
            spikes = nest.Create("spike_recorder")
            nest.Connect(
                pre_parrot + post_parrot + pre_parrot_ps + post_parrot_ps,
                spikes)

            # connect both parrot neurons with a stdp synapse onto port 1
            # thereby spikes transmitted through the stdp connection are
            # not repeated postsynaptically.
            nest.Connect(pre_parrot,
                         post_parrot,
                         syn_spec={
                             'synapse_model': 'stdp_synapse',
                             'receptor_type': 1
                         })
            nest.Connect(pre_parrot_ps,
                         post_parrot_ps,
                         syn_spec={
                             'synapse_model': 'stdp_synapse',
                             'receptor_type': 1
                         })

            # get STDP synapse and weight before protocol
            syn = nest.GetConnections(source=pre_parrot,
                                      synapse_model="stdp_synapse")
            w_pre = syn.get('weight')
            syn_ps = nest.GetConnections(source=pre_parrot_ps,
                                         synapse_model="stdp_synapse")
            w_pre_ps = syn_ps.get('weight')

            sim_time = max(pre_times + post_times) + 5 * delay
            nest.Simulate(sim_time)

            # get weight post protocol
            w_post = syn.get('weight')
            w_post_ps = syn_ps.get('weight')

            assert w_post != w_pre, "Plain parrot weight did not change."
            assert w_post_ps != w_pre_ps, "Precise parrot \
                weight did not change."

            post_weights['parrot'].append(w_post)
            post_weights['parrot_ps'].append(w_post_ps)

        if DEBUG_PLOTS:
            fig, ax = plt.subplots(nrows=2)
            fig.suptitle("Final obtained weights")
            ax[0].plot(post_weights["parrot"], marker="o", label="parrot")
            ax[0].plot(post_weights["parrot_ps"],
                       marker="o",
                       label="parrot_ps")
            ax[0].set_ylabel("final weight")
            ax[0].set_xticklabels([])
            ax[1].semilogy(np.abs(
                np.array(post_weights["parrot"]) -
                np.array(post_weights["parrot_ps"])),
                           marker="o",
                           label="error")
            ax[1].set_xticks([i for i in range(len(deltas))])
            ax[1].set_xticklabels(["{0:.1E}".format(d) for d in deltas])
            ax[1].set_xlabel("timestep [ms]")
            for _ax in ax:
                _ax.grid(True)
                _ax.legend()
            plt.savefig("/tmp/test_stdp_multiplicity.png")
            plt.close(fig)
        print(post_weights)
        return post_weights
    def test_models(self):
        """Time objects in models correctly updated"""

        # These parameters are automatically adjusted upon changes to
        # the tic base or the resolution so they should explicitly not
        # be the same after a change of those. We therefore exclude
        # them from the checks below.
        ignored_params = {
            "correlation_detector": ["delta_tau"],
            "correlomatrix_detector": ["delta_tau"],
            "correlospinmatrix_detector": ["delta_tau"],
            "noise_generator": ["dt"],
        }

        # Generate a dictionary of reference values for each model.
        reference = {}
        for model in nest.node_models + nest.synapse_models:
            if model in self.ignored_models:
                continue
            try:
                reference[model] = nest.GetDefaults(model)
            except nest.kernel.NESTError:
                # If we can't get the defaults, we ignore the model.
                pass

        # Change the tic-base.
        nest.set(resolution=0.5, tics_per_ms=1500.0)

        # At this point, Time objects in models should have been updated to
        # account for the new tic-base. Values in model defaults should therefore
        # be equal (within a tolerance) to the reference values.

        failing_models = []
        for model in reference.keys():
            model_reference = reference[model]
            model_defaults = nest.GetDefaults(model)
            # Remove entries where the item contains more than one value, as this causes issues when comparing.
            array_keys = [
                key for key, value in model_defaults.items()
                if isinstance(value, (list, tuple, dict, np.ndarray))
            ]
            for key in array_keys:
                del model_defaults[key]
                del model_reference[key]

            keydiff = []
            for key, value in model_defaults.items():
                if model in ignored_params and key in ignored_params[model]:
                    continue

                # value may not be a number, so we test for equality first.
                # If it's not equal to the reference value, we assume it is a number.
                if value != model_reference[key] and abs(
                        value - model_reference[key]) > self.eps:
                    print(value - model_reference[key])
                    keydiff.append([key, model_reference[key], value])

            # If any keys have values different from the reference, the model fails.
            if len(keydiff) > 0:
                print(model, keydiff)
                failing_models.append(model)

        # No models should fail for the test to pass.
        self.assertEqual([], failing_models)