From 184e00b88ae02d6a34ba2b21e1bf8377beae727c Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 9 Jun 2020 17:37:19 +0100 Subject: [PATCH 01/11] Tweaking bits and pieces of Python style --- spynnaker/pyNN/abstract_spinnaker_common.py | 21 +- .../external_device_lif_control.py | 4 +- .../pyNN/models/common/neuron_recorder.py | 6 +- .../connectors/abstract_connector.py | 7 +- .../connectors/from_list_connector.py | 10 +- .../neuron/abstract_population_vertex.py | 27 +-- .../abstract_pynn_neuron_model_standard.py | 2 +- .../implementations/neuron_impl_standard.py | 4 +- .../neuron/neuron_models/neuron_model_izh.py | 4 +- ...timing_dependence_pfister_spike_triplet.py | 10 +- .../timing_dependence_recurrent.py | 4 +- .../timing_dependence_spike_nearest_pair.py | 3 +- .../timing_dependence_spike_pair.py | 2 +- .../timing_dependence_vogels_2011.py | 2 +- .../synapse_dynamics/synapse_dynamics_stdp.py | 8 +- .../synapse_dynamics_structural_static.py | 3 +- .../synapse_dynamics_structural_stdp.py | 2 +- spynnaker/pyNN/models/neuron/synapse_io.py | 5 +- .../pyNN/models/pynn_population_common.py | 32 +-- .../pyNN/models/pynn_projection_common.py | 11 +- .../spike_source/spike_source_array_vertex.py | 8 +- .../spike_source_poisson_vertex.py | 31 ++- .../synapse_expander/synapse_expander.py | 4 +- .../on_chip_bit_field_generator.py | 210 +++++++++--------- ...ker_machine_bit_field_router_compressor.py | 19 +- ...pynnaker_external_device_plugin_manager.py | 12 +- .../pyNN/utilities/bit_field_utilities.py | 23 +- unittests/mocks.py | 7 +- 28 files changed, 232 insertions(+), 249 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index b2be34f041..233da03c7d 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -17,21 +17,22 @@ import math import os from six import with_metaclass - -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION from spinn_utilities.abstract_base import AbstractBase from spinn_utilities.log import FormatAdapter from spinn_front_end_common.interface.abstract_spinnaker_base import ( AbstractSpinnakerBase) +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.utilities.exceptions import ConfigurationException from spinn_front_end_common.utility_models import CommandSender from spinn_front_end_common.utilities.utility_objs import ExecutableFinder -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import unset_simulator from spinn_front_end_common.utilities.helpful_functions import read_config from spynnaker.pyNN.models.utility_models import synapse_expander from spynnaker.pyNN import overridden_pacman_functions, model_binaries -from spynnaker.pyNN.utilities import constants +from spynnaker.pyNN.utilities.constants import ( + MAX_DELAY_BLOCKS, MAX_SUPPORTED_DELAY_TICS, + MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, MIN_SUPPORTED_DELAY) from spynnaker.pyNN.spynnaker_simulator_interface import ( SpynnakerSimulatorInterface) from spynnaker.pyNN.utilities.extracted_data import ExtractedData @@ -250,7 +251,7 @@ def _set_up_timings( raise ConfigurationException( "Pacman does not support min delays below {} ms with the " "current machine time step".format( - constants.MIN_SUPPORTED_DELAY * self.machine_time_step)) + MIN_SUPPORTED_DELAY * self.machine_time_step)) if min_delay is not None: self.__min_delay = min_delay else: @@ -258,11 +259,9 @@ def _set_up_timings( self.machine_time_step / MICRO_TO_MILLISECOND_CONVERSION) # Sort out the maximum delay - natively_supported_delay_for_models = \ - constants.MAX_SUPPORTED_DELAY_TICS + natively_supported_delay_for_models = MAX_SUPPORTED_DELAY_TICS delay_extension_max_supported_delay = ( - constants.MAX_DELAY_BLOCKS * - constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK) + MAX_DELAY_BLOCKS * MAX_TIMER_TICS_SUPPORTED_PER_BLOCK) max_delay_tics_supported = \ natively_supported_delay_for_models + \ delay_extension_max_supported_delay @@ -398,7 +397,7 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None, super(AbstractSpiNNakerCommon, self).stop( turn_off_machine, clear_routing_tables, clear_tags) self.reset_number_of_neurons_per_core() - globals_variables.unset_simulator(self) + unset_simulator(self) def run(self, run_time): """ Run the model created. diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py index 7aaec28d7f..ac49da35b1 100644 --- a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py +++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py @@ -17,8 +17,8 @@ from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.exceptions import ConfigurationException from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard -from spynnaker.pyNN.models.defaults import default_initial_values,\ - default_parameters +from spynnaker.pyNN.models.defaults import ( + default_initial_values, default_parameters) from spynnaker.pyNN.models.neuron.input_types import InputTypeCurrent from spynnaker.pyNN.models.neuron.neuron_models import ( NeuronModelLeakyIntegrateAndFire) diff --git a/spynnaker/pyNN/models/common/neuron_recorder.py b/spynnaker/pyNN/models/common/neuron_recorder.py index 9c2126f728..3da9206d18 100644 --- a/spynnaker/pyNN/models/common/neuron_recorder.py +++ b/spynnaker/pyNN/models/common/neuron_recorder.py @@ -26,7 +26,7 @@ from pacman.model.resources.variable_sdram import VariableSDRAM from data_specification.enums import DataType from spinn_front_end_common.utilities.exceptions import ConfigurationException -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import get_simulator from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION, BITS_PER_WORD) from spinn_front_end_common.interface.buffer_management.recording_utilities \ @@ -142,7 +142,7 @@ def get_neuron_sampling_interval(self, variable): :return: Sampling interval in microseconds :rtype: float """ - step = (globals_variables.get_simulator().machine_time_step / + step = (get_simulator().machine_time_step / MICRO_TO_MILLISECOND_CONVERSION) return self.__sampling_rates[variable] * step @@ -479,7 +479,7 @@ def _compute_rate(self, sampling_interval): return 1 step = ( - globals_variables.get_simulator().machine_time_step / + get_simulator().machine_time_step / MICRO_TO_MILLISECOND_CONVERSION) rate = int(sampling_interval / step) if sampling_interval != rate * step: diff --git a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py index 8c24cdd78d..05612815e9 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py @@ -19,13 +19,12 @@ import numpy from pyNN.random import NumpyRNG, RandomDistribution from six import string_types, with_metaclass - -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION from spinn_utilities.logger_utils import warn_once from spinn_utilities.safe_eval import SafeEval -from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem from spinn_utilities.abstract_base import AbstractBase, abstractmethod +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION) +from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem from spynnaker.pyNN.utilities import utility_calls # global objects diff --git a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py index 962391e127..c5b830f51a 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py @@ -15,11 +15,10 @@ import logging import numpy - -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION from spinn_utilities.overrides import overrides -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION) +from spinn_front_end_common.utilities.globals_variables import get_simulator from .abstract_connector import AbstractConnector from spynnaker.pyNN.exceptions import InvalidParameterType @@ -337,8 +336,7 @@ def conn_list(self, conn_list): self.__delays = None try: delay_column = column_names.index('delay') + _FIRST_PARAM - machine_time_step = globals_variables.get_simulator( - ).machine_time_step + machine_time_step = get_simulator().machine_time_step self.__delays = (numpy.rint( numpy.array(self.__conn_list[:, delay_column]) * ( MICRO_TO_MILLISECOND_CONVERSION / machine_time_step)) * diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index 5189012912..ffb579cb53 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -30,17 +30,19 @@ AbstractCanReset) from spinn_front_end_common.abstract_models.impl import ( ProvidesKeyToAtomMappingImpl) -from spinn_front_end_common.utilities import ( - constants as common_constants, helpful_functions, globals_variables) from spinn_front_end_common.utilities.constants import ( - BYTES_PER_WORD, SYSTEM_BYTES_REQUIREMENT) + BYTES_PER_WORD, SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES) +from spinn_front_end_common.utilities.helpful_functions import ( + read_config_int, locate_memory_region_for_placement) +from spinn_front_end_common.utilities.globals_variables import get_simulator from spinn_front_end_common.utilities.utility_objs import ExecutableType from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.interface.profiling import profile_utils -from spynnaker.pyNN.utilities.constants import POPULATION_BASED_REGIONS +from spynnaker.pyNN.utilities.constants import ( + POPULATION_BASED_REGIONS, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.common import ( AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder) -from spynnaker.pyNN.utilities import constants, bit_field_utilities +from spynnaker.pyNN.utilities import bit_field_utilities from spynnaker.pyNN.models.abstract_models import ( AbstractPopulationInitializable, AbstractAcceptsIncomingSynapses, AbstractPopulationSettable, AbstractReadParametersBeforeSet, @@ -158,7 +160,7 @@ def __init__( self.__incoming_spike_buffer_size = incoming_spike_buffer_size # get config from simulator - config = globals_variables.get_simulator().config + config = get_simulator().config if incoming_spike_buffer_size is None: self.__incoming_spike_buffer_size = config.getint( @@ -194,7 +196,7 @@ def __init__( self.__has_reset_last = True # Set up for profiling - self.__n_profile_samples = helpful_functions.read_config_int( + self.__n_profile_samples = read_config_int( config, "Reports", "n_profile_samples") @property @@ -330,7 +332,7 @@ def _reserve_memory_regions( # Reserve memory: spec.reserve_memory_region( region=POPULATION_BASED_REGIONS.SYSTEM.value, - size=common_constants.SIMULATION_N_BYTES, + size=SIMULATION_N_BYTES, label='System') self._reserve_neuron_params_data_region(spec, vertex_slice) @@ -411,7 +413,7 @@ def _write_neuron_parameters( # Set the focus to the memory region 2 (neuron parameters): spec.switch_write_focus( - region=constants.POPULATION_BASED_REGIONS.NEURON_PARAMS.value) + region=POPULATION_BASED_REGIONS.NEURON_PARAMS.value) # Write the random back off value max_offset = ( @@ -470,7 +472,7 @@ def regenerate_data_specification( # write the neuron params into the new DSG region self._write_neuron_parameters( key=routing_info.get_first_key_from_pre_vertex( - placement.vertex, constants.SPIKE_PARTITION_ID), + placement.vertex, SPIKE_PARTITION_ID), machine_time_step=machine_time_step, spec=spec, time_scale_factor=time_scale_factor, vertex_slice=vertex_slice) @@ -533,7 +535,7 @@ def generate_data_specification( # Get the key key = routing_info.get_first_key_from_pre_vertex( - vertex, constants.SPIKE_PARTITION_ID) + vertex, SPIKE_PARTITION_ID) # Write the setup region spec.switch_write_focus(POPULATION_BASED_REGIONS.SYSTEM.value) @@ -749,8 +751,7 @@ def read_parameters_from_machine( self, transceiver, placement, vertex_slice): # locate SDRAM address to where the neuron parameters are stored - neuron_region_sdram_address = \ - helpful_functions.locate_memory_region_for_placement( + neuron_region_sdram_address = locate_memory_region_for_placement( placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value, transceiver) diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py index dbe3dc2426..78374fbe7c 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py @@ -13,9 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from spinn_utilities.overrides import overrides from .abstract_pynn_neuron_model import AbstractPyNNNeuronModel from spynnaker.pyNN.models.neuron.implementations import NeuronImplStandard -from spinn_utilities.overrides import overrides _population_parameters = dict( AbstractPyNNNeuronModel.default_population_parameters) diff --git a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py index 4302354338..deabf274ae 100644 --- a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py +++ b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py @@ -19,7 +19,7 @@ from spinn_utilities.overrides import overrides from spynnaker.pyNN.models.neuron.input_types import InputTypeConductance from .abstract_neuron_impl import AbstractNeuronImpl -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import get_simulator from spinn_front_end_common.utilities.constants import BYTES_PER_WORD # The size of the n_steps_per_timestep parameter @@ -187,7 +187,7 @@ def add_state_variables(self, state_variables): @overrides(AbstractNeuronImpl.get_data) def get_data(self, parameters, state_variables, vertex_slice): # Work out the time step per step - ts = globals_variables.get_simulator().machine_time_step + ts = get_simulator().machine_time_step ts /= self.__n_steps_per_timestep items = [numpy.array([self.__n_steps_per_timestep], dtype="uint32")] items.extend( diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_izh.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_izh.py index a039130413..ee67984ca2 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_izh.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_izh.py @@ -12,10 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION from spinn_utilities.overrides import overrides from data_specification.enums import DataType +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION) from .abstract_neuron_model import AbstractNeuronModel from spynnaker.pyNN.models.neuron.implementations import ( AbstractStandardNeuronComponent) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py index 1052c4659a..b9262dd700 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py @@ -17,13 +17,13 @@ from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( get_exp_lut_array) -from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence\ - import AbstractTimingDependence -from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ - import SynapseStructureWeightOnly -from spinn_front_end_common.utilities.globals_variables import get_simulator +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( + AbstractTimingDependence) +from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( + SynapseStructureWeightOnly) logger = logging.getLogger(__name__) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py index 1e6d1e9277..149555c46e 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py @@ -14,12 +14,10 @@ # along with this program. If not, see . import numpy -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION from spinn_utilities.overrides import overrides from data_specification.enums import DataType from spinn_front_end_common.utilities.constants import ( - BYTES_PER_WORD, BYTES_PER_SHORT) + BYTES_PER_WORD, BYTES_PER_SHORT, MICRO_TO_MILLISECOND_CONVERSION) from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightAccumulator) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py index f58d2a826d..d318a0eb7f 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py @@ -17,13 +17,12 @@ from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) - +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( get_exp_lut_array) from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) from .abstract_timing_dependence import AbstractTimingDependence -from spinn_front_end_common.utilities.globals_variables import get_simulator logger = logging.getLogger(__name__) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py index 40cb9ee532..fc7cc64d9c 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py @@ -17,12 +17,12 @@ from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_SHORT, BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( get_exp_lut_array) from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) -from spinn_front_end_common.utilities.globals_variables import get_simulator logger = logging.getLogger(__name__) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py index c75f8672b0..95217e1bce 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py @@ -18,11 +18,11 @@ from data_specification.enums import DataType from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, BYTES_PER_SHORT, MICRO_TO_MILLISECOND_CONVERSION) +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( AbstractTimingDependence) from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) -from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( float_to_fixed, get_exp_lut_array) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index 310f096d08..13a62b130a 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -21,12 +21,12 @@ BYTES_PER_WORD, BYTES_PER_SHORT) from spynnaker.pyNN.models.abstract_models import AbstractSettable from .abstract_plastic_synapse_dynamics import AbstractPlasticSynapseDynamics -from .abstract_synapse_dynamics_structural \ - import AbstractSynapseDynamicsStructural +from .abstract_synapse_dynamics_structural import ( + AbstractSynapseDynamicsStructural) from .abstract_generate_on_machine import ( AbstractGenerateOnMachine, MatrixGeneratorID) -from spynnaker.pyNN.exceptions import InvalidParameterType,\ - SynapticConfigurationException +from spynnaker.pyNN.exceptions import ( + InvalidParameterType, SynapticConfigurationException) from spynnaker.pyNN.utilities.utility_calls import get_n_bits # How large are the time-stamps stored with each event diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py index a15b60fc2a..a815be6463 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py @@ -17,7 +17,8 @@ from .abstract_synapse_dynamics_structural import ( AbstractSynapseDynamicsStructural) from .synapse_dynamics_structural_common import ( - SynapseDynamicsStructuralCommon as CommonSP) + SynapseDynamicsStructuralCommon as + CommonSP) from .synapse_dynamics_static import SynapseDynamicsStatic from .synapse_dynamics_stdp import SynapseDynamicsSTDP from .synapse_dynamics_structural_stdp import SynapseDynamicsStructuralSTDP diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py index e0e6518236..af46491dda 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py @@ -19,7 +19,7 @@ AbstractSynapseDynamicsStructural) from .synapse_dynamics_structural_common import ( SynapseDynamicsStructuralCommon as - CommonSP) + CommonSP) from spynnaker.pyNN.exceptions import SynapticConfigurationException diff --git a/spynnaker/pyNN/models/neuron/synapse_io.py b/spynnaker/pyNN/models/neuron/synapse_io.py index acef9f55c7..3cd626bcca 100644 --- a/spynnaker/pyNN/models/neuron/synapse_io.py +++ b/spynnaker/pyNN/models/neuron/synapse_io.py @@ -16,9 +16,8 @@ import math import numpy from six import raise_from - -from spinn_front_end_common.utilities.constants import \ - MICRO_TO_MILLISECOND_CONVERSION, BYTES_PER_WORD +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION, BYTES_PER_WORD) from spynnaker.pyNN.models.neural_projections.connectors import ( AbstractConnector) from spynnaker.pyNN.utilities.constants import MAX_SUPPORTED_DELAY_TICS diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index de06723c12..7da214a8a9 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -24,7 +24,8 @@ MaxVertexAtomsConstraint) from pacman.model.graphs.application.application_vertex import ( ApplicationVertex) -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import ( + get_simulator, get_not_running_simulator) from spinn_front_end_common.utilities.exceptions import ConfigurationException from spinn_front_end_common.abstract_models import AbstractChangableAfterRun from spynnaker.pyNN.models.abstract_models import ( @@ -165,14 +166,14 @@ def __init__( # things for pynn demands self._all_ids = numpy.arange( - globals_variables.get_simulator().id_counter, - globals_variables.get_simulator().id_counter + size) + get_simulator().id_counter, + get_simulator().id_counter + size) self.__first_id = self._all_ids[0] self.__last_id = self._all_ids[-1] # update the simulators id_counter for giving a unique ID for every # atom - globals_variables.get_simulator().id_counter += size + get_simulator().id_counter += size # set up initial values if given if initial_values is not None: @@ -365,7 +366,7 @@ def _initialize(self, variable, value): raise KeyError( "Population does not support the initialisation of {}".format( variable)) - if globals_variables.get_not_running_simulator().has_ran \ + if get_not_running_simulator().has_ran \ and not self._vertex_changeable_after_run: raise Exception("Population does not support changes after run") self._read_parameters_before_set() @@ -415,7 +416,7 @@ def _set_check(self, parameter, value): raise KeyError("Population does not have property {}".format( parameter)) - if globals_variables.get_not_running_simulator().has_ran \ + if get_not_running_simulator().has_ran \ and not self._vertex_changeable_after_run: raise Exception( " run has been called") @@ -493,20 +494,19 @@ def _read_parameters_before_set(self): # If the tools have run before, and not reset, and the read # hasn't already been done, read back the data - if globals_variables.get_simulator().has_ran \ + if get_simulator().has_ran \ and self._vertex_read_parameters_before_set \ and not self.__has_read_neuron_parameters_this_run \ - and not globals_variables.get_simulator().use_virtual_board: + and not get_simulator().use_virtual_board: + placements = get_simulator().placements # go through each machine vertex and read the neuron parameters # it contains for machine_vertex in self.__vertex.machine_vertices: # tell the core to rewrite neuron params back to the # SDRAM space. - placement = globals_variables.get_simulator().placements.\ - get_placement_of_vertex(machine_vertex) - self.__vertex.read_parameters_from_machine( - globals_variables.get_simulator().transceiver, placement, + get_simulator().transceiver, + placements.get_placement_of_vertex(machine_vertex), machine_vertex.vertex_slice) self.__has_read_neuron_parameters_this_run = True @@ -559,7 +559,7 @@ def set_constraint(self, constraint): :param ~pacman.model.constraints.AbstractConstraint constraint: """ - globals_variables.get_simulator().verify_not_running() + get_simulator().verify_not_running() if not isinstance(constraint, AbstractConstraint): raise ConfigurationException( "the constraint entered is not a recognised constraint") @@ -576,7 +576,7 @@ def add_placement_constraint(self, x, y, p=None): :param int y: The y-coordinate of the placement constraint :param int p: The processor ID of the placement constraint (optional) """ - globals_variables.get_simulator().verify_not_running() + get_simulator().verify_not_running() self.__vertex.add_constraint(ChipAndCoreConstraint(x, y, p)) # state that something has changed in the population, @@ -590,7 +590,7 @@ def set_mapping_constraint(self, constraint_dict): A dictionary containing "x", "y" and optionally "p" as keys, and ints as values """ - globals_variables.get_simulator().verify_not_running() + get_simulator().verify_not_running() self.add_placement_constraint(**constraint_dict) # state that something has changed in the population, @@ -603,7 +603,7 @@ def set_max_atoms_per_core(self, max_atoms_per_core): :param int max_atoms_per_core: the new value for the max atoms per core. """ - globals_variables.get_simulator().verify_not_running() + get_simulator().verify_not_running() self.__vertex.add_constraint( MaxVertexAtomsConstraint(max_atoms_per_core)) # state that something has changed in the population diff --git a/spynnaker/pyNN/models/pynn_projection_common.py b/spynnaker/pyNN/models/pynn_projection_common.py index 58a85ba9cb..d76bb8832e 100644 --- a/spynnaker/pyNN/models/pynn_projection_common.py +++ b/spynnaker/pyNN/models/pynn_projection_common.py @@ -31,14 +31,15 @@ DelayedApplicationEdge, SynapseInformation, ProjectionApplicationEdge, DelayAfferentApplicationEdge) from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex -from spynnaker.pyNN.utilities import constants +from spynnaker.pyNN.utilities.constants import ( + MAX_DELAY_BLOCKS, MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.neuron import ConnectionHolder # pylint: disable=protected-access logger = logging.getLogger(__name__) _delay_extension_max_supported_delay = ( - constants.MAX_DELAY_BLOCKS * constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK) + MAX_DELAY_BLOCKS * MAX_TIMER_TICS_SUPPORTED_PER_BLOCK) # The maximum delay supported by the Delay extension, in ticks. @@ -181,7 +182,7 @@ def __init__( # add edge to the graph spinnaker_control.add_application_edge( - self.__projection_edge, constants.SPIKE_PARTITION_ID) + self.__projection_edge, SPIKE_PARTITION_ID) # If the delay exceeds the post vertex delay, add a delay extension if max_delay > post_vertex_max_supported_delay_ms: @@ -297,7 +298,7 @@ def _add_delay_extension( pre_vertex, delay_vertex, label="{}_to_DelayExtension".format( pre_vertex.label)) self.__spinnaker_control.add_application_edge( - delay_afferent_edge, constants.SPIKE_PARTITION_ID) + delay_afferent_edge, SPIKE_PARTITION_ID) # Ensure that the delay extension knows how many states it will # support @@ -315,7 +316,7 @@ def _add_delay_extension( label="{}_delayed_to_{}".format( pre_vertex.label, post_vertex.label)) self.__spinnaker_control.add_application_edge( - delay_edge, constants.SPIKE_PARTITION_ID) + delay_edge, SPIKE_PARTITION_ID) else: delay_edge.add_synapse_information(self.__synapse_information) return delay_edge diff --git a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py index ad91188f3a..08e473a609 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py @@ -20,10 +20,10 @@ from spinn_front_end_common.abstract_models import AbstractChangableAfterRun from spinn_front_end_common.abstract_models.impl import ( ProvidesKeyToAtomMappingImpl) -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.common import ( AbstractSpikeRecordable, EIEIOSpikeRecorder, SimplePopulationSettable) -from spynnaker.pyNN.utilities import constants +from spynnaker.pyNN.utilities.constants import SPIKE_PARTITION_ID logger = logging.getLogger(__name__) @@ -66,7 +66,7 @@ def __init__( n_keys=n_neurons, label=label, constraints=constraints, max_atoms_per_core=max_atoms_per_core, send_buffer_times=_send_buffer_times(spike_times, time_step), - send_buffer_partition_id=constants.SPIKE_PARTITION_ID) + send_buffer_partition_id=SPIKE_PARTITION_ID) # handle recording self.__spike_recorder = EIEIOSpikeRecorder() @@ -118,7 +118,7 @@ def set_recording_spikes( @overrides(AbstractSpikeRecordable.get_spikes_sampling_interval) def get_spikes_sampling_interval(self): - return globals_variables.get_simulator().machine_time_step + return get_simulator().machine_time_step @overrides(AbstractSpikeRecordable.get_spikes) def get_spikes(self, placements, buffer_manager, machine_time_step): diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index 9b3a403ea9..7925adc713 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -18,7 +18,6 @@ import numpy import scipy.stats import struct - from spinn_utilities.overrides import overrides from data_specification.enums import DataType from pacman.executor.injection_decorator import inject_items @@ -36,26 +35,26 @@ from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.interface.buffer_management import ( recording_utilities) -from spinn_front_end_common.utilities import ( - helpful_functions, globals_variables) from spinn_front_end_common.utilities.constants import ( SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BYTES_PER_WORD) +from spinn_front_end_common.utilities.globals_variables import get_simulator +from spinn_front_end_common.utilities.helpful_functions import ( + locate_memory_region_for_placement, read_config_int) from spinn_front_end_common.utilities.utility_objs import ExecutableType from spinn_front_end_common.utilities.exceptions import ConfigurationException from spinn_front_end_common.interface.profiling import profile_utils from spynnaker.pyNN.models.common import ( AbstractSpikeRecordable, MultiSpikeRecorder, SimplePopulationSettable) -from spynnaker.pyNN.utilities import constants +from spynnaker.pyNN.utilities.constants import ( + LIVE_POISSON_CONTROL_PARTITION_ID, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.abstract_models import ( AbstractReadParametersBeforeSet) from .spike_source_poisson_machine_vertex import ( SpikeSourcePoissonMachineVertex) from spynnaker.pyNN.utilities.utility_calls import validate_mars_kiss_64_seed from spynnaker.pyNN.utilities.struct import Struct -from spynnaker.pyNN.utilities.ranged.spynnaker_ranged_dict \ - import SpynnakerRangeDictionary -from spynnaker.pyNN.utilities.ranged.spynnaker_ranged_list \ - import SpynnakerRangedList +from spynnaker.pyNN.utilities.ranged import ( + SpynnakerRangeDictionary, SpynnakerRangedList) logger = logging.getLogger(__name__) @@ -302,8 +301,8 @@ def __init__( self.__machine_time_step = None # get config from simulator - config = globals_variables.get_simulator().config - self.__n_profile_samples = helpful_functions.read_config_int( + config = get_simulator().config + self.__n_profile_samples = read_config_int( config, "Reports", "n_profile_samples") # Prepare for recording, and to get spikes @@ -616,13 +615,13 @@ def _write_poisson_parameters( # Write Key info for this core: key = routing_info.get_first_key_from_pre_vertex( - placement.vertex, constants.SPIKE_PARTITION_ID) + placement.vertex, SPIKE_PARTITION_ID) spec.write_value(data=1 if key is not None else 0) spec.write_value(data=key if key is not None else 0) # Write the incoming mask if there is one in_edges = graph.get_edges_ending_at_vertex_with_partition_name( - placement.vertex, constants.LIVE_POISSON_CONTROL_PARTITION_ID) + placement.vertex, LIVE_POISSON_CONTROL_PARTITION_ID) if len(in_edges) > 1: raise ConfigurationException( "Only one control edge can end at a Poisson vertex") @@ -837,7 +836,7 @@ def set_recording_spikes( @overrides(AbstractSpikeRecordable.get_spikes_sampling_interval) def get_spikes_sampling_interval(self): - return globals_variables.get_simulator().machine_time_step + return get_simulator().machine_time_step @staticmethod def get_dtcm_usage_for_atoms(): @@ -907,8 +906,7 @@ def read_parameters_from_machine( self, transceiver, placement, vertex_slice): # locate SDRAM address where parameters are stored - poisson_params = \ - helpful_functions.locate_memory_region_for_placement( + poisson_params = locate_memory_region_for_placement( placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver) seed_array = transceiver.read_memory( placement.x, placement.y, poisson_params + SEED_OFFSET_BYTES, @@ -916,8 +914,7 @@ def read_parameters_from_machine( self.__kiss_seed[vertex_slice] = struct.unpack_from("<4I", seed_array) # locate SDRAM address where the rates are stored - poisson_rate_region_sdram_address = \ - helpful_functions.locate_memory_region_for_placement( + poisson_rate_region_sdram_address = locate_memory_region_for_placement( placement, _REGIONS.RATES_REGION.value, transceiver) # get size of poisson params diff --git a/spynnaker/pyNN/models/utility_models/synapse_expander/synapse_expander.py b/spynnaker/pyNN/models/utility_models/synapse_expander/synapse_expander.py index cdb4a5f685..1a65b5444a 100644 --- a/spynnaker/pyNN/models/utility_models/synapse_expander/synapse_expander.py +++ b/spynnaker/pyNN/models/utility_models/synapse_expander/synapse_expander.py @@ -20,7 +20,7 @@ from spinn_utilities.make_tools.replacer import Replacer from spinnman.model import ExecutableTargets from spinnman.model.enums import CPUState -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.exceptions import SpynnakerException from spynnaker.pyNN.models.neuron import AbstractPopulationVertex from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex @@ -170,7 +170,7 @@ def _fill_in_connection_data(expanded_pop_vertices, placements, transceiver): :rtype: None """ - ctl = globals_variables.get_simulator() + ctl = get_simulator() use_extra_monitors = False for vertex in expanded_pop_vertices: diff --git a/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py b/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py index d68137934f..de6347a803 100644 --- a/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py +++ b/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py @@ -18,21 +18,25 @@ import logging import os from collections import defaultdict - -from spinn_front_end_common.abstract_models import \ - AbstractSupportsBitFieldGeneration -from spinn_front_end_common.utilities import system_control_logic -from spinn_front_end_common.utilities.constants import BYTES_PER_WORD -from spinn_front_end_common.utilities.utility_objs import ExecutableType - from spinn_utilities.progress_bar import ProgressBar - from spinnman.model import ExecutableTargets from spinnman.model.enums import CPUState +from spinn_front_end_common.abstract_models import ( + AbstractSupportsBitFieldGeneration) +from spinn_front_end_common.utilities.system_control_logic import ( + run_system_application) +from spinn_front_end_common.utilities.constants import BYTES_PER_WORD +from spinn_front_end_common.utilities.utility_objs import ExecutableType logger = logging.getLogger(__name__) +def _percent(amount, total): + if total == 0: + return 0.0 + return (100.0 * amount) / float(total) + + class OnChipBitFieldGenerator(object): """ Executes bitfield and routing table entries for atom based routing """ @@ -82,16 +86,16 @@ def __call__( :param placements: placements :param app_graph: the app graph :param executable_finder: the executable finder - :param provenance_file_path: the path to where provenance data items\ - is written + :param provenance_file_path: + the path to where provenance data items is written :param transceiver: the SpiNNMan instance :param read_bit_field_generator_iobuf: bool flag for report :param generating_bitfield_report: bool flag for report :param default_report_folder: the file path for reports :param machine_graph: the machine graph :param routing_infos: the key to edge map - :param generating_bit_field_summary_report: bool flag for making \ - summary report + :param generating_bit_field_summary_report: + bool flag for making summary report :rtype: None """ @@ -109,7 +113,7 @@ def __call__( progress.update(1) # run app - system_control_logic.run_system_application( + run_system_application( expander_cores, bit_field_app_id, transceiver, provenance_file_path, executable_finder, read_bit_field_generator_iobuf, self._check_for_success, @@ -121,23 +125,19 @@ def __call__( # read in bit fields for debugging purposes if generating_bitfield_report: self._read_back_bit_fields( - app_graph, transceiver, placements, - default_report_folder, self._BIT_FIELD_REPORT_FILENAME) + app_graph, transceiver, placements, default_report_folder) if generating_bit_field_summary_report: self._read_back_and_summarise_bit_fields( - app_graph, transceiver, placements, - default_report_folder, self._BIT_FIELD_SUMMARY_REPORT_FILENAME) + app_graph, transceiver, placements, default_report_folder) def _read_back_and_summarise_bit_fields( - self, app_graph, transceiver, placements, - default_report_folder, bit_field_summary_report_name): + self, app_graph, transceiver, placements, default_report_folder): """ summary report of the bitfields that were generated :param app_graph: app graph :param transceiver: the SPiNNMan instance :param placements: The placements :param default_report_folder:the file path for where reports are. - :param bit_field_summary_report_name: the name of the summary file :rtype: None """ progress = ProgressBar( @@ -148,72 +148,17 @@ def _read_back_and_summarise_bit_fields( chip_redundant_count = defaultdict(int) file_path = os.path.join( - default_report_folder, bit_field_summary_report_name) + default_report_folder, self._BIT_FIELD_SUMMARY_REPORT_FILENAME) with open(file_path, "w") as output: # read in for each app vertex that would have a bitfield for app_vertex in progress.over(app_graph.vertices): - local_total = 0 - local_redundant = 0 - # get machine verts for vertex in app_vertex.machine_vertices: if isinstance(vertex, AbstractSupportsBitFieldGeneration): - placement = placements.get_placement_of_vertex(vertex) - - # get bitfield address - bit_field_address = vertex.bit_field_base_address( - transceiver, placement) - - # read how many bitfields there are - n_bit_field_entries, = struct.unpack( - ". import logging - -from spinn_front_end_common.abstract_models.\ - abstract_supports_bit_field_generation import \ - AbstractSupportsBitFieldGeneration +from spinnman.model import ExecutableTargets +from spinnman.model.enums import CPUState +from spinn_front_end_common.abstract_models import ( + AbstractSupportsBitFieldGeneration) from spinn_front_end_common.interface.interface_functions.\ - machine_bit_field_router_compressor import \ - MachineBitFieldRouterCompressor + machine_bit_field_router_compressor import ( + MachineBitFieldRouterCompressor) from spinn_front_end_common.utilities import system_control_logic from spinn_front_end_common.utilities.utility_objs import ExecutableType -from spinnman.model import ExecutableTargets -from spinnman.model.enums import CPUState -from spynnaker.pyNN.models.utility_models.synapse_expander. \ - synapse_expander import SYNAPSE_EXPANDER +from spynnaker.pyNN.models.utility_models.synapse_expander.synapse_expander \ + import ( + SYNAPSE_EXPANDER) logger = logging.getLogger(__name__) diff --git a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py index 0df662a5f4..d71995b7a8 100644 --- a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py +++ b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py @@ -16,7 +16,8 @@ from spinn_utilities.socket_address import SocketAddress from pacman.model.graphs.application import ApplicationEdge from spinnman.messages.eieio import EIEIOType -from spinn_front_end_common.utilities import helpful_functions +from spinn_front_end_common.utilities.helpful_functions import ( + read_config, read_config_int) from spinn_front_end_common.utilities.globals_variables import get_simulator from spinn_front_end_common.utility_models import ( ReverseIpTagMultiCastSource) @@ -50,15 +51,15 @@ def add_database_socket_address( """ config = get_simulator().config if database_notify_port_num is None: - database_notify_port_num = helpful_functions.read_config_int( + database_notify_port_num = read_config_int( config, "Database", "notify_port") if database_notify_host is None: - database_notify_host = helpful_functions.read_config( + database_notify_host = read_config( config, "Database", "notify_hostname") elif database_notify_host == "0.0.0.0": database_notify_host = "localhost" if database_ack_port_num is None: - database_ack_port_num = helpful_functions.read_config_int( + database_ack_port_num = read_config_int( config, "Database", "listen_port") # build the database socket address used by the notification interface @@ -298,9 +299,8 @@ def add_edge(vertex, device_vertex, partition_id): ~pacman.model.graphs.application.ApplicationVertex :param str partition_id: the partition identifier for making nets """ - _spinnaker = get_simulator() edge = ApplicationEdge(vertex, device_vertex) - _spinnaker.add_application_edge(edge, partition_id) + get_simulator().add_application_edge(edge, partition_id) @staticmethod def add_application_vertex(vertex): diff --git a/spynnaker/pyNN/utilities/bit_field_utilities.py b/spynnaker/pyNN/utilities/bit_field_utilities.py index 4fbe52da45..ee69a5deb1 100644 --- a/spynnaker/pyNN/utilities/bit_field_utilities.py +++ b/spynnaker/pyNN/utilities/bit_field_utilities.py @@ -14,11 +14,11 @@ # along with this program. If not, see . import math - from pacman.utilities.constants import FULL_MASK +from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \ + import ( + determine_max_atoms_for_vertex) from spinn_front_end_common.utilities.constants import BYTES_PER_WORD -from pacman.utilities.algorithm_utilities. \ - partition_algorithm_utilities import determine_max_atoms_for_vertex from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex @@ -44,7 +44,8 @@ def get_estimated_sdram_for_bit_field_region(app_graph, vertex): - """ estimates the sdram for the bit field region + """ Estimates the SDRAM for the bit field region + :param app_graph: the app graph :param vertex: machine vertex :return: the estimated number of bytes used by the bit field region @@ -100,10 +101,9 @@ def get_estimated_sdram_for_key_region(app_graph, vertex): return sdram -def _exact_sdram_for_bit_field_region( - machine_graph, vertex, n_key_map): - """ calculates the correct sdram for the bitfield region based off \ - the machine graph and graph mapper +def _exact_sdram_for_bit_field_region(machine_graph, vertex, n_key_map): + """ Gets the correct SDRAM for the bitfield region based off \ + the machine graph :param machine_graph: machine graph :param vertex: the machine vertex @@ -123,14 +123,15 @@ def _exact_sdram_for_bit_field_region( def exact_sdram_for_bit_field_builder_region(): - """ returns the sdram requirement for the builder region - :return: returns the sdram requirement for the builder region + """ Gets the SDRAM requirement for the builder region + + :return: returns the SDRAM requirement for the builder region """ return N_REGIONS_ADDRESSES * BYTES_PER_WORD def _exact_sdram_for_bit_field_key_region(machine_graph, vertex): - """ calcs the exact sdram for the bitfield key region + """ Calculates the exact SDRAM for the bitfield key region :param machine_graph: machine graph :param vertex: machine vertex diff --git a/unittests/mocks.py b/unittests/mocks.py index 299d83d317..230e347b58 100644 --- a/unittests/mocks.py +++ b/unittests/mocks.py @@ -15,7 +15,8 @@ import configparser import numpy -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.globals_variables import ( + set_failed_state, set_simulator) from spynnaker.pyNN.utilities.spynnaker_failed_state import ( SpynnakerFailedState) from builtins import property @@ -132,8 +133,8 @@ def id_counter(self, value): @classmethod def setup(cls): simulator = MockSimulator() - globals_variables.set_failed_state(SpynnakerFailedState()) - globals_variables.set_simulator(simulator) + set_failed_state(SpynnakerFailedState()) + set_simulator(simulator) return simulator @property From 847a6144fcfc7f59de47f769916b043c9777cbea Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 15 Jun 2020 21:10:52 +0100 Subject: [PATCH 02/11] I just had to tweak things --- spynnaker/pyNN/abstract_spinnaker_common.py | 2 + .../connectors/abstract_connector.py | 2 +- .../neuron/abstract_population_vertex.py | 42 +++++++++-------- .../implementations/neuron_impl_standard.py | 3 +- .../pyNN/models/pynn_population_common.py | 3 +- .../spike_source_poisson_vertex.py | 16 +++---- .../on_chip_bit_field_generator.py | 46 ++++++++----------- 7 files changed, 54 insertions(+), 60 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 233da03c7d..e8a0449687 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -19,6 +19,8 @@ from six import with_metaclass from spinn_utilities.abstract_base import AbstractBase from spinn_utilities.log import FormatAdapter +from spinn_front_end_common.utilities.constants import ( + MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.interface.abstract_spinnaker_base import ( AbstractSpinnakerBase) from spinn_front_end_common.utilities.constants import ( diff --git a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py index 05612815e9..eab6155166 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py @@ -19,9 +19,9 @@ import numpy from pyNN.random import NumpyRNG, RandomDistribution from six import string_types, with_metaclass +from spinn_utilities.abstract_base import AbstractBase, abstractmethod from spinn_utilities.logger_utils import warn_once from spinn_utilities.safe_eval import SafeEval -from spinn_utilities.abstract_base import AbstractBase, abstractmethod from spinn_front_end_common.utilities.constants import ( MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index ffb579cb53..714c7a7662 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -31,18 +31,24 @@ from spinn_front_end_common.abstract_models.impl import ( ProvidesKeyToAtomMappingImpl) from spinn_front_end_common.utilities.constants import ( - BYTES_PER_WORD, SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES) + BYTES_PER_WORD, SIMULATION_N_BYTES, SYSTEM_BYTES_REQUIREMENT) from spinn_front_end_common.utilities.helpful_functions import ( read_config_int, locate_memory_region_for_placement) from spinn_front_end_common.utilities.globals_variables import get_simulator from spinn_front_end_common.utilities.utility_objs import ExecutableType -from spinn_front_end_common.interface.simulation import simulation_utilities -from spinn_front_end_common.interface.profiling import profile_utils +from spinn_front_end_common.interface.simulation.simulation_utilities import ( + get_simulation_header_array) +from spinn_front_end_common.interface.profiling.profile_utils import ( + get_profile_region_size, reserve_profile_region, write_profile_region_data) from spynnaker.pyNN.utilities.constants import ( POPULATION_BASED_REGIONS, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.common import ( AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder) -from spynnaker.pyNN.utilities import bit_field_utilities +from spynnaker.pyNN.utilities.bit_field_utilities import ( + exact_sdram_for_bit_field_builder_region, + get_estimated_sdram_for_bit_field_region, + get_estimated_sdram_for_key_region, + reserve_bit_field_regions, write_bitfield_init_data) from spynnaker.pyNN.models.abstract_models import ( AbstractPopulationInitializable, AbstractAcceptsIncomingSynapses, AbstractPopulationSettable, AbstractReadParametersBeforeSet, @@ -305,13 +311,10 @@ def _get_sdram_usage_for_atoms( len(PopulationMachineVertex.EXTRA_PROVENANCE_DATA_ENTRIES)) + self.__synapse_manager.get_sdram_usage_in_bytes( vertex_slice, machine_time_step, graph, self) + - profile_utils.get_profile_region_size( - self.__n_profile_samples) + - bit_field_utilities.get_estimated_sdram_for_bit_field_region( - graph, self) + - bit_field_utilities.get_estimated_sdram_for_key_region( - graph, self) + - bit_field_utilities.exact_sdram_for_bit_field_builder_region()) + get_profile_region_size(self.__n_profile_samples) + + get_estimated_sdram_for_bit_field_region(graph, self) + + get_estimated_sdram_for_key_region(graph, self) + + exact_sdram_for_bit_field_builder_region()) return sdram_requirement def _reserve_memory_regions( @@ -342,12 +345,12 @@ def _reserve_memory_regions( size=self._neuron_recorder.get_static_sdram_usage(vertex_slice), label="neuron recording") - profile_utils.reserve_profile_region( + reserve_profile_region( spec, POPULATION_BASED_REGIONS.PROFILING.value, self.__n_profile_samples) # reserve bit field region - bit_field_utilities.reserve_bit_field_regions( + reserve_bit_field_regions( spec, machine_graph, n_key_map, vertex, POPULATION_BASED_REGIONS.BIT_FIELD_BUILDER.value, POPULATION_BASED_REGIONS.BIT_FIELD_FILTER.value, @@ -412,8 +415,7 @@ def _write_neuron_parameters( n_atoms)) # Set the focus to the memory region 2 (neuron parameters): - spec.switch_write_focus( - region=POPULATION_BASED_REGIONS.NEURON_PARAMS.value) + spec.switch_write_focus(POPULATION_BASED_REGIONS.NEURON_PARAMS.value) # Write the random back off value max_offset = ( @@ -539,7 +541,7 @@ def generate_data_specification( # Write the setup region spec.switch_write_focus(POPULATION_BASED_REGIONS.SYSTEM.value) - spec.write_array(simulation_utilities.get_simulation_header_array( + spec.write_array(get_simulation_header_array( self.get_binary_file_name(), machine_time_step, time_scale_factor)) @@ -553,7 +555,7 @@ def generate_data_specification( spec, key, vertex_slice, machine_time_step, time_scale_factor) # write profile data - profile_utils.write_profile_region_data( + write_profile_region_data( spec, POPULATION_BASED_REGIONS.PROFILING.value, self.__n_profile_samples) @@ -570,7 +572,7 @@ def generate_data_specification( self.__synapse_manager.on_chip_written_matrix_size) # write up the bitfield builder data - bit_field_utilities.write_bitfield_init_data( + write_bitfield_init_data( spec, vertex, machine_graph, routing_info, n_key_map, POPULATION_BASED_REGIONS.BIT_FIELD_BUILDER.value, POPULATION_BASED_REGIONS.POPULATION_TABLE.value, @@ -752,8 +754,8 @@ def read_parameters_from_machine( # locate SDRAM address to where the neuron parameters are stored neuron_region_sdram_address = locate_memory_region_for_placement( - placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value, - transceiver) + placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value, + transceiver) # shift past the extra stuff before neuron parameters that we don't # need to read diff --git a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py index deabf274ae..b48e26cee2 100644 --- a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py +++ b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py @@ -187,8 +187,7 @@ def add_state_variables(self, state_variables): @overrides(AbstractNeuronImpl.get_data) def get_data(self, parameters, state_variables, vertex_slice): # Work out the time step per step - ts = get_simulator().machine_time_step - ts /= self.__n_steps_per_timestep + ts = get_simulator().machine_time_step / self.__n_steps_per_timestep items = [numpy.array([self.__n_steps_per_timestep], dtype="uint32")] items.extend( component.get_data(parameters, state_variables, vertex_slice, ts) diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index 7da214a8a9..5adf234845 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -166,8 +166,7 @@ def __init__( # things for pynn demands self._all_ids = numpy.arange( - get_simulator().id_counter, - get_simulator().id_counter + size) + get_simulator().id_counter, get_simulator().id_counter + size) self.__first_id = self._all_ids[0] self.__last_id = self._all_ids[-1] diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index 7925adc713..d414348b56 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -42,7 +42,8 @@ locate_memory_region_for_placement, read_config_int) from spinn_front_end_common.utilities.utility_objs import ExecutableType from spinn_front_end_common.utilities.exceptions import ConfigurationException -from spinn_front_end_common.interface.profiling import profile_utils +from spinn_front_end_common.interface.profiling.profile_utils import ( + get_profile_region_size, reserve_profile_region, write_profile_region_data) from spynnaker.pyNN.models.common import ( AbstractSpikeRecordable, MultiSpikeRecorder, SimplePopulationSettable) from spynnaker.pyNN.utilities.constants import ( @@ -489,7 +490,7 @@ def get_resources_used_by_atoms(self, vertex_slice, machine_time_step): poisson_params_sz + recording_utilities.get_recording_header_size(1) + recording_utilities.get_recording_data_constant_size(1) + - profile_utils.get_profile_region_size(self.__n_profile_samples)) + get_profile_region_size(self.__n_profile_samples)) recording = self.get_recording_sdram_usage( vertex_slice, machine_time_step) @@ -567,7 +568,7 @@ def reserve_memory_regions(self, spec, placement): size=recording_utilities.get_recording_header_size(1), label="Recording") - profile_utils.reserve_profile_region( + reserve_profile_region( spec, _REGIONS.PROFILER_REGION.value, self.__n_profile_samples) placement.vertex.reserve_provenance_data_region(spec) @@ -907,7 +908,7 @@ def read_parameters_from_machine( # locate SDRAM address where parameters are stored poisson_params = locate_memory_region_for_placement( - placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver) + placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver) seed_array = transceiver.read_memory( placement.x, placement.y, poisson_params + SEED_OFFSET_BYTES, SEED_SIZE_BYTES) @@ -915,7 +916,7 @@ def read_parameters_from_machine( # locate SDRAM address where the rates are stored poisson_rate_region_sdram_address = locate_memory_region_for_placement( - placement, _REGIONS.RATES_REGION.value, transceiver) + placement, _REGIONS.RATES_REGION.value, transceiver) # get size of poisson params size_of_region = self.get_rates_bytes(vertex_slice) @@ -1021,9 +1022,8 @@ def generate_data_specification( first_machine_time_step) # write profile data - profile_utils.write_profile_region_data( - spec, _REGIONS.PROFILER_REGION.value, - self.__n_profile_samples) + write_profile_region_data( + spec, _REGIONS.PROFILER_REGION.value, self.__n_profile_samples) # End-of-Spec: spec.end_specification() diff --git a/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py b/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py index de6347a803..2c39dd5dcb 100644 --- a/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py +++ b/spynnaker/pyNN/overridden_pacman_functions/on_chip_bit_field_generator.py @@ -13,11 +13,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math -import struct +from collections import defaultdict import logging import os -from collections import defaultdict +import struct from spinn_utilities.progress_bar import ProgressBar from spinnman.model import ExecutableTargets from spinnman.model.enums import CPUState @@ -46,9 +45,6 @@ class OnChipBitFieldGenerator(object): # flag which states that the binary finished cleanly. _SUCCESS = 0 - # the number of bytes needed to read the user2 register - _USER_BYTES = 4 - # n key to n neurons maps size in words _N_KEYS_DATA_SET_IN_WORDS = 1 @@ -64,9 +60,8 @@ class OnChipBitFieldGenerator(object): # n elements in each key to n atoms map _N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP = 2 - _BYTES_PER_FILTER = 12 - - _ONE_WORDS = struct.Struct("> bit_in_word) & self._BIT_MASK - return flag + word_id, bit_in_word = divmod(neuron_id, self._BITS_IN_A_WORD) + return (bit_field[word_id] >> bit_in_word) & self._BIT_MASK def _calculate_core_data( self, app_graph, placements, progress, @@ -356,8 +348,8 @@ def __write_single_core_data( address = txrx.get_user_1_register_address_from_core(placement.p) txrx.write_memory( placement.x, placement.y, address, - self._ONE_WORDS.pack(bit_field_builder_region), - self._USER_BYTES) + self._ONE_WORD.pack(bit_field_builder_region), + self._ONE_WORD.size) def _check_for_success(self, executable_targets, transceiver): """ Goes through the cores checking for cores that have failed to\ @@ -382,6 +374,6 @@ def __get_status(self, core_subset, p, transceiver): x = core_subset.x y = core_subset.y user_2_address = transceiver.get_user_2_register_address_from_core(p) - result, = struct.unpack(" Date: Thu, 9 Jul 2020 12:57:08 +0100 Subject: [PATCH 03/11] Yet more tweaking extracted from a different old branch --- spynnaker/pyNN/abstract_spinnaker_common.py | 2 -- .../spynnaker_data_specification_writer.py | 15 ++++++--- ...ker_neuron_network_specification_report.py | 32 +++++++++++-------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index e8a0449687..d0790c18b0 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -23,8 +23,6 @@ MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.interface.abstract_spinnaker_base import ( AbstractSpinnakerBase) -from spinn_front_end_common.utilities.constants import ( - MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.utilities.exceptions import ConfigurationException from spinn_front_end_common.utility_models import CommandSender from spinn_front_end_common.utilities.utility_objs import ExecutableFinder diff --git a/spynnaker/pyNN/overridden_pacman_functions/spynnaker_data_specification_writer.py b/spynnaker/pyNN/overridden_pacman_functions/spynnaker_data_specification_writer.py index c4a34f03b8..e0b0542d24 100644 --- a/spynnaker/pyNN/overridden_pacman_functions/spynnaker_data_specification_writer.py +++ b/spynnaker/pyNN/overridden_pacman_functions/spynnaker_data_specification_writer.py @@ -28,7 +28,17 @@ def __call__( self, placements, hostname, report_default_directory, write_text_specs, machine, data_n_timesteps): # pylint: disable=too-many-arguments, signature-differs + return super(SpynnakerDataSpecificationWriter, self).__call__( + placements, hostname, report_default_directory, write_text_specs, + machine, data_n_timesteps, + placement_order=self.__sort_delays_to_end(placements)) + @staticmethod + def __sort_delays_to_end(placements): + """ + :param ~.Placements placements: + :rtype: list(~.Placement) + """ delay_extensions = list() placement_order = list() for placement in placements.placements: @@ -37,7 +47,4 @@ def __call__( else: placement_order.append(placement) placement_order.extend(delay_extensions) - - return super(SpynnakerDataSpecificationWriter, self).__call__( - placements, hostname, report_default_directory, write_text_specs, - machine, data_n_timesteps, placement_order) + return placement_order diff --git a/spynnaker/pyNN/utilities/spynnaker_neuron_network_specification_report.py b/spynnaker/pyNN/utilities/spynnaker_neuron_network_specification_report.py index 1962a27d08..a8ebf62972 100644 --- a/spynnaker/pyNN/utilities/spynnaker_neuron_network_specification_report.py +++ b/spynnaker/pyNN/utilities/spynnaker_neuron_network_specification_report.py @@ -34,6 +34,10 @@ class SpYNNakerNeuronGraphNetworkSpecificationReport(object): @staticmethod def _get_diagram(label): + """ + :param str label: + :rtype: ~graphviz.Digraph + """ # pylint: disable=import-error try: import graphviz @@ -44,8 +48,12 @@ def _get_diagram(label): return graphviz.Digraph(comment=label) def __call__(self, report_folder, application_graph): + """ + :param str report_folder: + :param ~.ApplicationGraph application_graph: + """ # create holders for data - vertex_holders = dict() + vertex_names = dict() dot_diagram = self._get_diagram( "The graph of the network in graphical form") @@ -56,29 +64,25 @@ def __call__(self, report_folder, application_graph): "generating the graphical representation of the neural network") # write vertices into dot diagram - for vertex_counter, vertex in progress.over( + for vertex_index, vertex in progress.over( enumerate(application_graph.vertices), False): - dot_diagram.node( - "{}".format(vertex_counter), - "{} ({} neurons)".format(vertex.label, vertex.n_atoms)) - vertex_holders[vertex] = vertex_counter + # Dot needs string names for each vertex; these are not labels + vertex_names[vertex] = str(vertex_index) + dot_diagram.node(vertex_names[vertex], "{} ({} neurons)".format( + vertex.label, vertex.n_atoms)) # write edges into dot diagram for partition in progress.over( application_graph.outgoing_edge_partitions, False): for edge in partition.edges: - source_vertex_id = vertex_holders[edge.pre_vertex] - dest_vertex_id = vertex_holders[edge.post_vertex] + pre_name = vertex_names[edge.pre_vertex] + post_name = vertex_names[edge.post_vertex] if isinstance(edge, ProjectionApplicationEdge): for synapse_info in edge.synapse_information: dot_diagram.edge( - "{}".format(source_vertex_id), - "{}".format(dest_vertex_id), - "{}".format(synapse_info.connector)) + pre_name, post_name, str(synapse_info.connector)) else: - dot_diagram.edge( - "{}".format(source_vertex_id), - "{}".format(dest_vertex_id)) + dot_diagram.edge(pre_name, post_name) # write dot file and generate pdf file_to_output = os.path.join(report_folder, "network_graph.gv") From 43c6b38d68dddcfa5c9d0f26d8e591d71c9d3595 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Fri, 10 Jul 2020 17:51:04 +0100 Subject: [PATCH 04/11] flake8/shorten class name/pylint/doc --- .../neuron/synapse_dynamics/__init__.py | 3 +- .../synapse_dynamics_structural_common.py | 4 +- .../synapse_dynamics_structural_static.py | 14 +- .../synapse_dynamics_structural_stdp.py | 14 +- .../redundant_packet_count_report.py | 125 +++++++++--------- 5 files changed, 79 insertions(+), 81 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py index 3ea25b6de0..81437512c6 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py @@ -22,7 +22,8 @@ from .pynn_synapse_dynamics import PyNNSynapseDynamics from .synapse_dynamics_static import SynapseDynamicsStatic from .synapse_dynamics_stdp import SynapseDynamicsSTDP -from .synapse_dynamics_structural_common import SynapseDynamicsStructuralCommon +from .synapse_dynamics_structural_common import ( + StructuralPlasticityCommon as SynapseDynamicsStructuralCommon) from .synapse_dynamics_structural_static import SynapseDynamicsStructuralStatic from .synapse_dynamics_structural_stdp import SynapseDynamicsStructuralSTDP diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py index 5ed0145697..336047fac2 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py @@ -26,7 +26,7 @@ from spynnaker.pyNN.exceptions import SynapticConfigurationException -class SynapseDynamicsStructuralCommon(object): +class StructuralPlasticityCommon(object): """ Utility class that holds properties of synaptic rewiring\ both in the presence and absence of STDP. @@ -500,7 +500,7 @@ def get_vertex_executable_suffix(self): def is_same_as(self, synapse_dynamics): """ - :param SynapseDynamicsStructuralCommon synapse_dynamics: + :param StructuralPlasticityCommon synapse_dynamics: :rtype: bool """ # Note noqa because exact type comparison is required here diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py index a815be6463..fe78cc16c6 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py @@ -16,9 +16,7 @@ from spinn_utilities.overrides import overrides from .abstract_synapse_dynamics_structural import ( AbstractSynapseDynamicsStructural) -from .synapse_dynamics_structural_common import ( - SynapseDynamicsStructuralCommon as - CommonSP) +from .synapse_dynamics_structural_common import StructuralPlasticityCommon from .synapse_dynamics_static import SynapseDynamicsStatic from .synapse_dynamics_stdp import SynapseDynamicsSTDP from .synapse_dynamics_structural_stdp import SynapseDynamicsStructuralSTDP @@ -38,10 +36,10 @@ class SynapseDynamicsStructuralStatic( def __init__( self, partner_selection, formation, elimination, - f_rew=CommonSP.DEFAULT_F_REW, - initial_weight=CommonSP.DEFAULT_INITIAL_WEIGHT, - initial_delay=CommonSP.DEFAULT_INITIAL_DELAY, - s_max=CommonSP.DEFAULT_S_MAX, seed=None, + f_rew=StructuralPlasticityCommon.DEFAULT_F_REW, + initial_weight=StructuralPlasticityCommon.DEFAULT_INITIAL_WEIGHT, + initial_delay=StructuralPlasticityCommon.DEFAULT_INITIAL_DELAY, + s_max=StructuralPlasticityCommon.DEFAULT_S_MAX, seed=None, weight=0.0, delay=1.0): """ :param AbstractPartnerSelection partner_selection: @@ -65,7 +63,7 @@ def __init__( super(SynapseDynamicsStructuralStatic, self).__init__( weight=weight, delay=delay, pad_to_length=s_max) - self.__common_sp = CommonSP( + self.__common_sp = StructuralPlasticityCommon( partner_selection, formation, elimination, f_rew, initial_weight, initial_delay, s_max, seed) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py index af46491dda..057ab64924 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py @@ -17,9 +17,7 @@ from .synapse_dynamics_stdp import SynapseDynamicsSTDP from .abstract_synapse_dynamics_structural import ( AbstractSynapseDynamicsStructural) -from .synapse_dynamics_structural_common import ( - SynapseDynamicsStructuralCommon as - CommonSP) +from .synapse_dynamics_structural_common import StructuralPlasticityCommon from spynnaker.pyNN.exceptions import SynapticConfigurationException @@ -38,10 +36,10 @@ def __init__( self, partner_selection, formation, elimination, timing_dependence=None, weight_dependence=None, voltage_dependence=None, dendritic_delay_fraction=1.0, - f_rew=CommonSP.DEFAULT_F_REW, - initial_weight=CommonSP.DEFAULT_INITIAL_WEIGHT, - initial_delay=CommonSP.DEFAULT_INITIAL_DELAY, - s_max=CommonSP.DEFAULT_S_MAX, seed=None, + f_rew=StructuralPlasticityCommon.DEFAULT_F_REW, + initial_weight=StructuralPlasticityCommon.DEFAULT_INITIAL_WEIGHT, + initial_delay=StructuralPlasticityCommon.DEFAULT_INITIAL_DELAY, + s_max=StructuralPlasticityCommon.DEFAULT_S_MAX, seed=None, weight=0.0, delay=1.0, backprop_delay=True): """ :param AbstractPartnerSelection partner_selection: @@ -73,7 +71,7 @@ def __init__( timing_dependence, weight_dependence, voltage_dependence, dendritic_delay_fraction, weight, delay, pad_to_length=s_max, backprop_delay=backprop_delay) - self.__common_sp = CommonSP( + self.__common_sp = StructuralPlasticityCommon( partner_selection, formation, elimination, f_rew, initial_weight, initial_delay, s_max, seed) diff --git a/spynnaker/pyNN/utilities/redundant_packet_count_report.py b/spynnaker/pyNN/utilities/redundant_packet_count_report.py index 8c18c1edd9..809d0b1c4a 100644 --- a/spynnaker/pyNN/utilities/redundant_packet_count_report.py +++ b/spynnaker/pyNN/utilities/redundant_packet_count_report.py @@ -13,10 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import logging from collections import defaultdict - +import logging +import os from spinn_utilities.log import FormatAdapter from spynnaker.pyNN.models.neuron import PopulationMachineVertex @@ -24,80 +23,82 @@ class RedundantPacketCountReport(object): + """ Reports how many packets were filtered by the packet filtering. + + :param provenance_items: + the collected provenance + :type provenance_items: + list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem) + :param str report_default_directory: where to write reports + """ + # The name of the report we create _FILE_NAME = "redundant_packet_count.rpt" + # The provenance items we care about for a vertex + _RELEVANT = frozenset([ + PopulationMachineVertex.GHOST_SEARCHES, + PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS, + PopulationMachineVertex.INVALID_MASTER_POP_HITS, + PopulationMachineVertex.SPIKES_PROCESSED]) + def __call__(self, provenance_items, report_default_directory): + """ + :param list(~.ProvenanceDataItem) provenance_items: + :param str report_default_directory: + """ file_name = os.path.join(report_default_directory, self._FILE_NAME) - try: with open(file_name, "w") as f: self._write_report(f, provenance_items) - except Exception: + except Exception: # pylint: disable=broad-except logger.exception("Generate_placement_reports: Can't open file" " {} for writing.", self._FILE_NAME) - @staticmethod - def _write_report(output, provenance_items): + def _write_report(self, output, provenance_items): + """ + :param ~io.TextIOBase output: + :param list(~.ProvenanceDataItem) provenance_items: + """ data = defaultdict(dict) - for provenance_item in provenance_items: last_name = provenance_item.names[-1] - key = provenance_item.names[0] - if ((last_name == PopulationMachineVertex.GHOST_SEARCHES) or - (last_name == - PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS) or - (last_name == - PopulationMachineVertex.INVALID_MASTER_POP_HITS) or - (last_name == PopulationMachineVertex.SPIKES_PROCESSED)): - + if last_name in self._RELEVANT: + key = provenance_item.names[0] # add to store data[key][last_name] = provenance_item.value - # accum enough data on a core to do summary - if len(data[key].keys()) == 4: + if len(data[key].keys()) == len(self._RELEVANT): + self.__write_core_summary(key, data[key], output) - # total packets received - total = ( - data[key][PopulationMachineVertex.GHOST_SEARCHES] + - data[key][ - PopulationMachineVertex. - BIT_FIELD_FILTERED_PACKETS] + - data[key][ - PopulationMachineVertex.INVALID_MASTER_POP_HITS] + - data[key][PopulationMachineVertex.SPIKES_PROCESSED]) - - # total redundant packets - redundant = ( - data[key][PopulationMachineVertex.GHOST_SEARCHES] + - data[key][ - PopulationMachineVertex. - BIT_FIELD_FILTERED_PACKETS] + - data[key][ - PopulationMachineVertex.INVALID_MASTER_POP_HITS]) - - percentage = 0 - if total != 0: - percentage = (100.0 / total) * redundant - - output.write( - "core {} \n\n" - " {} packets received.\n" - " {} were detected as redundant packets by the " - "bitfield filter.\n" - " {} were detected as having no " - "targets after the DMA stage.\n" - " {} were detected as " - "packets which we should not have received in the " - "first place. \n" - " Overall this makes a redundant " - "percentage of {}\n".format( - key, total, - data[key][ - PopulationMachineVertex. - BIT_FIELD_FILTERED_PACKETS], - data[key][PopulationMachineVertex.GHOST_SEARCHES], - data[key][ - PopulationMachineVertex. - INVALID_MASTER_POP_HITS], - percentage)) + @staticmethod + def __write_core_summary(key, items, output): + """ + :param str key: The name of the core + :param dict items: The relevant items for a core + :param ~io.TextIOBase output: + """ + # Extract + ghosts = items[PopulationMachineVertex.GHOST_SEARCHES] + filtered = items[PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS] + invalid = items[PopulationMachineVertex.INVALID_MASTER_POP_HITS] + spikes = items[PopulationMachineVertex.SPIKES_PROCESSED] + + # total packets received + total = ghosts + filtered + invalid + spikes + # total redundant packets + redundant = ghosts + filtered + invalid + + percentage = 0 + if total != 0: + percentage = 100.0 * redundant / total + + output.write( + "For core {}\n\n" + " {} packets received.\n" + " {} were detected as redundant by the bitfield filter.\n" + " {} were detected as having no targets after the DMA stage.\n" + " {} were detected as packets which we should not have " + "received in the first place.\n" + " Overall this makes a redundancy rate of {}%\n\n".format( + key, total, filtered, ghosts, invalid, percentage)) From b601262f1f746a94e22d04c91c6d9a0d04fafc8a Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 30 Oct 2017 10:53:07 +0000 Subject: [PATCH 05/11] Some minor refactorings --- .../push_bot_wifi_connection.py | 33 ++++--------------- .../pyNN/models/common/recording_utils.py | 4 +-- .../connectors/abstract_connector.py | 4 +-- 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py index 14508dcf37..48e23f5d39 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py @@ -14,11 +14,11 @@ # along with this program. If not, see . import logging -import platform import select import socket -import subprocess from six import raise_from +from spinn_utilities.overrides import overrides +from spinn_utilities.ping import Ping from spinnman.connections.abstract_classes import Listenable, Connection from spinnman.exceptions import SpinnmanIOException, SpinnmanTimeoutException from spinn_front_end_common.utilities.constants import BYTES_PER_KB @@ -102,28 +102,9 @@ def __init__(self, remote_host, remote_port=56000): # Set a general timeout on the socket self.__socket.settimeout(0) + @overrides(Connection.is_connected) def is_connected(self): - """ See\ - :py:meth:`~spinnman.connections.Connection.is_connected` - """ - if platform.platform().lower().startswith("windows"): - cmd_args = "-n 1 -w 1" - else: - cmd_args = "-c 1 -W 1" - - # check if machine is active and on the network - for _ in range(5): # Try up to five times... - # Start a ping process - process = subprocess.Popen( - "ping " + cmd_args + " " + self.__remote_ip_address, - shell=True, stdout=subprocess.PIPE) - process.wait() - if process.returncode == 0: - # ping worked - return True - - # If the ping fails this number of times, the host cannot be contacted - return False + return Ping.host_is_reachable(self.__remote_ip_address) @property def local_ip_address(self): @@ -190,18 +171,18 @@ def send(self, data): except Exception as e: # pylint: disable=broad-except raise_from(SpinnmanIOException(str(e)), e) + @overrides(Connection.close) def close(self): - """ See\ - :py:meth:`spinnman.connections.Connection.close` - """ try: self.__socket.shutdown(socket.SHUT_WR) except Exception: # pylint: disable=broad-except pass self.__socket.close() + @overrides(Listenable.is_ready_to_receive, extend_defaults=True) def is_ready_to_receive(self, timeout=0): return bool(select.select([self.__socket], [], [], timeout)[0]) + @overrides(Listenable.get_receive_method) def get_receive_method(self): return self.receive diff --git a/spynnaker/pyNN/models/common/recording_utils.py b/spynnaker/pyNN/models/common/recording_utils.py index a9c6bcc23a..c9312a36e9 100644 --- a/spynnaker/pyNN/models/common/recording_utils.py +++ b/spynnaker/pyNN/models/common/recording_utils.py @@ -109,9 +109,7 @@ def needs_buffering(buffer_max, space_needed, enable_buffered_recording): return False if not enable_buffered_recording: return False - if buffer_max < space_needed: - return True - return False + return buffer_max < space_needed def get_buffer_sizes(buffer_max, space_needed, enable_buffered_recording): diff --git a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py index eab6155166..419ee3013b 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py @@ -45,6 +45,7 @@ class AbstractConnector(with_metaclass(AbstractBase, object)): NUMPY_SYNAPSES_DTYPE = [("source", "uint32"), ("target", "uint16"), ("weight", "float64"), ("delay", "float64"), ("synapse_type", "uint8")] + _DISTANCE_REGEXP = re.compile(r'.*d\[\d*\].*') __slots__ = [ "_delays", @@ -333,8 +334,7 @@ def _expand_distances(self, d_expression): :param str d_expression: :rtype: bool """ - regexpr = re.compile(r'.*d\[\d*\].*') - return regexpr.match(d_expression) + return self._DISTANCE_REGEXP.match(d_expression) def _generate_random_values( self, values, n_connections, pre_vertex_slice, post_vertex_slice): From 37f1327cdabba2163d5cee1ceb818b668928df89 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Thu, 6 Aug 2020 13:03:37 +0100 Subject: [PATCH 06/11] Only make a logger if we're going to use it And add some more type annotation docs And refactor a little bit --- .../extra_algorithms/graph_edge_filter.py | 4 +- .../graph_edge_weight_updater.py | 3 - .../on_chip_bit_field_generator.py | 2 - .../redundant_packet_count_report.py | 3 +- ...spynnaker_connection_holder_generations.py | 17 ++- ...ker_neuron_network_specification_report.py | 3 - .../pyNN/extra_algorithms/synapse_expander.py | 109 +++++++++++------- 7 files changed, 83 insertions(+), 58 deletions(-) diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py index 3c3b16ef6b..2e00a4b414 100644 --- a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py +++ b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py @@ -57,10 +57,10 @@ def __call__(self, app_graph, machine_graph): for partition in progress.over(machine_graph.outgoing_edge_partitions): for edge in partition.edges: if self._is_filterable(edge): - logger.debug("this edge was pruned {}", edge) + logger.debug("this edge was pruned: {}", edge) prune_count += 1 continue - logger.debug("this edge was not pruned {}", edge) + logger.debug("this edge was not pruned: {}", edge) no_prune_count += 1 self._add_edge_to_new_graph(edge, partition, new_machine_graph) diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py index 5c19d9a890..ee9fc475f3 100644 --- a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py +++ b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py @@ -13,12 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_utilities.progress_bar import ProgressBar from spynnaker.pyNN.models.abstract_models import AbstractWeightUpdatable -logger = logging.getLogger(__name__) - class GraphEdgeWeightUpdater(object): """ Updates the weights of all edges. diff --git a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py index ce06e864dc..615475c010 100644 --- a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py +++ b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py @@ -14,7 +14,6 @@ # along with this program. If not, see . from collections import defaultdict -import logging import math import os import struct @@ -28,7 +27,6 @@ from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spinn_front_end_common.utilities.utility_objs import ExecutableType -logger = logging.getLogger(__name__) _ONE_WORD = struct.Struct(". +from collections import defaultdict import os import logging -from collections import defaultdict - from spinn_utilities.log import FormatAdapter from spynnaker.pyNN.models.neuron import PopulationMachineVertex diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py b/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py index 90f911c02e..411342dd36 100644 --- a/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py +++ b/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py @@ -13,13 +13,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_utilities.progress_bar import ProgressBar from spynnaker.pyNN.models.neuron import ConnectionHolder from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge -logger = logging.getLogger(__name__) - class SpYNNakerConnectionHolderGenerator(object): """ Sets up connection holders for reports to use. @@ -28,11 +25,14 @@ class SpYNNakerConnectionHolderGenerator(object): application_graph: app graph :return: the set of connection holders for after DSG generation - :rtype: dict(tuple(ProjectionApplicationEdge, SynapseInformation), \ + :rtype: dict(tuple(ProjectionApplicationEdge, SynapseInformation), ConnectionHolder) """ def __call__(self, application_graph): + """ + :param ~.ApplicationGraph application_graph: + """ progress = ProgressBar( application_graph.n_outgoing_edge_partitions, "Generating connection holders for reporting connection data.") @@ -41,7 +41,7 @@ def __call__(self, application_graph): for partition in progress.over( application_graph.outgoing_edge_partitions): for edge in partition.edges: - # add pre run generators so that reports can extract without + # add pre-run generators so that reports can extract without # going to machine. if isinstance(edge, ProjectionApplicationEdge): # build connection holders @@ -52,6 +52,13 @@ def __call__(self, application_graph): @staticmethod def _generate_holder_for_edge(edge, data_holders): + """ + :param ProjectionApplicationEdge edge: + :param data_holders: + :type data_holders: + dict(tuple(ProjectionApplicationEdge, SynapseInformation), + ConnectionHolder) + """ # build connection holders connection_holder = ConnectionHolder( None, True, edge.pre_vertex.n_atoms, edge.post_vertex.n_atoms) diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py b/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py index bab311ace1..1e45ee0b6a 100644 --- a/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py +++ b/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py @@ -13,14 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging import os from spinn_utilities.progress_bar import ProgressBar from spynnaker.pyNN.exceptions import SpynnakerException from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge -logger = logging.getLogger(__name__) - class SpYNNakerNeuronGraphNetworkSpecificationReport(object): """ Produces a report describing the graph created from the neural \ diff --git a/spynnaker/pyNN/extra_algorithms/synapse_expander.py b/spynnaker/pyNN/extra_algorithms/synapse_expander.py index e37a9064ad..05f122ca12 100644 --- a/spynnaker/pyNN/extra_algorithms/synapse_expander.py +++ b/spynnaker/pyNN/extra_algorithms/synapse_expander.py @@ -13,21 +13,17 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import functools -import logging from six import iteritems - -from spinn_front_end_common.utilities.system_control_logic import \ - run_system_application -from spinn_front_end_common.utilities.utility_objs import ExecutableType from spinn_utilities.progress_bar import ProgressBar from spinnman.model import ExecutableTargets from spinnman.model.enums import CPUState -from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.utilities.system_control_logic import ( + run_system_application) +from spinn_front_end_common.utilities.utility_objs import ExecutableType +from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron import AbstractPopulationVertex from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex -logger = logging.getLogger(__name__) - SYNAPSE_EXPANDER = "synapse_expander.aplx" DELAY_EXPANDER = "delay_expander.aplx" @@ -81,52 +77,83 @@ def _plan_expansion(app_graph, placements, synapse_expander_bin, # Add all machine vertices of the population vertex to ones # that need synapse expansion if isinstance(vertex, AbstractPopulationVertex): - gen_on_machine = False - for m_vertex in vertex.machine_vertices: - if vertex.gen_on_machine(m_vertex.vertex_slice): - placement = placements.get_placement_of_vertex(m_vertex) - expander_cores.add_processor( - synapse_expander_bin, - placement.x, placement.y, placement.p, - executable_type=ExecutableType.SYSTEM) - gen_on_machine = True + gen_on_machine = _plan_expansion_of_vertex( + vertex, placements, expander_cores, synapse_expander_bin) if gen_on_machine: expanded_pop_vertices.append(vertex) elif isinstance(vertex, DelayExtensionVertex): - for m_vertex in vertex.machine_vertices: - if vertex.gen_on_machine(m_vertex.vertex_slice): - placement = placements.get_placement_of_vertex(m_vertex) - expander_cores.add_processor( - delay_expander_bin, - placement.x, placement.y, placement.p, - executable_type=ExecutableType.SYSTEM) + _plan_expansion_of_vertex( + vertex, placements, expander_cores, delay_expander_bin) + # No post-expand actions for these return expander_cores, expanded_pop_vertices +def _plan_expansion_of_vertex( + vertex, placements, expander_cores, expander_binary): + """ + :param vertex: + :type vertex: AbstractPopulationVertex or DelayExtensionVertex + :param ~.Placements placements: + :param ~.ExecutableTargets expander_cores: + :param str expander_binary: + :return: True if any expander cores were added + :rtype: bool + """ + gen_on_machine = False + for m_vertex in vertex.machine_vertices: + if vertex.gen_on_machine(m_vertex.vertex_slice): + placement = placements.get_placement_of_vertex(m_vertex) + expander_cores.add_processor( + expander_binary, placement.x, placement.y, placement.p, + executable_type=ExecutableType.SYSTEM) + gen_on_machine = True + return gen_on_machine + + def _fill_in_connection_data( expander_cores, transceiver, expanded_pop_vertices, placements): - """ Once expander has run, fill in the connection data + """ Once expander has run, fill in the connection data we have for the\ + expanded connection matrix. - :rtype: None + :param ~.ExecutableTargets expander_cores: + :param ~.Transceiver transceiver: + :param list(AbstractPopulationVertex) expanded_pop_vertices: + :param ~.Placements placements: """ - ctl = globals_variables.get_simulator() - use_extra_monitors = False + # pylint: disable=unused-argument + ctl = get_simulator() for vertex in expanded_pop_vertices: - conn_holders = vertex.get_connection_holders() - for (app_edge, synapse_info), conn_holder_list in iteritems( - conn_holders): + for (edge, synapse_info), conn_holders in iteritems( + vertex.get_connection_holders()): # Only do this if this synapse_info has been generated # on the machine using the expander if synapse_info.may_generate_on_machine(): - machine_edges = app_edge.machine_edges - for machine_edge in machine_edges: - placement = placements.get_placement_of_vertex( - machine_edge.post_vertex) - conns = vertex.get_connections_from_machine( - transceiver, placement, machine_edge, - ctl.routing_infos, synapse_info, ctl.machine_time_step, - use_extra_monitors) - for conn_holder in conn_holder_list: - conn_holder.add_connections(conns) + _read_connections_for_app_edge_from_machine( + vertex, placements, transceiver, ctl, + edge, synapse_info, conn_holders) + + +def _read_connections_for_app_edge_from_machine( + vertex, placements, transceiver, ctl, + app_edge, synapse_info, conn_holder_list): + """ Reads (and records for later) the connections that were actually \ + generated on the machine for a particular application edge. + + :param AbstractPopulationVertex vertex: + :param ~.Placements placements: + :param ~.Transceiver transceiver: + :param ~.SimulatorInterface ctl: + :param ~.ApplicationEdge app_edge: + :param SynapseInformation synapse_info: + :param list(ConnectionHolder) conn_holder_list: + """ + use_extra_monitors = False + for edge in app_edge.machine_edges: + conns = vertex.get_connections_from_machine( + transceiver, placements.get_placement_of_vertex(edge.post_vertex), + edge, ctl.routing_infos, synapse_info, ctl.machine_time_step, + use_extra_monitors) + for conn_holder in conn_holder_list: + conn_holder.add_connections(conns) From fa561d3599dd71f958c46a78c316dc5d143be6f0 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Thu, 6 Aug 2020 16:01:07 +0100 Subject: [PATCH 07/11] Only make a logger if we're going to use it And use ceildiv and round_up. And so on and so on --- spynnaker/gsyn_tools.py | 2 +- spynnaker/pyNN/abstract_spinnaker_common.py | 6 +- .../ethernet_control_connection.py | 3 - .../pyNN/external_devices_models/__init__.py | 4 +- .../external_device_lif_control.py | 3 - .../external_device_lif_control_vertex.py | 3 - ...ernal_spinnaker_link_fpga_retina_device.py | 4 - .../munich_spinnaker_link_motor_device.py | 2 - .../abstract_push_bot_output_device.py | 3 +- .../push_bot_lif_ethernet.py | 5 +- .../push_bot_lif_spinnaker_link.py | 4 - .../push_bot_retina_connection.py | 3 - .../push_bot_spinnaker_link_retina_device.py | 4 - .../on_chip_bit_field_generator.py | 10 +- .../abstract_population_settable.py | 8 +- spynnaker/pyNN/models/abstract_pynn_model.py | 2 +- .../common/abstract_spike_recordable.py | 2 +- .../models/common/multi_spike_recorder.py | 24 +++-- .../pyNN/models/common/neuron_recorder.py | 19 ++-- .../pyNN/models/common/recording_utils.py | 2 - spynnaker/pyNN/models/defaults.py | 16 ++-- .../connectors/abstract_connector.py | 39 ++++---- .../abstract_generate_connector_on_machine.py | 20 ++-- .../connectors/all_to_all_connector.py | 4 - .../connectors/array_connector.py | 10 +- .../connectors/csa_connector.py | 4 - ...istance_dependent_probability_connector.py | 18 ++-- .../connectors/fixed_number_post_connector.py | 15 ++- .../connectors/fixed_number_pre_connector.py | 16 ++-- .../connectors/fixed_probability_connector.py | 23 +++-- .../connectors/from_list_connector.py | 15 ++- .../index_based_probability_connector.py | 16 ++-- .../connectors/kernel_connector.py | 10 +- .../connectors/multapse_connector.py | 16 ++-- .../connectors/one_to_one_connector.py | 4 - .../connectors/small_world_connector.py | 5 +- .../delay_afferent_machine_edge.py | 4 - .../projection_application_edge.py | 4 - .../neural_properties/neural_parameter.py | 16 ++-- .../neuron/abstract_population_vertex.py | 24 ++--- .../pyNN/models/neuron/master_pop_table.py | 20 ++-- .../models/neuron/plasticity/stdp/common.py | 2 - .../abstract_timing_dependence.py | 2 +- ...timing_dependence_pfister_spike_triplet.py | 6 +- .../timing_dependence_spike_nearest_pair.py | 4 - .../timing_dependence_spike_pair.py | 4 - .../timing_dependence_vogels_2011.py | 7 +- .../abstract_weight_dependence.py | 2 +- .../formation/distance_dependent_formation.py | 6 +- .../abstract_plastic_synapse_dynamics.py | 10 +- .../abstract_static_synapse_dynamics.py | 8 +- .../abstract_synapse_dynamics.py | 4 +- .../synapse_dynamics_static.py | 3 +- .../synapse_dynamics/synapse_dynamics_stdp.py | 10 +- .../synapse_dynamics_structural_common.py | 16 ++-- .../synapse_dynamics_structural_static.py | 4 +- .../synapse_dynamics_structural_stdp.py | 4 +- spynnaker/pyNN/models/neuron/synapse_io.py | 6 +- .../pyNN/models/neuron/synaptic_manager.py | 24 ++--- .../pyNN/models/pynn_population_common.py | 31 +++--- .../pyNN/models/pynn_projection_common.py | 8 +- spynnaker/pyNN/models/recording_common.py | 2 +- .../spike_source/spike_source_array_vertex.py | 6 +- .../spike_source_poisson_vertex.py | 17 ++-- .../utility_models/delays/delay_block.py | 6 +- .../delays/delay_extension_vertex.py | 27 +++--- .../spike_injector/spike_injector_vertex.py | 4 +- .../munich_io_spinnaker_link_protocol.py | 4 - .../pyNN/utilities/bit_field_utilities.py | 94 +++++++++---------- spynnaker/pyNN/utilities/constants.py | 3 + .../random_stats/abstract_random_stats.py | 4 +- spynnaker/pyNN/utilities/utility_calls.py | 26 +++-- 72 files changed, 334 insertions(+), 432 deletions(-) diff --git a/spynnaker/gsyn_tools.py b/spynnaker/gsyn_tools.py index 6cbcf077b6..80ec836511 100644 --- a/spynnaker/gsyn_tools.py +++ b/spynnaker/gsyn_tools.py @@ -54,7 +54,7 @@ def check_sister_gysn(sister, n_neurons, runtime, gsyn): """ Compare an arrays of conductances with baseline data from a file next\ to a specified module. For testing. - :param sister: A module. The file read from will be ``gsyn.data`` \ + :param sister: A module. The file read from will be ``gsyn.data`` adjacent to this module. :param n_neurons: The number of neurons that produced the data. :param runtime: The length of time that the generated data represents. diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 9d0eee2b40..4f9f6ce749 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -36,6 +36,7 @@ SpynnakerSimulatorInterface) from spynnaker.pyNN.utilities.extracted_data import ExtractedData from spynnaker import __version__ as version +from spynnaker.pyNN.utilities.utility_calls import round_up logger = FormatAdapter(logging.getLogger(__name__)) @@ -239,7 +240,7 @@ def _set_up_timings( self.set_up_timings(timestep, time_scale_factor) else: self.set_up_timings( - math.ceil(timestep * MICRO_TO_MILLISECOND_CONVERSION), + round_up(timestep * MICRO_TO_MILLISECOND_CONVERSION), time_scale_factor) # Sort out the minimum delay @@ -275,8 +276,7 @@ def _set_up_timings( else: self.__max_delay = ( max_delay_tics_supported * ( - self.machine_time_step / - MICRO_TO_MILLISECOND_CONVERSION)) + self.machine_time_step / MICRO_TO_MILLISECOND_CONVERSION)) # Sort out the time scale factor if not user specified # (including config) diff --git a/spynnaker/pyNN/connections/ethernet_control_connection.py b/spynnaker/pyNN/connections/ethernet_control_connection.py index 320d8f3cc4..c74ab85be7 100644 --- a/spynnaker/pyNN/connections/ethernet_control_connection.py +++ b/spynnaker/pyNN/connections/ethernet_control_connection.py @@ -13,12 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_front_end_common.utility_models import MultiCastCommand from spinn_front_end_common.utilities.connections import LiveEventConnection -logger = logging.getLogger(__name__) - class EthernetControlConnection(LiveEventConnection): """ A connection that can translate Ethernet control messages received\ diff --git a/spynnaker/pyNN/external_devices_models/__init__.py b/spynnaker/pyNN/external_devices_models/__init__.py index 4d5871a858..15eab73669 100644 --- a/spynnaker/pyNN/external_devices_models/__init__.py +++ b/spynnaker/pyNN/external_devices_models/__init__.py @@ -17,7 +17,7 @@ from .abstract_ethernet_sensor import AbstractEthernetSensor from .abstract_ethernet_translator import AbstractEthernetTranslator from .abstract_multicast_controllable_device import ( - AbstractMulticastControllableDevice) + AbstractMulticastControllableDevice, SendType) from .arbitrary_fpga_device import ArbitraryFPGADevice from .external_device_lif_control import ExternalDeviceLifControl from .external_spinnaker_link_cochlea_device import ExternalCochleaDevice @@ -32,5 +32,5 @@ "AbstractEthernetTranslator", "ArbitraryFPGADevice", "AbstractMulticastControllableDevice", "ExternalDeviceLifControl", "ExternalCochleaDevice", "ExternalFPGARetinaDevice", - "MunichMotorDevice", "MunichRetinaDevice", + "MunichMotorDevice", "MunichRetinaDevice", "SendType", "ThresholdTypeMulticastDeviceControl"] diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py index ac49da35b1..baaaff5437 100644 --- a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py +++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py @@ -13,7 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.exceptions import ConfigurationException from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard @@ -27,8 +26,6 @@ from .threshold_type_multicast_device_control import ( ThresholdTypeMulticastDeviceControl) -logger = logging.getLogger(__name__) - class ExternalDeviceLifControl(AbstractPyNNNeuronModelStandard): """ Abstract control module for the PushBot, based on the LIF neuron,\ diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py index 34c6ae6e23..8b7977c276 100644 --- a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py +++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py @@ -14,7 +14,6 @@ # along with this program. If not, see . from collections import OrderedDict -import logging from spinn_utilities.overrides import overrides from pacman.model.constraints.key_allocator_constraints import ( FixedKeyAndMaskConstraint) @@ -26,8 +25,6 @@ from spynnaker.pyNN.models.neuron import AbstractPopulationVertex from .abstract_ethernet_controller import AbstractEthernetController -logger = logging.getLogger(__name__) - class ExternalDeviceLifControlVertex( AbstractPopulationVertex, diff --git a/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py b/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py index 2855636d2a..f4e775fb65 100644 --- a/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py +++ b/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from pacman.model.constraints.key_allocator_constraints import ( FixedKeyAndMaskConstraint) @@ -28,8 +26,6 @@ from spinn_front_end_common.utility_models import MultiCastCommand from spynnaker.pyNN.exceptions import SpynnakerException -logger = logging.getLogger(__name__) - def get_y_from_fpga_retina(key, mode): if mode == 128: diff --git a/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py b/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py index 81bc0e1585..0cfe3d8e37 100644 --- a/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py +++ b/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py @@ -13,7 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_utilities.overrides import overrides from pacman.executor.injection_decorator import inject_items from pacman.model.constraints.key_allocator_constraints import ( @@ -36,7 +35,6 @@ from spynnaker.pyNN.exceptions import SpynnakerException from spynnaker.pyNN.models.defaults import defaults -logger = logging.getLogger(__name__) MOTOR_PARTITION_ID = "MOTOR" diff --git a/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py b/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py index 822edc2ad9..0e03de7386 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py @@ -14,8 +14,7 @@ # along with this program. If not, see . from enum import Enum -from spynnaker.pyNN.external_devices_models\ - .abstract_multicast_controllable_device import SendType +from spynnaker.pyNN.external_devices_models import SendType class AbstractPushBotOutputDevice(Enum): diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py index a51f02d0f1..54c46d2e08 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py @@ -16,11 +16,8 @@ from spynnaker.pyNN.models.defaults import default_initial_values from spynnaker.pyNN.external_devices_models.push_bot.push_bot_ethernet \ import ( - PushBotTranslator) + PushBotTranslator, get_pushbot_wifi_connection) from spynnaker.pyNN.external_devices_models import ExternalDeviceLifControl -from spynnaker.pyNN.external_devices_models.push_bot.push_bot_ethernet \ - import ( - get_pushbot_wifi_connection) class PushBotLifEthernet(ExternalDeviceLifControl): diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py index 737abdd1d7..7e5e6d6245 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py @@ -12,14 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spynnaker.pyNN.external_devices_models import ExternalDeviceLifControl from spynnaker.pyNN.protocols import MunichIoSpiNNakerLinkProtocol from spynnaker.pyNN.models.defaults import default_initial_values -logger = logging.getLogger(__name__) - class PushBotLifSpinnakerLink(ExternalDeviceLifControl): """ Control module for a PushBot connected to a SpiNNaker Link diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py index fe016e1f7f..da2ce6c4f4 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from threading import RLock import numpy from spinnman.connections import ConnectionListener @@ -23,7 +21,6 @@ import ( PushBotRetinaResolution) -logger = logging.getLogger(__name__) _RETINA_PACKET_SIZE = BYTES_PER_SHORT diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py index dd583c6ab5..0f663f400e 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from pacman.executor.injection_decorator import inject, supports_injection from pacman.model.graphs.application import ApplicationSpiNNakerLinkVertex @@ -21,8 +19,6 @@ from spynnaker.pyNN.external_devices_models.push_bot import ( AbstractPushBotRetinaDevice) -logger = logging.getLogger(__name__) - @supports_injection class PushBotSpiNNakerLinkRetinaDevice( diff --git a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py index 615475c010..e4ba3ad8cd 100644 --- a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py +++ b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py @@ -14,7 +14,6 @@ # along with this program. If not, see . from collections import defaultdict -import math import os import struct from spinn_utilities.progress_bar import ProgressBar @@ -26,6 +25,7 @@ run_system_application) from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spinn_front_end_common.utilities.utility_objs import ExecutableType +from spynnaker.pyNN.utilities.constants import BITS_PER_WORD _ONE_WORD = struct.Struct("> bit_in_word) & cls._BIT_MASK return flag diff --git a/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py b/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py index 373af12a5e..d3643dbfa2 100644 --- a/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py +++ b/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py @@ -38,8 +38,8 @@ def get_value_by_selector(self, selector, key): """ Gets the value for a particular key but only for the selected\ subset. - :param selector: See \ - :py:meth:`~spinn_utilities.ranged.RangedList.get_value_by_selector`\ + :param selector: See + :py:meth:`~spinn_utilities.ranged.RangedList.get_value_by_selector` as this is just a pass through method :type selector: None or slice or int or list(bool) or list(int) :param str key: the name of the parameter to change @@ -60,8 +60,8 @@ def set_value_by_selector(self, selector, key, value): """ Sets the value for a particular key but only for the selected \ subset. - :param selector: See \ - :py:class:`~spinn_utilities.ranged.RangedList`.set_value_by_selector\ + :param selector: See + :py:meth:`~spinn_utilities.ranged.RangedList.set_value_by_selector` as this is just a pass through method :type selector: None or slice or int or list(bool) or list(int) :param str key: the name of the parameter to change diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py index 65048ddf66..0b78ed2212 100644 --- a/spynnaker/pyNN/models/abstract_pynn_model.py +++ b/spynnaker/pyNN/models/abstract_pynn_model.py @@ -100,7 +100,7 @@ def has_parameter(cls, name): @abstractproperty def default_population_parameters(self): """ Get the default values for the parameters at the population level - These are parameters that can be passed in to the Population\ + These are parameters that can be passed in to the Population constructor in addition to the standard PyNN options :rtype: dict(str, Any) diff --git a/spynnaker/pyNN/models/common/abstract_spike_recordable.py b/spynnaker/pyNN/models/common/abstract_spike_recordable.py index b18ef17c83..b31e410af1 100644 --- a/spynnaker/pyNN/models/common/abstract_spike_recordable.py +++ b/spynnaker/pyNN/models/common/abstract_spike_recordable.py @@ -71,7 +71,7 @@ def get_spikes(self, placements, buffer_manager, machine_time_step): ~spinn_front_end_common.interface.buffer_management.BufferManager :param int machine_time_step: the time step of the simulation, in microseconds - :return: A numpy array of 2-element arrays of (neuron_id, time)\ + :return: A numpy array of 2-element arrays of (neuron_id, time) ordered by time, one element per event :rtype: ~numpy.ndarray(tuple(int,int)) """ diff --git a/spynnaker/pyNN/models/common/multi_spike_recorder.py b/spynnaker/pyNN/models/common/multi_spike_recorder.py index c1d917560f..dbf4b3aee2 100644 --- a/spynnaker/pyNN/models/common/multi_spike_recorder.py +++ b/spynnaker/pyNN/models/common/multi_spike_recorder.py @@ -12,18 +12,17 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import math import logging import struct import numpy -from pacman.model.resources.constant_sdram import ConstantSDRAM from spinn_utilities.progress_bar import ProgressBar from spinn_utilities.log import FormatAdapter -from spynnaker.pyNN.models.common import recording_utils -from pacman.model.resources.variable_sdram import VariableSDRAM +from pacman.model.resources import ConstantSDRAM, VariableSDRAM from spinn_front_end_common.utilities.constants import ( - BYTES_PER_WORD, BITS_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) + BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) +from spynnaker.pyNN.models.common.recording_utils import make_missing_string +from spynnaker.pyNN.utilities.utility_calls import ceildiv +from spynnaker.pyNN.utilities.constants import BITS_PER_WORD logger = FormatAdapter(logging.getLogger(__name__)) _TWO_WORDS = struct.Struct(". from __future__ import division -import logging import struct import numpy from spinn_front_end_common.utilities.helpful_functions import ( @@ -22,7 +21,6 @@ from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spynnaker.pyNN.exceptions import MemReadException -logger = logging.getLogger(__name__) _RECORDING_COUNT = struct.Struct(". - -import logging import numpy from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import BYTES_PER_WORD @@ -25,8 +23,6 @@ N_GEN_PARAMS = 1 -logger = logging.getLogger(__file__) - class AllToAllConnector(AbstractGenerateConnectorOnMachine, AbstractConnectorSupportsViewsOnMachine): diff --git a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py index 8d25c7bdf8..0ccbdde520 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py @@ -12,14 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import numpy from spinn_utilities.overrides import overrides from .abstract_connector import AbstractConnector -logger = logging.getLogger(__name__) - class ArrayConnector(AbstractConnector): """ Make connections using an array of integers based on the IDs\ @@ -32,9 +28,9 @@ class ArrayConnector(AbstractConnector): def __init__(self, array, safe=True, callback=None, verbose=False): """ :param array: - An explicit boolean matrix that specifies the connections\ - between the pre- and post-populations\ - (see PyNN documentation). Must be 2D in practice. + An explicit boolean matrix that specifies the connections between + the pre- and post-populations (see PyNN documentation). + Must be 2D in practice. :type array: ~numpy.ndarray(2, ~numpy.uint8) :param bool safe: :param callable callback: Ignored diff --git a/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py index 4c33b01e59..1ebaa91357 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import numpy from spinn_utilities.overrides import overrides from .abstract_connector import AbstractConnector @@ -24,8 +22,6 @@ # Importing csa causes problems with readthedocs so allowing it to fail _csa_found = (False, _ex) -logger = logging.getLogger(__name__) - class CSAConnector(AbstractConnector): """ Make connections using a Connection Set Algebra (Djurfeldt 2012)\ diff --git a/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py index 84f522378b..da947829e1 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import math import numpy from numpy import ( @@ -22,10 +20,10 @@ minimum, e, pi) from spinn_utilities.overrides import overrides from spinn_utilities.safe_eval import SafeEval -from spynnaker.pyNN.utilities import utility_calls +from spynnaker.pyNN.utilities.utility_calls import ( + get_probable_maximum_selected, round_up) from .abstract_connector import AbstractConnector -logger = logging.getLogger(__name__) # support for arbitrary expression for the distance dependence _d_expr_context = SafeEval(math, numpy, arccos, arcsin, arctan, arctan2, ceil, cos, cosh, exp, fabs, floor, fmod, hypot, ldexp, @@ -112,8 +110,7 @@ def _set_probabilities(self, synapse_info): @overrides(AbstractConnector.get_delay_maximum) def get_delay_maximum(self, synapse_info): return self._get_delay_maximum( - synapse_info.delays, - utility_calls.get_probable_maximum_selected( + synapse_info.delays, get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, numpy.amax(self.__probs))) @@ -126,12 +123,12 @@ def get_n_connections_from_pre_vertex_maximum( max_prob = numpy.amax( self.__probs[0:synapse_info.n_pre_neurons, post_vertex_slice.as_slice]) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, post_vertex_slice.n_atoms, max_prob) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, @@ -141,7 +138,7 @@ def get_n_connections_from_pre_vertex_maximum( @overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum) def get_n_connections_to_post_vertex_maximum(self, synapse_info): # pylint: disable=too-many-arguments - return utility_calls.get_probable_maximum_selected( + return get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_post_neurons, numpy.amax(self.__probs)) @@ -150,8 +147,7 @@ def get_n_connections_to_post_vertex_maximum(self, synapse_info): def get_weight_maximum(self, synapse_info): # pylint: disable=too-many-arguments return self._get_weight_maximum( - synapse_info.weights, - utility_calls.get_probable_maximum_selected( + synapse_info.weights, get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, numpy.amax(self.__probs))) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py index da9f71aee1..463106cd2e 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py @@ -14,8 +14,6 @@ # along with this program. If not, see . from __future__ import print_function -import logging -import math import numpy from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import BYTES_PER_WORD @@ -24,13 +22,12 @@ AbstractGenerateConnectorOnMachine, ConnectorIDs) from .abstract_connector_supports_views_on_machine import ( AbstractConnectorSupportsViewsOnMachine) -from spynnaker.pyNN.utilities import utility_calls from spynnaker.pyNN.exceptions import SpynnakerException +from spynnaker.pyNN.utilities.utility_calls import ( + round_up, get_probable_maximum_selected) N_GEN_PARAMS = 8 -logger = logging.getLogger(__file__) - class FixedNumberPostConnector(AbstractGenerateConnectorOnMachine, AbstractConnectorSupportsViewsOnMachine): @@ -202,12 +199,12 @@ def get_n_connections_from_pre_vertex_maximum( prob_in_slice = min( post_vertex_slice.n_atoms / float( synapse_info.n_post_neurons), 1.0) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, self.__n_post, prob_in_slice, chance=1.0/100000.0) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, @@ -218,11 +215,11 @@ def get_n_connections_from_pre_vertex_maximum( def get_n_connections_to_post_vertex_maximum(self, synapse_info): # pylint: disable=too-many-arguments selection_prob = 1.0 / float(synapse_info.n_post_neurons) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons, selection_prob, chance=1.0/100000.0) - return int(math.ceil(n_connections)) + return round_up(n_connections) @overrides(AbstractConnector.get_weight_maximum) def get_weight_maximum(self, synapse_info): diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py index 4f31127f1b..8f3960cc6b 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py @@ -12,24 +12,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging -import math import numpy from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from .abstract_connector import AbstractConnector from .abstract_generate_connector_on_machine import ( AbstractGenerateConnectorOnMachine, ConnectorIDs) -from spynnaker.pyNN.utilities import utility_calls +from spynnaker.pyNN.utilities.utility_calls import ( + get_probable_maximum_selected, round_up) from spynnaker.pyNN.exceptions import SpynnakerException from .abstract_connector_supports_views_on_machine import ( AbstractConnectorSupportsViewsOnMachine) N_GEN_PARAMS = 8 -logger = logging.getLogger(__file__) - class FixedNumberPreConnector(AbstractGenerateConnectorOnMachine, AbstractConnectorSupportsViewsOnMachine): @@ -70,7 +66,7 @@ def __init__( :type rng: ~pyNN.random.NumpyRNG or None """ # :param ~pyNN.space.Space space: - # a Space object, needed if you wish to specify distance-dependent\ + # a Space object, needed if you wish to specify distance-dependent # weights or delays - not implemented super(FixedNumberPreConnector, self).__init__(safe, callback, verbose) self.__n_pre = n @@ -201,19 +197,19 @@ def get_n_connections_from_pre_vertex_maximum( max_delay=None): # pylint: disable=too-many-arguments prob_selection = 1.0 / float(synapse_info.n_pre_neurons) - n_connections_total = utility_calls.get_probable_maximum_selected( + n_connections_total = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, self.__n_pre * synapse_info.n_post_neurons, prob_selection, chance=1.0/10000.0) prob_in_slice = min( float(post_vertex_slice.n_atoms) / float( synapse_info.n_post_neurons), 1.0) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, n_connections_total, prob_in_slice, chance=1.0/100000.0) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py index 75021337b2..ce25056ab2 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py @@ -12,19 +12,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import math import numpy from spinn_utilities.overrides import overrides from data_specification.enums.data_type import DataType from spinn_front_end_common.utilities.exceptions import ConfigurationException -from spynnaker.pyNN.utilities import utility_calls +from spinn_front_end_common.utilities.constants import BYTES_PER_WORD +from spynnaker.pyNN.utilities.utility_calls import ( + round_up, get_probable_maximum_selected) from .abstract_connector import AbstractConnector from .abstract_generate_connector_on_machine import ( AbstractGenerateConnectorOnMachine, ConnectorIDs) from .abstract_connector_supports_views_on_machine import ( AbstractConnectorSupportsViewsOnMachine) -from spinn_front_end_common.utilities.constants import BYTES_PER_WORD N_GEN_PARAMS = 6 @@ -43,11 +42,11 @@ def __init__( callback=None, verbose=False, rng=None): """ :param float p_connect: - a float between zero and one. Each potential connection is created\ + a float between zero and one. Each potential connection is created with this probability. :param bool allow_self_connections: - if the connector is used to connect a Population to itself, this\ - flag determines whether a neuron is allowed to connect to itself,\ + if the connector is used to connect a Population to itself, this + flag determines whether a neuron is allowed to connect to itself, or only to other neurons in the Population. :param bool safe: :param callable callback: Ignored @@ -67,7 +66,7 @@ def __init__( @overrides(AbstractConnector.get_delay_maximum) def get_delay_maximum(self, synapse_info): - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, self._p_connect) @@ -78,12 +77,12 @@ def get_n_connections_from_pre_vertex_maximum( self, post_vertex_slice, synapse_info, min_delay=None, max_delay=None): # pylint: disable=too-many-arguments - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, post_vertex_slice.n_atoms, self._p_connect, chance=1.0/10000.0) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, @@ -93,7 +92,7 @@ def get_n_connections_from_pre_vertex_maximum( @overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum) def get_n_connections_to_post_vertex_maximum(self, synapse_info): # pylint: disable=too-many-arguments - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons, self._p_connect, chance=1.0/10000.0) @@ -102,7 +101,7 @@ def get_n_connections_to_post_vertex_maximum(self, synapse_info): @overrides(AbstractConnector.get_weight_maximum) def get_weight_maximum(self, synapse_info): # pylint: disable=too-many-arguments - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, self._p_connect) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py index c5b830f51a..d12e4be4c5 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py @@ -13,7 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging import numpy from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( @@ -22,8 +21,6 @@ from .abstract_connector import AbstractConnector from spynnaker.pyNN.exceptions import InvalidParameterType -logger = logging.getLogger(__name__) - # Indices of the source and target in the connection list array _SOURCE = 0 _TARGET = 1 @@ -371,9 +368,11 @@ def conn_list(self, conn_list): @property def column_names(self): - """ The names of the columns in the array after the first two. \ - Of particular interest is whether ``weight`` and ``delay`` columns\ - are present. + """ The names of the columns in the array after the first two. + + .. note:: + Of particular interest is whether ``weight`` and ``delay`` columns + are present. :rtype: list(str) """ @@ -384,8 +383,8 @@ def column_names(self, column_names): self.__column_names = column_names def get_extra_parameters(self): - """ Getter for the extra parameters. Excludes ``weight`` and\ - ``delay`` columns. + """ Getter for the extra parameters. Excludes ``weight`` and + ``delay`` columns. :return: The extra parameters :rtype: ~numpy.ndarray diff --git a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py index 1b7a0250ae..a38dfbdace 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import math import numpy from numpy import ( @@ -22,10 +20,10 @@ minimum, e, pi) from spinn_utilities.overrides import overrides from spinn_utilities.safe_eval import SafeEval -from spynnaker.pyNN.utilities import utility_calls +from spynnaker.pyNN.utilities.utility_calls import ( + get_probable_maximum_selected, round_up) from .abstract_connector import AbstractConnector -logger = logging.getLogger(__name__) # support for arbitrary expression for the indices _index_expr_context = SafeEval(math, numpy, arccos, arcsin, arctan, arctan2, ceil, cos, cosh, exp, fabs, floor, fmod, hypot, @@ -84,7 +82,7 @@ def _update_probs_from_index_expression(self, synapse_info): @overrides(AbstractConnector.get_delay_maximum) def get_delay_maximum(self, synapse_info): self._update_probs_from_index_expression(synapse_info) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, numpy.amax(self.__probs)) @@ -95,12 +93,12 @@ def get_n_connections_from_pre_vertex_maximum( self, post_vertex_slice, synapse_info, min_delay=None, max_delay=None): self._update_probs_from_index_expression(synapse_info) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, post_vertex_slice.n_atoms, numpy.amax(self.__probs)) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, @@ -110,14 +108,14 @@ def get_n_connections_from_pre_vertex_maximum( @overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum) def get_n_connections_to_post_vertex_maximum(self, synapse_info): self._update_probs_from_index_expression(synapse_info) - return utility_calls.get_probable_maximum_selected( + return get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons, numpy.amax(self.__probs)) @overrides(AbstractConnector.get_weight_maximum) def get_weight_maximum(self, synapse_info): self._update_probs_from_index_expression(synapse_info) - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( synapse_info.n_pre_neurons * synapse_info.n_post_neurons, synapse_info.n_pre_neurons * synapse_info.n_post_neurons, numpy.amax(self.__probs)) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py index b64d4cb110..668e3d5ca9 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py @@ -65,11 +65,11 @@ def __init__( :type shape_kernel: list(int) or tuple(int,int) :param weight_kernel: (optional) 2D matrix of size shape_kernel describing the weights - :type weight_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG \ + :type weight_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float or list(int) or list(float) or None :param delay_kernel: (optional) 2D matrix of size shape_kernel describing the delays - :type delay_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG \ + :type delay_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float or list(int) or list(float) or None :param shape_common: (optional) 2D shape of common coordinate system (for both pre and post, @@ -200,7 +200,7 @@ def __get_kernel_vals(self, vals): """ Convert kernel values given into the correct format. :param vals: - :type vals: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray\ + :type vals: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray or ConvolutionKernel :rtype: ~numpy.ndarray """ @@ -228,10 +228,10 @@ def __compute_statistics( """ Compute the relevant information required for the connections. :param weights: - :type weights: int or float or ~pyNN.random.NumpyRNG or \ + :type weights: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray or ConvolutionKernel :param delays: - :type delays: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray\ + :type delays: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray or ConvolutionKernel :param ~pacman.model.graphs.common.Slice pre_vertex_slice: :param ~pacman.model.graphs.common.Slice post_vertex_slice: diff --git a/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py index f0229340b0..060f4d8a02 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py @@ -12,16 +12,14 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging -import math import numpy.random from six import raise_from from spinn_utilities.abstract_base import abstractmethod from spinn_utilities.overrides import overrides from pacman.model.graphs.common import Slice from spinn_front_end_common.utilities.constants import BYTES_PER_WORD -from spynnaker.pyNN.utilities import utility_calls +from spynnaker.pyNN.utilities.utility_calls import ( + get_probable_maximum_selected, round_up) from spynnaker.pyNN.exceptions import SpynnakerException from .abstract_connector import AbstractConnector from .abstract_generate_connector_on_machine import ( @@ -31,8 +29,6 @@ N_GEN_PARAMS = 8 -logger = logging.getLogger(__name__) - class MultapseConnector(AbstractGenerateConnectorOnMachine, AbstractConnectorSupportsViewsOnMachine): @@ -148,14 +144,14 @@ def get_n_connections_from_pre_vertex_maximum( prob_in_slice = min( post_vertex_slice.n_atoms / float(synapse_info.n_post_neurons), 1.0) - max_in_slice = utility_calls.get_probable_maximum_selected( + max_in_slice = get_probable_maximum_selected( self.__num_synapses, self.__num_synapses, prob_in_slice) prob_in_row = 1.0 / synapse_info.n_pre_neurons - n_connections = utility_calls.get_probable_maximum_selected( + n_connections = get_probable_maximum_selected( self.__num_synapses, max_in_slice, prob_in_row) if min_delay is None or max_delay is None: - return int(math.ceil(n_connections)) + return round_up(n_connections) return self._get_n_connections_from_pre_vertex_with_delay_maximum( synapse_info.delays, @@ -165,7 +161,7 @@ def get_n_connections_from_pre_vertex_maximum( @overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum) def get_n_connections_to_post_vertex_maximum(self, synapse_info): prob_of_choosing_post_atom = 1.0 / synapse_info.n_post_neurons - return utility_calls.get_probable_maximum_selected( + return get_probable_maximum_selected( self.__num_synapses, self.__num_synapses, prob_of_choosing_post_atom) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py index f730ddacfb..b1bbcfbbe5 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import numpy from spinn_utilities.overrides import overrides from .abstract_connector import AbstractConnector @@ -22,8 +20,6 @@ from .abstract_connector_supports_views_on_machine import ( AbstractConnectorSupportsViewsOnMachine) -logger = logging.getLogger(__name__) - class OneToOneConnector(AbstractGenerateConnectorOnMachine, AbstractConnectorSupportsViewsOnMachine): diff --git a/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py index 9df9a7e4cb..7c6cc61c87 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py @@ -12,11 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math - import numpy from spinn_utilities.overrides import overrides from .abstract_connector import AbstractConnector +from spynnaker.pyNN.utilities.utility_calls import round_up class SmallWorldConnector(AbstractConnector): @@ -85,7 +84,7 @@ def _set_n_connections(self, synapse_info): self.__mask = (d < self.__degree).astype(float) - self.__n_connections = int(math.ceil(numpy.sum(self.__mask))) + self.__n_connections = round_up(numpy.sum(self.__mask)) @overrides(AbstractConnector.get_delay_maximum) def get_delay_maximum(self, synapse_info): diff --git a/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py b/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py index 1d4faef5be..8d8777c166 100644 --- a/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py +++ b/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py @@ -12,15 +12,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from pacman.model.graphs.machine import MachineEdge from spynnaker.pyNN.models.abstract_models import ( AbstractWeightUpdatable, AbstractFilterableEdge) -logger = logging.getLogger(__name__) - class DelayAfferentMachineEdge( MachineEdge, AbstractFilterableEdge, AbstractWeightUpdatable): diff --git a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py index 1b61795507..7d21ef22cc 100644 --- a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py +++ b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py @@ -12,14 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from pacman.model.graphs.application import ApplicationEdge from .projection_machine_edge import ProjectionMachineEdge from spynnaker.pyNN.models.abstract_models import AbstractFilterableEdge - -logger = logging.getLogger(__name__) _DynamicsStructural = None diff --git a/spynnaker/pyNN/models/neural_properties/neural_parameter.py b/spynnaker/pyNN/models/neural_properties/neural_parameter.py index bc1887e6e8..757d591c97 100644 --- a/spynnaker/pyNN/models/neural_properties/neural_parameter.py +++ b/spynnaker/pyNN/models/neural_properties/neural_parameter.py @@ -111,8 +111,8 @@ def __init__(self, value, datatype, slice_start, slice_stop, spec): """ Iterator that repeats the single values the required number of\ times. - Allows a single Value parameter to be treated the same as parameters\ - with len. \ + Allows a single Value parameter to be treated the same as parameters + with len. Caches `cmd_word_list` and `cmd_string` so they are only created once. :param value: The simple value that is the data for each element @@ -146,10 +146,10 @@ class NeuronParameter(object): def __init__(self, value, data_type): """ - :param value: what the value of the parameter is; if a list or array,\ + :param value: what the value of the parameter is; if a list or array, potentially provides a different value for each neuron - :type value: int or float or bool or list(int) or list(float) or \ - list(bool) or ~numpy.ndarray or \ + :type value: int or float or bool or list(int) or list(float) or + list(bool) or ~numpy.ndarray or ~spinn_utilities.ranged.AbstractList :param ~data_specification.enums.DataType data_type: The serialization type of the parameter in the neuron model. @@ -164,8 +164,8 @@ def get_value(self): """ What the value of the parameter is; if a list or array,\ potentially provides a different value for each neuron. - :rtype: int or float or bool or list(int) or list(float) or \ - list(bool) or ~numpy.ndarray or \ + :rtype: int or float or bool or list(int) or list(float) or + list(bool) or ~numpy.ndarray or ~spinn_utilities.ranged.AbstractList """ return self.__value @@ -186,7 +186,7 @@ def iterator_by_slice(self, slice_start, slice_stop, spec): :param ~data_specification.DataSpecificationGenerator spec: The data specification to eventually write to. (Note that this does not actually do the write). - :return: Iterator that produces a command to write to the\ + :return: Iterator that produces a command to write to the specification for each element in the slice. :rtype: six.Iterator(tuple(bytearray, str)) """ diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index 00be8c390e..78e4fc2a61 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -12,10 +12,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging import os -import math from spinn_utilities.overrides import overrides from pacman.model.constraints.key_allocator_constraints import ( ContiguousKeyRangeContraint) @@ -56,12 +53,11 @@ from spynnaker.pyNN.exceptions import InvalidParameterType from spynnaker.pyNN.utilities.ranged import ( SpynnakerRangeDictionary, SpynnakerRangedList) +from spynnaker.pyNN.utilities.utility_calls import ceildiv from .synapse_dynamics import AbstractSynapseDynamicsStructural from .synaptic_manager import SynapticManager from .population_machine_vertex import PopulationMachineVertex -logger = logging.getLogger(__name__) - # TODO: Make sure these values are correct (particularly CPU cycles) _NEURON_BASE_DTCM_USAGE_IN_BYTES = 9 * BYTES_PER_WORD _NEURON_BASE_SDRAM_USAGE_IN_BYTES = 3 * BYTES_PER_WORD @@ -88,7 +84,8 @@ class AbstractPopulationVertex( AbstractReadParametersBeforeSet, AbstractAcceptsIncomingSynapses, ProvidesKeyToAtomMappingImpl, AbstractCanReset): """ Underlying vertex model for Neural Populations. - Not actually abstract. + + Not actually abstract. """ __slots__ = [ @@ -142,8 +139,8 @@ def __init__( :param spikes_per_second: Expected spike rate :type spikes_per_second: float or None :param ring_buffer_sigma: - How many SD above the mean to go for upper bound of ring buffer \ - size; a good starting choice is 5.0. Given length of simulation \ + How many SD above the mean to go for upper bound of ring buffer + size; a good starting choice is 5.0. Given length of simulation we can set this for approximate number of saturation events. :type ring_buffer_sigma: float or None :param incoming_spike_buffer_size: @@ -421,8 +418,7 @@ def _write_neuron_parameters( max_offset = ( machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR spec.write_value( - int(math.ceil(max_offset / self.__n_subvertices)) * - self.__n_data_specs) + ceildiv(max_offset, self.__n_subvertices) * self.__n_data_specs) self.__n_data_specs += 1 # Write the number of microseconds between sending spikes @@ -824,7 +820,7 @@ def add_pre_run_connection_holder( def get_connection_holders(self): """ - :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),\ + :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation), ConnectionHolder) """ return self.__synapse_manager.get_connection_holders() @@ -912,11 +908,11 @@ def get_units(self, variable): def describe(self): """ Get a human-readable description of the cell or synapse type. - The output may be customised by specifying a different template\ - together with an associated template engine\ + The output may be customised by specifying a different template + together with an associated template engine (see :py:mod:`pyNN.descriptions`). - If template is None, then a dictionary containing the template context\ + If template is None, then a dictionary containing the template context will be returned. :rtype: dict(str, ...) diff --git a/spynnaker/pyNN/models/neuron/master_pop_table.py b/spynnaker/pyNN/models/neuron/master_pop_table.py index 078c04856c..77ead72cd4 100644 --- a/spynnaker/pyNN/models/neuron/master_pop_table.py +++ b/spynnaker/pyNN/models/neuron/master_pop_table.py @@ -12,19 +12,16 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging -import math import struct import numpy -from spinn_front_end_common.utilities.constants import BYTES_PER_WORD, \ - SARK_PER_MALLOC_SDRAM_USAGE +from spinn_front_end_common.utilities.constants import ( + BYTES_PER_WORD, SARK_PER_MALLOC_SDRAM_USAGE) from spynnaker.pyNN.models.neural_projections import ( ProjectionApplicationEdge, ProjectionMachineEdge) from spynnaker.pyNN.exceptions import ( SynapseRowTooBigException, SynapticConfigurationException) +from spynnaker.pyNN.utilities.utility_calls import ceildiv -logger = logging.getLogger(__name__) _TWO_WORDS = struct.Struct(". import math -import logging import numpy -logger = logging.getLogger(__name__) # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py index a11db4e352..02946be2d5 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py @@ -89,7 +89,7 @@ def get_provenance_data(self, pre_population_label, post_population_label): :param str pre_population_label: label of pre. :param str post_population_label: label of post. - :rtype: \ + :rtype: list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem) """ # pylint: disable=unused-argument diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py index b9262dd700..1651034c01 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py @@ -13,19 +13,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import logging from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.utilities.globals_variables import get_simulator from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( get_exp_lut_array) -from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( - AbstractTimingDependence) from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) - -logger = logging.getLogger(__name__) +from .abstract_timing_dependence import AbstractTimingDependence class TimingDependencePfisterSpikeTriplet(AbstractTimingDependence): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py index d318a0eb7f..35673a8729 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) @@ -24,8 +22,6 @@ SynapseStructureWeightOnly) from .abstract_timing_dependence import AbstractTimingDependence -logger = logging.getLogger(__name__) - class TimingDependenceSpikeNearestPair(AbstractTimingDependence): """ A timing dependence STDP rule based on nearest pairs. diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py index fc7cc64d9c..89e20f045e 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from spinn_front_end_common.utilities.constants import ( BYTES_PER_SHORT, BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) @@ -24,8 +22,6 @@ from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) -logger = logging.getLogger(__name__) - class TimingDependenceSpikePair(AbstractTimingDependence): """ A basic timing dependence STDP rule. diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py index 95217e1bce..de788709fd 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py @@ -12,21 +12,16 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import logging from spinn_utilities.overrides import overrides from data_specification.enums import DataType from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, BYTES_PER_SHORT, MICRO_TO_MILLISECOND_CONVERSION) from spinn_front_end_common.utilities.globals_variables import get_simulator -from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( - AbstractTimingDependence) from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import ( SynapseStructureWeightOnly) from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( float_to_fixed, get_exp_lut_array) - -logger = logging.getLogger(__name__) +from .abstract_timing_dependence import AbstractTimingDependence class TimingDependenceVogels2011(AbstractTimingDependence): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py index 109ae9ce86..ec47c17ccc 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py @@ -28,7 +28,7 @@ def get_provenance_data(self, pre_population_label, post_population_label): :param str pre_population_label: label of pre. :param str post_population_label: label of post. :return: the provenance data of the weight dependency - :rtype: \ + :rtype: list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem) """ # pylint: disable=unused-argument diff --git a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py index d8460cff3e..e30b6fe8e4 100644 --- a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py +++ b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py @@ -48,13 +48,13 @@ def __init__( :param float p_form_forward: The peak probability of formation on feed-forward connections :param float sigma_form_forward: - The spread of probability with distance of formation on\ + The spread of probability with distance of formation on feed-forward connections :param float p_form_lateral: The peak probability of formation on lateral connections :param float sigma_form_lateral: - The spread of probability with distance of formation on\ - lateral connections + The spread of probability with distance of formation on lateral + connections """ self.__grid = numpy.asarray(grid, dtype=int) self.__p_form_forward = p_form_forward diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py index 40be1c50f7..b87aaf58a1 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py @@ -42,13 +42,13 @@ def get_plastic_synaptic_data( and lengths for the fixed_plastic and plastic-plastic parts of\ each row. - Data is returned as an array made up of an array of 32-bit words for\ - each row, for each of the fixed-plastic and plastic-plastic data\ - regions. The row into which connection should go is given by\ - `connection_row_indices`, and the total number of rows is given by\ + Data is returned as an array made up of an array of 32-bit words for + each row, for each of the fixed-plastic and plastic-plastic data + regions. The row into which connection should go is given by + `connection_row_indices`, and the total number of rows is given by `n_rows`. - Lengths are returned as an array made up of an integer for each row,\ + Lengths are returned as an array made up of an integer for each row, for each of the fixed-plastic and plastic-plastic regions. :param ~numpy.ndarray connections: diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py index 3edd43b921..b6e8233df1 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py @@ -41,12 +41,12 @@ def get_static_synaptic_data( """ Get the fixed-fixed data for each row, and lengths for the\ fixed-fixed parts of each row. - Data is returned as an array made up of an array of 32-bit words for\ - each row for the fixed-fixed region. The row into which connection\ - should go is given by `connection_row_indices`, and the total number\ + Data is returned as an array made up of an array of 32-bit words for + each row for the fixed-fixed region. The row into which connection + should go is given by `connection_row_indices`, and the total number of rows is given by `n_rows`. - Lengths are returned as an array made up of an integer for each row,\ + Lengths are returned as an array made up of an integer for each row, for the fixed-fixed region. :param ~numpy.ndarray connections: diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py index ca31ddaf4b..4bd162baa2 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py @@ -13,11 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math import numpy from six import add_metaclass from spinn_utilities.abstract_base import ( AbstractBase, abstractmethod, abstractproperty) +from spynnaker.pyNN.utilities.utility_calls import ceildiv @add_metaclass(AbstractBase) @@ -196,7 +196,7 @@ def get_n_items(self, rows, item_size): :rtype: ~numpy.ndarray """ return numpy.array([ - int(math.ceil(float(row.size) / float(item_size))) + ceildiv(row.size, item_size) for row in rows], dtype="uint32").reshape((-1, 1)) def get_words(self, rows): diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py index 6975734fc3..7028b34c44 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py @@ -179,7 +179,8 @@ def requires_mapping(self): @overrides(AbstractChangableAfterRun.mark_no_changes, extend_doc=False) def mark_no_changes(self): """ Marks the point after which changes are reported. Immediately\ - after calling this method, requires_mapping should return False. + after calling this method, :py:meth:`requires_mapping` should \ + return False. """ self.__change_requires_mapping = False diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index 13a62b130a..f55497817e 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -12,8 +12,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import math import numpy from spinn_utilities.overrides import overrides from spinn_front_end_common.abstract_models import AbstractChangableAfterRun @@ -27,7 +25,7 @@ AbstractGenerateOnMachine, MatrixGeneratorID) from spynnaker.pyNN.exceptions import ( InvalidParameterType, SynapticConfigurationException) -from spynnaker.pyNN.utilities.utility_calls import get_n_bits +from spynnaker.pyNN.utilities.utility_calls import get_n_bits, ceildiv # How large are the time-stamps stored with each event TIME_STAMP_BYTES = BYTES_PER_WORD @@ -281,7 +279,7 @@ def _n_header_bytes(self): # The actual number of bytes is in a word-aligned struct, so work out # the number of bytes as a number of words - return int(math.ceil(float(n_bytes) / BYTES_PER_WORD)) * BYTES_PER_WORD + return ceildiv(n_bytes, BYTES_PER_WORD) * BYTES_PER_WORD def __get_n_connections(self, n_connections, check_length_padded=True): """ @@ -303,7 +301,7 @@ def __get_n_connections(self, n_connections, check_length_padded=True): self._n_header_bytes + (synapse_structure.get_n_half_words_per_connection() * BYTES_PER_SHORT * n_connections)) - pp_size_words = int(math.ceil(float(pp_size_bytes) / BYTES_PER_WORD)) + pp_size_words = ceildiv(pp_size_bytes, BYTES_PER_WORD) return fp_size_words + pp_size_words @@ -476,7 +474,7 @@ def get_provenance_data(self, pre_population_label, post_population_label): """ :param str pre_population_label: :param str post_population_label: - :rtype: \ + :rtype: list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem) """ prov_data = list() diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py index 336047fac2..932aeb57f8 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py @@ -12,9 +12,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - import collections -import math import numpy from data_specification.enums.data_type import DataType from spinn_front_end_common.utilities.constants import ( @@ -24,6 +22,7 @@ from .abstract_synapse_dynamics_structural import ( AbstractSynapseDynamicsStructural) from spynnaker.pyNN.exceptions import SynapticConfigurationException +from spynnaker.pyNN.utilities.utility_calls import ceildiv class StructuralPlasticityCommon(object): @@ -307,8 +306,9 @@ def __write_prepopulation_info( """ :param ~data_specification.DataSpecificationGenerator spec: :param AbstractPopulationVertex app_vertex: - :param list(tuple(ProjectionApplicationEdge,SynapseInformation)) \ - structural_edges: + :param structural_edges: + :type structural_edges: + list(tuple(ProjectionApplicationEdge,SynapseInformation)) :param RoutingInfo routing_info: :param dict(AbstractSynapseType,float) weight_scales: :param ~pacman.model.graphs.common.Slice post_slice: @@ -368,8 +368,9 @@ def __write_post_to_pre_table( matrix. :param ~data_specification.DataSpecificationGenerator spec: - :param dict(tuple(AbstractPopulationVertex,SynapseInformation),int) \ - pop_index: + :param pop_index: + :type pop_index: + dict(tuple(AbstractPopulationVertex,SynapseInformation),int) :param AbstractPopulationVertex app_vertex: :param ~pacman.model.graphs.common.Slice post_slice: """ @@ -441,8 +442,7 @@ def get_parameters_sdram_usage_in_bytes( max_atoms = in_edge.pre_vertex.get_max_atoms_per_core() if in_edge.pre_vertex.n_atoms < max_atoms: max_atoms = in_edge.pre_vertex.n_atoms - n_sub_edges += int(math.ceil( - float(in_edge.pre_vertex.n_atoms) / float(max_atoms))) + n_sub_edges += ceildiv(in_edge.pre_vertex.n_atoms, max_atoms) dynamics = synapse_info.synapse_dynamics param_sizes += dynamics.formation\ .get_parameters_sdram_usage_in_bytes() diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py index fe78cc16c6..80fbaae48c 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py @@ -27,8 +27,8 @@ class SynapseDynamicsStructuralStatic( SynapseDynamicsStatic, AbstractSynapseDynamicsStructural): """ Class that enables synaptic rewiring in the absence of STDP. - It acts as a wrapper around SynapseDynamicsStatic, meaning that \ - rewiring can operate in parallel with static synapses. + It acts as a wrapper around :py:class:`SynapseDynamicsStatic`, meaning + that rewiring can operate in parallel with static synapses. Written by Petrut Bogdan. """ diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py index 057ab64924..c764d2e46f 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py @@ -25,8 +25,8 @@ class SynapseDynamicsStructuralSTDP( SynapseDynamicsSTDP, AbstractSynapseDynamicsStructural): """ Class that enables synaptic rewiring in the presence of STDP. - It acts as a wrapper around SynapseDynamicsSTDP, meaning rewiring can\ - operate in parallel with STDP synapses. + It acts as a wrapper around :py:class:`SynapseDynamicsSTDP`, meaning + rewiring can operate in parallel with STDP synapses. Written by Petrut Bogdan. """ diff --git a/spynnaker/pyNN/models/neuron/synapse_io.py b/spynnaker/pyNN/models/neuron/synapse_io.py index 3cd626bcca..e59c0fb7dd 100644 --- a/spynnaker/pyNN/models/neuron/synapse_io.py +++ b/spynnaker/pyNN/models/neuron/synapse_io.py @@ -13,7 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math import numpy from six import raise_from from spinn_front_end_common.utilities.constants import ( @@ -25,6 +24,7 @@ from spynnaker.pyNN.models.neuron.synapse_dynamics import ( AbstractStaticSynapseDynamics, AbstractSynapseDynamicsStructural, AbstractSynapseDynamics) +from spynnaker.pyNN.utilities.utility_calls import ceildiv _N_HEADER_WORDS = 3 # There are 16 slots, one per time step @@ -132,7 +132,7 @@ def _n_words(n_bytes): :param int n_bytes: :rtype: int """ - return math.ceil(float(n_bytes) / BYTES_PER_WORD) + return ceildiv(n_bytes, BYTES_PER_WORD) @staticmethod def _get_max_row_length( @@ -323,7 +323,7 @@ def get_synapses( :return: (row_data, max_row_length, delayed_row_data, max_delayed_row_length, delayed_source_ids, stages) :rtype: - tuple(~numpy.ndarray, int, ~numpy.ndarray, int, ~numpy.ndarray,\ + tuple(~numpy.ndarray, int, ~numpy.ndarray, int, ~numpy.ndarray, ~numpy.ndarray) """ # pylint: disable=too-many-arguments, too-many-locals diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index f03a3774f0..18cfd17098 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -39,7 +39,7 @@ from spynnaker.pyNN.utilities.constants import ( POPULATION_BASED_REGIONS, POSSION_SIGMA_SUMMATION_LIMIT) from spynnaker.pyNN.utilities.utility_calls import ( - get_maximum_probable_value, get_n_bits) + get_maximum_probable_value, get_n_bits, ceildiv, round_up) from spynnaker.pyNN.utilities.running_stats import RunningStats from spynnaker.pyNN.models.neuron.master_pop_table import ( MasterPopTableAsBinarySearch) @@ -287,7 +287,7 @@ def add_pre_run_connection_holder( def get_connection_holders(self): """ - :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),\ + :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation), ConnectionHolder) """ return self.__pre_run_connection_holders @@ -397,8 +397,8 @@ def _get_size_of_generator_information(self, in_edges): max_atoms = in_edge.pre_vertex.get_max_atoms_per_core() if in_edge.pre_vertex.n_atoms < max_atoms: max_atoms = in_edge.pre_vertex.n_atoms - n_edge_vertices = int(math.ceil( - float(in_edge.pre_vertex.n_atoms) / float(max_atoms))) + n_edge_vertices = ceildiv( + in_edge.pre_vertex.n_atoms, max_atoms) # Get the size if synapse_info.may_generate_on_machine(): @@ -531,20 +531,20 @@ def _ring_buffer_expected_upper_bound( Requires an assessment of maximum Poisson input rate. - Assumes knowledge of mean and SD of weight distribution, fan-in\ + Assumes knowledge of mean and SD of weight distribution, fan-in and timestep. - All arguments should be assumed real values except n_synapses_in\ + All arguments should be assumed real values except n_synapses_in which will be an integer. - :param float weight_mean: Mean of weight distribution (in either nA or\ + :param float weight_mean: Mean of weight distribution (in either nA or microSiemens as required) :param float weight_std_dev: SD of weight distribution :param float spikes_per_second: Maximum expected Poisson rate in Hz :param int machine_timestep: in us :param int n_synapses_in: No of connected synapses - :param float sigma: How many SD above the mean to go for upper bound;\ - a good starting choice is 5.0. Given length of simulation we can\ + :param float sigma: How many SD above the mean to go for upper bound; + a good starting choice is 5.0. Given length of simulation we can set this for approximate number of saturation events. :rtype: float """ @@ -692,7 +692,7 @@ def _get_ring_buffer_to_input_left_shifts( # Convert these to powers; we could use int.bit_length() for this if # they were integers, but they aren't... max_weight_powers = ( - 0 if w <= 0 else int(math.ceil(max(0, math.log(w, 2)))) + 0 if w <= 0 else round_up(max(0, math.log(w, 2))) for w in max_weights) # If 2^max_weight_power equals the max weight, we have to add another @@ -718,7 +718,7 @@ def __get_weight_scale(ring_buffer_to_input_left_shift): :param int ring_buffer_to_input_left_shift: :rtype: float """ - return float(math.pow(2, 16 - (ring_buffer_to_input_left_shift + 1))) + return 2.0 ** (16 - (ring_buffer_to_input_left_shift + 1)) def _write_synapse_parameters( self, spec, ring_buffer_shifts, weight_scale): @@ -1097,7 +1097,7 @@ def __is_direct( self, single_addr, connector, pre_vertex_slice, post_vertex_slice, app_edge, synapse_info): """ Determine if the given connection can be done with a "direct"\ - synaptic matrix - this must have an exactly 1 entry per row + synaptic matrix. This must have an exactly 1 entry per row. :param int single_addr: :param AbstractConnector connector: diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index 5adf234845..81df354f2b 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -72,7 +72,8 @@ def __init__( :param spinnaker_control: The simulator engine core. :type spinnaker_control: ~spinn_front_end_common.interface.abstract_spinnaker_base.AbstractSpinnakerBase - :param size: The size of the population; external devices may use None + :param size: The size of the population; external devices may use + `None` :type size: int or float or None :param label: The label for the population, or None for a default :type label: str or None @@ -87,7 +88,7 @@ def __init__( :param initial_values: Initialisation for model variables. :type initial_values: dict(str, Any) or None :param additional_parameters: - Any extra parameters to pass to the model's vertex creation \ + Any extra parameters to pass to the model's vertex creation function. :type additional_parameters: dict(str, Any) or None """ @@ -247,13 +248,13 @@ def get(self, parameter_names, gather=True, simplify=True): """ Get the values of a parameter for every local cell in the\ population. - :param parameter_names: Name of parameter. This is either a single\ + :param parameter_names: Name of parameter. This is either a single string or a list of strings :type parameter_names: str or iterable(str) :param bool gather: pointless on sPyNNaker :param bool simplify: ignored - :return: A single list of values (or possibly a single value) if\ - paramter_names is a string, or a dict of these if parameter names\ + :return: A single list of values (or possibly a single value) if + paramter_names is a string, or a dict of these if parameter names is a list. :rtype: str or list(str) or dict(str,str) or dict(str,list(str)) """ @@ -278,15 +279,15 @@ def get_by_selector(self, selector, parameter_names): """ Get the values of a parameter for the selected cell in the\ population. - :param selector: a description of the subrange to accept. \ - Or None for all. See: \ + :param selector: a description of the subrange to accept. + Or `None` for all. See :py:meth:`~spinn_utilities.ranged.AbstractSized.selector_to_ids` :type selector: slice or int or iterable(bool) or iterable(int) - :param parameter_names: Name of parameter. This is either a\ + :param parameter_names: Name of parameter. This is either a single string or a list of strings :type parameter_names: str or iterable(str) - :return: A single list of values (or possibly a single value) if\ - paramter_names is a string or a dict of these if parameter names\ + :return: A single list of values (or possibly a single value) if + paramter_names is a string or a dict of these if parameter names is a list. :rtype: str or list(str) or dict(str,str) or dict(str,list(str)) """ @@ -433,9 +434,9 @@ def _set_check(self, parameter, value): def set(self, parameter, value=None): """ Set one or more parameters for every cell in the population. - param can be a dict, in which case value should not be supplied, or a\ - string giving the parameter name, in which case value is the parameter\ - value. value can be a numeric value, or list of such\ + param can be a dict, in which case value should not be supplied, or a + string giving the parameter name, in which case value is the parameter + value. value can be a numeric value, or list of such (e.g. for setting spike times):: p.set("tau_m", 20.0). @@ -460,8 +461,8 @@ def set(self, parameter, value=None): def set_by_selector(self, selector, parameter, value=None): """ Set one or more parameters for selected cell in the population. - param can be a dict, in which case value should not be supplied, or a\ - string giving the parameter name, in which case value is the parameter\ + param can be a dict, in which case value should not be supplied, or a + string giving the parameter name, in which case value is the parameter value. value can be a numeric value, or list of such (e.g. for setting spike times):: diff --git a/spynnaker/pyNN/models/pynn_projection_common.py b/spynnaker/pyNN/models/pynn_projection_common.py index a2a44947e9..0c770a2526 100644 --- a/spynnaker/pyNN/models/pynn_projection_common.py +++ b/spynnaker/pyNN/models/pynn_projection_common.py @@ -14,7 +14,6 @@ # along with this program. If not, see . import logging -import math import numpy from pyNN.random import RandomDistribution from spinn_utilities.progress_bar import ProgressBar @@ -34,6 +33,7 @@ from spynnaker.pyNN.utilities.constants import ( MAX_DELAY_BLOCKS, MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.neuron import ConnectionHolder +from spynnaker.pyNN.utilities.utility_calls import ceildiv # pylint: disable=protected-access @@ -302,9 +302,9 @@ def _add_delay_extension( # Ensure that the delay extension knows how many states it will # support - n_stages = int(math.ceil( - float(max_delay_for_projection - max_delay_per_neuron) / - float(max_delay_per_neuron))) + n_stages = ceildiv( + max_delay_for_projection - max_delay_per_neuron, + max_delay_per_neuron) if n_stages > delay_vertex.n_delay_stages: delay_vertex.n_delay_stages = n_stages diff --git a/spynnaker/pyNN/models/recording_common.py b/spynnaker/pyNN/models/recording_common.py index 5ff82ef527..d17180bd91 100644 --- a/spynnaker/pyNN/models/recording_common.py +++ b/spynnaker/pyNN/models/recording_common.py @@ -60,7 +60,7 @@ def _record(self, variable, sampling_interval=None, to_file=None, indexes=None): """ Tell the vertex to record data. - :param str variable: the variable to record, valued variables to\ + :param str variable: the variable to record, valued variables to record are: 'gsyn_exc', 'gsyn_inh', 'v', 'spikes' :param int sampling_interval: the interval to record them :param indexes: List of indexes to record or None for all diff --git a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py index 08e473a609..cb03491317 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py @@ -141,11 +141,11 @@ def clear_spike_recording(self, buffer_manager, placements): def describe(self): """ Returns a human-readable description of the cell or synapse type. - The output may be customised by specifying a different template\ - together with an associated template engine\ + The output may be customised by specifying a different template + together with an associated template engine (see :py:mod:`pyNN.descriptions`). - If template is None, then a dictionary containing the template\ + If template is `None`, then a dictionary containing the template context will be returned. """ diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index d414348b56..a2436864ea 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -14,7 +14,6 @@ # along with this program. If not, see . import logging -import math import numpy import scipy.stats import struct @@ -52,7 +51,8 @@ AbstractReadParametersBeforeSet) from .spike_source_poisson_machine_vertex import ( SpikeSourcePoissonMachineVertex) -from spynnaker.pyNN.utilities.utility_calls import validate_mars_kiss_64_seed +from spynnaker.pyNN.utilities.utility_calls import ( + validate_mars_kiss_64_seed, ceildiv, round_up) from spynnaker.pyNN.utilities.struct import Struct from spynnaker.pyNN.utilities.ranged import ( SpynnakerRangeDictionary, SpynnakerRangedList) @@ -457,7 +457,7 @@ def _max_spikes_per_ts(self, machine_time_step): max_spikes_per_ts = scipy.stats.poisson.ppf( 1.0 - (1.0 / float(chance_ts)), float(self.__max_rate) / ts_per_second) - return int(math.ceil(max_spikes_per_ts)) + 1.0 + return round_up(max_spikes_per_ts) + 1.0 def get_recording_sdram_usage(self, vertex_slice, machine_time_step): """ @@ -640,8 +640,7 @@ def _write_poisson_parameters( max_offset = ( machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR spec.write_value( - int(math.ceil(max_offset / self.__n_subvertices)) * - self.__n_data_specs) + ceildiv(max_offset, self.__n_subvertices) * self.__n_data_specs) self.__n_data_specs += 1 if self.__max_spikes > 0: @@ -1059,12 +1058,12 @@ def clear_spike_recording(self, buffer_manager, placements): def describe(self): """ Return a human-readable description of the cell or synapse type. - The output may be customised by specifying a different template\ - together with an associated template engine\ + The output may be customised by specifying a different template + together with an associated template engine (see :py:mod:`pyNN.descriptions`). - If template is None, then a dictionary containing the template context\ - will be returned. + If template is `None`, then a dictionary containing the template + context will be returned. :rtype: dict(str, ...) """ diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_block.py b/spynnaker/pyNN/models/utility_models/delays/delay_block.py index feea65f675..d0de1f0842 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_block.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_block.py @@ -12,9 +12,9 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import math import numpy +from spynnaker.pyNN.utilities.utility_calls import ceildiv +from spynnaker.pyNN.utilities.constants import BITS_PER_WORD class DelayBlock(object): @@ -33,7 +33,7 @@ def __init__(self, n_delay_stages, delay_per_stage, vertex_slice): """ self.__delay_per_stage = delay_per_stage self.__n_delay_stages = n_delay_stages - n_words_per_row = int(math.ceil(vertex_slice.n_atoms / 32.0)) + n_words_per_row = ceildiv(vertex_slice.n_atoms, BITS_PER_WORD) self.__delay_block = numpy.zeros( (n_delay_stages, n_words_per_row), dtype="uint32") diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py index 21cd5f1a6c..2e6e42bf90 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py @@ -12,10 +12,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - from collections import defaultdict -import logging -import math from spinn_utilities.overrides import overrides from pacman.executor.injection_decorator import inject_items from pacman.model.constraints.key_allocator_constraints import ( @@ -30,20 +27,19 @@ AbstractProvidesOutgoingPartitionConstraints, AbstractHasAssociatedBinary) from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.utilities.constants import ( - SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BITS_PER_WORD, - BYTES_PER_WORD) + SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BYTES_PER_WORD) from spinn_front_end_common.utilities.utility_objs import ExecutableType from .delay_block import DelayBlock from .delay_extension_machine_vertex import DelayExtensionMachineVertex from .delay_generator_data import DelayGeneratorData -from spynnaker.pyNN.utilities.constants import SPIKE_PARTITION_ID +from spynnaker.pyNN.utilities.constants import ( + SPIKE_PARTITION_ID, BITS_PER_WORD) from spynnaker.pyNN.models.neural_projections import DelayedApplicationEdge from spynnaker.pyNN.models.neural_projections.connectors import ( AbstractGenerateConnectorOnMachine) from spynnaker.pyNN.models.neuron.synapse_dynamics import ( AbstractGenerateOnMachine) - -logger = logging.getLogger(__name__) +from spynnaker.pyNN.utilities.utility_calls import ceildiv _DELAY_PARAM_HEADER_WORDS = 8 # pylint: disable=protected-access @@ -87,9 +83,10 @@ def __init__(self, n_neurons, delay_per_stage, source_vertex, where messages are coming from :param int machine_time_step: how long is the machine time step :param int time_scale_factor: what slowdown factor has been applied - :param iterable(~pacman.model.constraints.AbstractConstraint) \ - constraints: + :param constraints: the vertex constraints + :type constraints: + iterable(~pacman.model.constraints.AbstractConstraint) :param str label: the vertex label """ # pylint: disable=too-many-arguments @@ -225,8 +222,7 @@ def generate_data_specification( # ################################################################### # Reserve SDRAM space for memory areas: vertex_slice = vertex.vertex_slice - n_words_per_stage = int( - math.ceil(vertex_slice.n_atoms / BITS_PER_WORD)) + n_words_per_stage = ceildiv(vertex_slice.n_atoms, BITS_PER_WORD) delay_params_sz = BYTES_PER_WORD * ( _DELAY_PARAM_HEADER_WORDS + (self.__n_delay_stages * n_words_per_stage)) @@ -340,8 +336,7 @@ def write_delay_parameters( max_offset = ( machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR spec.write_value( - int(math.ceil(max_offset / total_n_vertices)) * - self.__n_data_specs) + ceildiv(max_offset, total_n_vertices) * self.__n_data_specs) self.__n_data_specs += 1 # Write the time between spikes @@ -418,8 +413,8 @@ def _get_size_of_generator_information(self, out_edges): max_atoms = out_edge.post_vertex.get_max_atoms_per_core() if out_edge.post_vertex.n_atoms < max_atoms: max_atoms = out_edge.post_vertex.n_atoms - n_edge_vertices = int(math.ceil(float( - out_edge.post_vertex.n_atoms) / float(max_atoms))) + n_edge_vertices = ceildiv( + out_edge.post_vertex.n_atoms, max_atoms) # Get the size gen_size = self._get_edge_generator_size(synapse_info) diff --git a/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py b/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py index 1825924a93..18aba38ba4 100644 --- a/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py +++ b/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py @@ -131,8 +131,8 @@ def describe(self): together with an associated template engine (see :py:mod:`pyNN.descriptions`). - If template is None, then a dictionary containing the template context - will be returned. + If template is `None`, then a dictionary containing the template + context will be returned. """ parameters = dict() diff --git a/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py b/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py index 638ef8dff9..77242bcea5 100644 --- a/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py +++ b/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py @@ -12,14 +12,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - from enum import Enum -import logging from spinn_front_end_common.utility_models import MultiCastCommand from spinn_front_end_common.utilities.exceptions import ConfigurationException -logger = logging.getLogger(__name__) - # structure of command is KKKKKKKKKKKKKKKKKKKKK-IIIIIII-F-DDD # K = ignored key at the top of the command # I = instruction diff --git a/spynnaker/pyNN/utilities/bit_field_utilities.py b/spynnaker/pyNN/utilities/bit_field_utilities.py index ee69a5deb1..0b5d27e5d6 100644 --- a/spynnaker/pyNN/utilities/bit_field_utilities.py +++ b/spynnaker/pyNN/utilities/bit_field_utilities.py @@ -13,8 +13,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math from pacman.utilities.constants import FULL_MASK +from spynnaker.pyNN.utilities.utility_calls import ceildiv from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \ import ( determine_max_atoms_for_vertex) @@ -46,9 +46,10 @@ def get_estimated_sdram_for_bit_field_region(app_graph, vertex): """ Estimates the SDRAM for the bit field region - :param app_graph: the app graph - :param vertex: machine vertex + :param ~.ApplicationGraph app_graph: the app graph + :param ~.ApplicationVertex vertex: app vertex :return: the estimated number of bytes used by the bit field region + :rtype: int """ sdram = 0 for incoming_edge in app_graph.get_edges_ending_at_vertex(vertex): @@ -59,17 +60,15 @@ def get_estimated_sdram_for_bit_field_region(app_graph, vertex): max_atoms = incoming_edge.pre_vertex.n_atoms # Get the number of likely vertices - n_machine_vertices = int(math.ceil( - float(incoming_edge.pre_vertex.n_atoms) / - float(max_atoms))) - n_atoms_per_machine_vertex = int(math.ceil( - float(incoming_edge.pre_vertex.n_atoms) / - n_machine_vertices)) + n_machine_vertices = ceildiv( + incoming_edge.pre_vertex.n_atoms, max_atoms) + n_atoms_per_machine_vertex = ceildiv( + incoming_edge.pre_vertex.n_atoms, n_machine_vertices) if isinstance(edge_pre_vertex, DelayExtensionVertex): n_atoms_per_machine_vertex *= \ edge_pre_vertex.n_delay_stages - n_words_for_atoms = int(math.ceil( - n_atoms_per_machine_vertex / BIT_IN_A_WORD)) + n_words_for_atoms = ceildiv( + n_atoms_per_machine_vertex, int(BIT_IN_A_WORD)) sdram += ( (ELEMENTS_USED_IN_EACH_BIT_FIELD + ( n_words_for_atoms * n_machine_vertices)) * @@ -80,9 +79,10 @@ def get_estimated_sdram_for_bit_field_region(app_graph, vertex): def get_estimated_sdram_for_key_region(app_graph, vertex): """ gets an estimate of the bitfield builder region - :param app_graph: the app graph - :param vertex: machine vertex + :param ~.ApplicationGraph app_graph: the app graph + :param ~.ApplicationVertex vertex: app vertex :return: sdram needed + :rtype: int """ # basic sdram @@ -94,8 +94,7 @@ def get_estimated_sdram_for_key_region(app_graph, vertex): max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex) if in_edge.pre_vertex.n_atoms < max_atoms: max_atoms = in_edge.pre_vertex.n_atoms - n_edge_vertices = int(math.ceil( - float(in_edge.pre_vertex.n_atoms) / float(max_atoms))) + n_edge_vertices = ceildiv(in_edge.pre_vertex.n_atoms, max_atoms) sdram += (n_edge_vertices * N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP * BYTES_PER_WORD) return sdram @@ -105,16 +104,17 @@ def _exact_sdram_for_bit_field_region(machine_graph, vertex, n_key_map): """ Gets the correct SDRAM for the bitfield region based off \ the machine graph - :param machine_graph: machine graph - :param vertex: the machine vertex - :param n_key_map: n keys map + :param ~.MachineGraph machine_graph: machine graph + :param ~.MachineVertex vertex: the machine vertex + :param ~.AbstractMachinePartitionNKeysMap n_key_map: n keys map :return: sdram in bytes + :rtype: int """ sdram = ELEMENTS_USED_IN_BIT_FIELD_HEADER * BYTES_PER_WORD for incoming_edge in machine_graph.get_edges_ending_at_vertex(vertex): n_keys = n_key_map.n_keys_for_partition( machine_graph.get_outgoing_partition_for_edge(incoming_edge)) - n_words_for_atoms = int(math.ceil(n_keys / BIT_IN_A_WORD)) + n_words_for_atoms = ceildiv(n_keys, int(BIT_IN_A_WORD)) sdram += ( (ELEMENTS_USED_IN_EACH_BIT_FIELD + n_words_for_atoms) * @@ -133,14 +133,15 @@ def exact_sdram_for_bit_field_builder_region(): def _exact_sdram_for_bit_field_key_region(machine_graph, vertex): """ Calculates the exact SDRAM for the bitfield key region - :param machine_graph: machine graph - :param vertex: machine vertex + :param ~.MachineGraph machine_graph: machine graph + :param ~.MachineVertex vertex: machine vertex :return: bytes + :rtype: int """ return ( - N_KEYS_DATA_SET_IN_WORDS + - len(machine_graph.get_edges_ending_at_vertex(vertex)) * - N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP) * BYTES_PER_WORD + N_KEYS_DATA_SET_IN_WORDS + + len(machine_graph.get_edges_ending_at_vertex(vertex)) * + N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP) * BYTES_PER_WORD def reserve_bit_field_regions( @@ -148,14 +149,14 @@ def reserve_bit_field_regions( bit_filter_region, bit_field_key_region): """ reserves the regions for the bitfields - :param spec: dsg file - :param machine_graph: machine graph - :param n_key_map: map between partitions and n keys - :param vertex: machine vertex - :param bit_field_builder_region: region id for the builder region - :param bit_filter_region: region id for the bitfield region - :param bit_field_key_region: region id for the key map - :rtype: None + :param ~.DataSpecificationGenerator spec: dsg file + :param ~.MachineGraph machine_graph: machine graph + :param ~.AbstractMachinePartitionNKeysMap n_key_map: + map between partitions and n keys + :param ~.MachineVertex vertex: machine vertex + :param int bit_field_builder_region: region id for the builder region + :param int bit_filter_region: region id for the bitfield region + :param int bit_field_key_region: region id for the key map """ # reserve the final destination for the bitfields @@ -186,21 +187,20 @@ def write_bitfield_init_data( structural_dynamics_region_id, has_structural_dynamics_region): """ writes the init data needed for the bitfield generator - :param spec: data spec writer - :param machine_vertex: machine vertex - :param machine_graph: machine graph - :param routing_info: keys - :param n_key_map: map for edge to n keys - :param bit_field_builder_region: the region id for the bitfield builder - :param master_pop_region_id: the region id for the master pop table - :param synaptic_matrix_region_id: the region id for the synaptic matrix - :param direct_matrix_region_id: the region id for the direct matrix - :param bit_field_region_id: the region id for the bit-fields - :param bit_field_key_map_region_id: the region id for the key map - :param structural_dynamics_region_id: the region id for the structural - :param has_structural_dynamics_region: \ - bool saying if the core has a has_structural_dynamics_region or not - :rtype: None + :param ~.DataSpecificationGenerator spec: data spec writer + :param ~.MachineVertex machine_vertex: machine vertex + :param ~.MachineGraph machine_graph: machine graph + :param ~.RoutingInfo routing_info: keys + :param ~.AbstractMachinePartitionNKeysMap n_key_map: map for edge to n keys + :param int bit_field_builder_region: the region id for the bitfield builder + :param int master_pop_region_id: the region id for the master pop table + :param int synaptic_matrix_region_id: the region id for the synaptic matrix + :param int direct_matrix_region_id: the region id for the direct matrix + :param int bit_field_region_id: the region id for the bit-fields + :param int bit_field_key_map_region_id: the region id for the key map + :param int structural_dynamics_region_id: the region id for the structural + :param bool has_structural_dynamics_region: + whether the core has a structural dynamics region """ spec.switch_write_focus(bit_field_builder_region) diff --git a/spynnaker/pyNN/utilities/constants.py b/spynnaker/pyNN/utilities/constants.py index bf63e59569..d164f78d61 100644 --- a/spynnaker/pyNN/utilities/constants.py +++ b/spynnaker/pyNN/utilities/constants.py @@ -17,6 +17,9 @@ from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, BYTES_PER_KB) +#: The number of bits in a SpiNNaker machine word +BITS_PER_WORD = 32 + POSSION_SIGMA_SUMMATION_LIMIT = 3.0 BLOCK_INDEX_HEADER_WORDS = 3 diff --git a/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py b/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py index 154e4b804e..a93382bd32 100644 --- a/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py +++ b/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py @@ -50,12 +50,12 @@ def var(self, dist): @abstractmethod def high(self, dist): - """ Return the high cutoff value of the distribution, or None if the\ + """ Return the high cutoff value of the distribution, or `None` if the\ distribution is unbounded """ @abstractmethod def low(self, dist): - """ Return the low cutoff value of the distribution, or None if the\ + """ Return the low cutoff value of the distribution, or `None` if the\ distribution is unbounded """ diff --git a/spynnaker/pyNN/utilities/utility_calls.py b/spynnaker/pyNN/utilities/utility_calls.py index 4cc881fffa..4cf09fd99c 100644 --- a/spynnaker/pyNN/utilities/utility_calls.py +++ b/spynnaker/pyNN/utilities/utility_calls.py @@ -16,9 +16,8 @@ """ utility class containing simple helper methods """ -import os -import logging import math +import os import numpy from pyNN.random import RandomDistribution from scipy.stats import binom @@ -30,7 +29,6 @@ RandomStatsPoissonImpl, RandomStatsRandIntImpl, RandomStatsUniformImpl, RandomStatsVonmisesImpl, RandomStatsBinomialImpl) - MAX_RATE = 2 ** 32 - 1 # To allow a unit32_t to be used to store the rate STATS_BY_NAME = { @@ -46,8 +44,6 @@ 'randint': RandomStatsRandIntImpl(), 'vonmises': RandomStatsVonmisesImpl()} -logger = logging.getLogger(__name__) - def check_directory_exists_and_create_if_not(filename): """ Create a parent directory for a file if it doesn't exist @@ -287,6 +283,15 @@ def validate_mars_kiss_64_seed(seed): return seed +def round_up(value): + """ Rounds a value up to the nearest integer. + + :param float value: + :rtype: int + """ + return int(math.ceil(value)) + + def get_n_bits(n_values): """ Determine how many bits are required for the given number of values @@ -298,4 +303,13 @@ def get_n_bits(n_values): return 0 if n_values == 1: return 1 - return int(math.ceil(math.log(n_values, 2))) + return round_up(math.log(n_values, 2)) + + +def ceildiv(x, y): + """ Divide `x` by `y` and round *up*. + + :rtype: int + """ + d, m = divmod(x, y) + return int(d) + (m != 0) From 8572455b88d170b6e2a2fe69a35d2e8bb3c1b475 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Fri, 7 Aug 2020 09:33:21 +0100 Subject: [PATCH 08/11] Split fudge, remove unused code from the premises --- .../pyNN/models/neuron/synaptic_manager.py | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index 18cfd17098..636ed2efd7 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -102,7 +102,8 @@ class SynapticManager(object): "_direct_matrix_region"] # TODO make this right - FUDGE = 0 + _CPU_FUDGE = 0 + _DTCM_FUDGE = 0 def __init__(self, n_synapse_types, ring_buffer_sigma, spikes_per_second, config, population_table_type=None, synapse_io=None): @@ -209,22 +210,6 @@ def synapse_dynamics(self): """ return self.__synapse_dynamics - @staticmethod - def __combine_structural_stdp_dynamics(structural, stdp): - """ - :param AbstractSynapseDynamicsStructural structural: - :param SynapseDynamicsSTDP stdp: - :rtype: SynapseDynamicsStructuralSTDP - """ - return SynapseDynamicsStructuralSTDP( - structural.partner_selection, structural.formation, - structural.elimination, - stdp.timing_dependence, stdp.weight_dependence, - # voltage dependence is not supported - None, stdp.dendritic_delay_fraction, - structural.f_rew, structural.initial_weight, - structural.initial_delay, structural.s_max, structural.seed) - @synapse_dynamics.setter def synapse_dynamics(self, synapse_dynamics): if self.__synapse_dynamics is None: @@ -297,14 +282,14 @@ def get_n_cpu_cycles(self): :rtype: int """ # TODO: Calculate this correctly - return self.FUDGE + return self._CPU_FUDGE def get_dtcm_usage_in_bytes(self): """ :rtype: int """ # TODO: Calculate this correctly - return self.FUDGE + return self._DTCM_FUDGE def _get_synapse_params_size(self): """ From 671ecc5eac21b13b2ffaac7acecf58328691629d Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 10 Aug 2020 12:05:07 +0100 Subject: [PATCH 09/11] More tinkering with bits --- spynnaker/pyNN/abstract_spinnaker_common.py | 3 - .../abstract_ethernet_translator.py | 1 - ...ker_machine_bit_field_router_compressor.py | 1 - .../abstract_accepts_incoming_synapses.py | 8 +- .../abstract_read_parameters_before_set.py | 1 - .../abstract_models/abstract_settable.py | 4 +- .../common/abstract_neuron_recordable.py | 1 - .../common/abstract_spike_recordable.py | 1 - .../pyNN/models/common/neuron_recorder.py | 26 +++++- .../neural_projections/synapse_information.py | 12 ++- .../neuron/abstract_population_vertex.py | 87 ++++++++++++------- .../additional_input_ca2_adaptive.py | 5 -- .../abstract_standard_neuron_component.py | 11 ++- .../pyNN/models/neuron/master_pop_table.py | 2 - .../abstract_synapse_dynamics_structural.py | 13 +++ .../synapse_dynamics_structural_common.py | 48 ++++------ .../synapse_dynamics_structural_stdp.py | 2 +- spynnaker/pyNN/models/neuron/synapse_io.py | 5 ++ .../pyNN/models/neuron/synaptic_manager.py | 5 +- spynnaker/pyNN/models/recording_common.py | 2 - .../spike_source_poisson_vertex.py | 4 +- .../delays/delay_extension_vertex.py | 37 ++++---- .../pyNN/utilities/bit_field_utilities.py | 37 +------- spynnaker/pyNN/utilities/extracted_data.py | 1 - 24 files changed, 171 insertions(+), 146 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 4f9f6ce749..16eb9ec123 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -386,7 +386,6 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None, :param clear_tags: informs the tool chain if it should clear the tags off the machine at stop :type clear_tags: bool or None - :rtype: None """ # pylint: disable=protected-access for population in self._populations: @@ -402,7 +401,6 @@ def run(self, run_time): :param run_time: the time (in milliseconds) to run the simulation for :type run_time: float or int - :rtype: None """ # pylint: disable=protected-access @@ -427,7 +425,6 @@ def register_binary_search_path(search_path): """ Register an additional binary search path for executables. :param str search_path: absolute search path for binaries - :rtype: None """ # pylint: disable=protected-access AbstractSpiNNakerCommon.__EXECUTABLE_FINDER.add_path(search_path) diff --git a/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py b/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py index 45bb784607..0e1c62bcdd 100644 --- a/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py +++ b/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py @@ -33,5 +33,4 @@ def translate_control_packet(self, multicast_packet): :param multicast_packet: A received multicast packet :type multicast_packet: ~spinnman.messages.eieio.data_messages.AbstractEIEIODataElement - :rtype: None """ diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py index e142440eb4..0bfa0da5d0 100644 --- a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py +++ b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py @@ -182,7 +182,6 @@ def _rerun_synaptic_cores( :param ~.ExecutableFinder executable_finder: finder of binary file paths :param bool read_expander_iobuf: read off iobuf if needed - :rtype: None """ if synaptic_expander_rerun_cores.total_processors != 0: logger.info("rerunning synaptic expander") diff --git a/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py b/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py index 1131ab4ae6..7d2b795ac8 100644 --- a/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py +++ b/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py @@ -66,7 +66,7 @@ def get_connections_from_machine( # pylint: disable=too-many-arguments """ Get the connections from the machine post-run. - :param ~spinnman.Transceiver transceiver: + :param ~spinnman.transceiver.Transceiver transceiver: :param ~pacman.model.placements.Placement placement: :param ProjectionMachineEdge edge: :param ~pacman.model.routing_info.RoutingInfo routing_infos: @@ -76,11 +76,13 @@ def get_connections_from_machine( :param placements: :type placements: None or ~pacman.model.placements.Placements :param monitor_api: - :type monitor_api: None or \ + :type monitor_api: None or ~spinn_front_end_common.utility_models.DataSpeedUpPacketGatherMachineVertex :param fixed_routes: :param extra_monitor: the extra monitor for this - :type fixed_routes: None or \ + :type extra_monitor: + ~spinn_front_end_common.utility_models.ExtraMonitorSupportMachineVertex + :type fixed_routes: None or dict(tuple(int,int),~spinn_machine.FixedRouteEntry) """ diff --git a/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py b/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py index 4ed297a476..6ebd72bee0 100644 --- a/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py +++ b/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py @@ -35,5 +35,4 @@ def read_parameters_from_machine( the placement of a vertex :param ~pacman.model.graphs.common.Slice vertex_slice: the slice of atoms for this vertex - :rtype: None """ diff --git a/spynnaker/pyNN/models/abstract_models/abstract_settable.py b/spynnaker/pyNN/models/abstract_models/abstract_settable.py index fe91c7105f..b049d99da7 100644 --- a/spynnaker/pyNN/models/abstract_models/abstract_settable.py +++ b/spynnaker/pyNN/models/abstract_models/abstract_settable.py @@ -27,7 +27,7 @@ class AbstractSettable(object): @abstractmethod def get_value(self, key): - """ Get a property + """ Get a property of the model :param str key: the name of the property :rtype: Any or float or int or list(float) or list(int) @@ -35,7 +35,7 @@ def get_value(self, key): @abstractmethod def set_value(self, key, value): - """ Set a property + """ Set a property of the model :param str key: the name of the parameter to change :param value: the new value of the parameter to assign diff --git a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py index c2da949187..c06f071664 100644 --- a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py +++ b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py @@ -65,7 +65,6 @@ def clear_recording(self, variable, buffer_manager, placements): ~spinn_front_end_common.interface.buffer_management.BufferManager :param ~pacman.model.placements.Placements placements: the placements object - :rtype: None """ @abstractmethod diff --git a/spynnaker/pyNN/models/common/abstract_spike_recordable.py b/spynnaker/pyNN/models/common/abstract_spike_recordable.py index b31e410af1..789e055033 100644 --- a/spynnaker/pyNN/models/common/abstract_spike_recordable.py +++ b/spynnaker/pyNN/models/common/abstract_spike_recordable.py @@ -57,7 +57,6 @@ def clear_spike_recording(self, buffer_manager, placements): ~spinn_front_end_common.interface.buffer_management.BufferManager :param ~pacman.model.placements.Placements placements: the placements object - :rtype: None """ @abstractmethod diff --git a/spynnaker/pyNN/models/common/neuron_recorder.py b/spynnaker/pyNN/models/common/neuron_recorder.py index db564ffb2a..1000477a74 100644 --- a/spynnaker/pyNN/models/common/neuron_recorder.py +++ b/spynnaker/pyNN/models/common/neuron_recorder.py @@ -149,7 +149,14 @@ def get_neuron_sampling_interval(self, variable): def _convert_placement_matrix_data( self, row_data, n_rows, data_row_length, variable, n_neurons): - + """ + :param ~numpy.ndarray row_data: + :param int n_rows: + :param int data_row_length: + :param str variable: + :param int n_neurons: + :rtype: ~numpy.ndarray + """ surplus_bytes = self._N_BYTES_FOR_TIMESTAMP var_data = (row_data[:, surplus_bytes:].reshape( n_rows * data_row_length)) @@ -162,6 +169,17 @@ def _convert_placement_matrix_data( def _process_missing_data( missing_str, placement, expected_rows, n_neurons, times, sampling_rate, label, placement_data): + """ + :param str missing_str: + :param ~.Placement placement: + :param int expected_rows: + :param int n_neurons: + :param ~numpy.ndarray times: + :param int sampling_rate: + :param str label: + :param ~numpy.ndarray placement_data: + :rtype: ~numpy.ndarray + """ missing_str += "({}, {}, {}); ".format( placement.x, placement.y, placement.p) # Start the fragment for this slice empty @@ -334,7 +352,7 @@ def get_spikes( ~pacman.model.graphs.application.ApplicationVertex :param str variable: :param int machine_time_step: microseconds - :return: + :return: array of atom IDs and event times :rtype: ~numpy.ndarray(tuple(int,int)) """ if variable not in self.__bitfield_variables: @@ -649,7 +667,6 @@ def write_neuron_recording_region( :param ~pacman.model.graphs.commmon.Slice vertex_slice: the vertex slice :param int data_n_time_steps: how many time steps to run this time - :rtype: None """ spec.switch_write_focus(neuron_recording_region) spec.write_array(get_recording_header_array( @@ -926,4 +943,7 @@ def _get_data(self, vertex_slice): @property def _indexes(self): # for testing only + """ + :rtype: dict + """ return _ReadOnlyDict(self.__indexes) diff --git a/spynnaker/pyNN/models/neural_projections/synapse_information.py b/spynnaker/pyNN/models/neural_projections/synapse_information.py index d41264f61c..e95ab89ca5 100644 --- a/spynnaker/pyNN/models/neural_projections/synapse_information.py +++ b/spynnaker/pyNN/models/neural_projections/synapse_information.py @@ -17,7 +17,7 @@ from spynnaker.pyNN.models.neural_projections.connectors import ( AbstractGenerateConnectorOnMachine) from spynnaker.pyNN.models.neuron.synapse_dynamics import ( - AbstractGenerateOnMachine) + AbstractGenerateOnMachine, AbstractSynapseDynamicsStructural) class SynapseInformation(object): @@ -142,6 +142,16 @@ def synapse_dynamics(self): """ return self.__synapse_dynamics + @property + def is_structural(self): + """ Whether the dynamic behaviour of the synapse is structurally \ + plastic. + + :rtype: bool + """ + return isinstance(self.__synapse_dynamics, + AbstractSynapseDynamicsStructural) + @property def synapse_type(self): """ The type of the synapse diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index 78e4fc2a61..846b401a10 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -20,6 +20,9 @@ from pacman.model.graphs.application import ApplicationVertex from pacman.model.resources import ( ConstantSDRAM, CPUCyclesPerTickResource, DTCMResource, ResourceContainer) +from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \ + import ( + determine_max_atoms_for_vertex) from spinn_front_end_common.abstract_models import ( AbstractChangableAfterRun, AbstractProvidesIncomingPartitionConstraints, AbstractProvidesOutgoingPartitionConstraints, AbstractHasAssociatedBinary, @@ -38,25 +41,27 @@ from spinn_front_end_common.interface.profiling.profile_utils import ( get_profile_region_size, reserve_profile_region, write_profile_region_data) from spynnaker.pyNN.utilities.constants import ( - POPULATION_BASED_REGIONS, SPIKE_PARTITION_ID) -from spynnaker.pyNN.models.common import ( - AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder) + POPULATION_BASED_REGIONS, SPIKE_PARTITION_ID, BITS_PER_WORD) +from spynnaker.pyNN.utilities.ranged import ( + SpynnakerRangeDictionary, SpynnakerRangedList) +from spynnaker.pyNN.utilities.utility_calls import ceildiv from spynnaker.pyNN.utilities.bit_field_utilities import ( exact_sdram_for_bit_field_builder_region, - get_estimated_sdram_for_bit_field_region, get_estimated_sdram_for_key_region, - reserve_bit_field_regions, write_bitfield_init_data) + reserve_bit_field_regions, write_bitfield_init_data, + ELEMENTS_USED_IN_EACH_BIT_FIELD) +from spynnaker.pyNN.exceptions import InvalidParameterType from spynnaker.pyNN.models.abstract_models import ( AbstractPopulationInitializable, AbstractAcceptsIncomingSynapses, AbstractPopulationSettable, AbstractReadParametersBeforeSet, AbstractContainsUnits) -from spynnaker.pyNN.exceptions import InvalidParameterType -from spynnaker.pyNN.utilities.ranged import ( - SpynnakerRangeDictionary, SpynnakerRangedList) -from spynnaker.pyNN.utilities.utility_calls import ceildiv +from spynnaker.pyNN.models.common import ( + AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder) from .synapse_dynamics import AbstractSynapseDynamicsStructural from .synaptic_manager import SynapticManager from .population_machine_vertex import PopulationMachineVertex +from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex +from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge # TODO: Make sure these values are correct (particularly CPU cycles) _NEURON_BASE_DTCM_USAGE_IN_BYTES = 9 * BYTES_PER_WORD @@ -324,7 +329,7 @@ def _reserve_memory_regions( the slice of atoms from the application vertex :param ~.MachineVertex vertex: this vertex :param ~.MachineGraph machine_graph: machine graph - :param n_key_map: nkey map + :param ~.AbstractMachinePartitionNKeysMap n_key_map: nkey map :return: None """ spec.comment("\nReserving memory space for data regions:\n\n") @@ -508,13 +513,19 @@ def generate_data_specification( application_graph, machine_graph, routing_info, data_n_time_steps, n_key_map): """ - :param machine_time_step: (injected) - :param time_scale_factor: (injected) + :param int machine_time_step: (injected) + :param int time_scale_factor: (injected) :param application_graph: (injected) + :type application_graph: + ~pacman.model.graphs.application.ApplicationGraph :param machine_graph: (injected) - :param routing_info: (injected) - :param data_n_time_steps: (injected) + :type machine_graph: + ~pacman.model.graphs.machine.MachineGraph + :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected) + :param int data_n_time_steps: (injected) :param n_key_map: (injected) + :type n_key_map: + ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap """ # pylint: disable=too-many-arguments, arguments-differ vertex = placement.vertex @@ -725,8 +736,6 @@ def conductance_based(self): @overrides(AbstractPopulationSettable.get_value) def get_value(self, key): - """ Get a property of the overall model. - """ if key not in self._parameters: raise InvalidParameterType( "Population {} does not have parameter {}".format( @@ -735,8 +744,6 @@ def get_value(self, key): @overrides(AbstractPopulationSettable.set_value) def set_value(self, key, value): - """ Set a property of the overall model. - """ if key not in self._parameters: raise InvalidParameterType( "Population {} does not have parameter {}".format( @@ -847,21 +854,11 @@ def get_maximum_delay_supported_in_ms(self, machine_time_step): @overrides(AbstractProvidesIncomingPartitionConstraints. get_incoming_partition_constraints) def get_incoming_partition_constraints(self, partition): - """ Gets the constraints for partitions going into this vertex. - - :param partition: partition that goes into this vertex - :return: list of constraints - """ return self.__synapse_manager.get_incoming_partition_constraints() @overrides(AbstractProvidesOutgoingPartitionConstraints. get_outgoing_partition_constraints) def get_outgoing_partition_constraints(self, partition): - """ Gets the constraints for partitions going out of this vertex. - - :param partition: the partition that leaves this vertex - :return: list of constraints - """ return [ContiguousKeyRangeContraint()] @overrides( @@ -887,7 +884,6 @@ def _clear_recording_region( :param buffer_manager: the buffer manager object :param placements: the placements object :param recording_region_id: the recorded region ID for clearing - :rtype: None """ for machine_vertex in self.machine_vertices: placement = placements.get_placement_of_vertex(machine_vertex) @@ -956,3 +952,36 @@ def reset_to_first_timestep(self): if self.__synapse_manager.changes_during_run: self.__change_requires_data_generation = True self.__change_requires_neuron_parameters_reload = False + + +def get_estimated_sdram_for_bit_field_region(app_graph, vertex): + """ Estimates the SDRAM for the bit field region + + :param ~.ApplicationGraph app_graph: the app graph + :param ~.ApplicationVertex vertex: app vertex + :return: the estimated number of bytes used by the bit field region + :rtype: int + """ + sdram = 0 + for incoming_edge in app_graph.get_edges_ending_at_vertex(vertex): + if isinstance(incoming_edge, ProjectionApplicationEdge): + edge_pre_vertex = incoming_edge.pre_vertex + max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex) + if incoming_edge.pre_vertex.n_atoms < max_atoms: + max_atoms = incoming_edge.pre_vertex.n_atoms + + # Get the number of likely vertices + n_machine_vertices = ceildiv( + incoming_edge.pre_vertex.n_atoms, max_atoms) + n_atoms_per_machine_vertex = ceildiv( + incoming_edge.pre_vertex.n_atoms, n_machine_vertices) + if isinstance(edge_pre_vertex, DelayExtensionVertex): + n_atoms_per_machine_vertex *= \ + edge_pre_vertex.n_delay_stages + n_words_for_atoms = ceildiv( + n_atoms_per_machine_vertex, BITS_PER_WORD) + sdram += ( + (ELEMENTS_USED_IN_EACH_BIT_FIELD + ( + n_words_for_atoms * n_machine_vertices)) * + BYTES_PER_WORD) + return sdram diff --git a/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py b/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py index 0c23bafe62..3525cf9cab 100644 --- a/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py +++ b/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py @@ -73,11 +73,6 @@ def has_variable(self, variable): @overrides(AbstractAdditionalInput.get_values) def get_values(self, parameters, state_variables, vertex_slice, ts): - """ - :param int ts: machine time step - """ - # pylint: disable=arguments-differ - # Add the rest of the data return [parameters[TAU_CA2].apply_operation( operation=lambda x: numpy.exp(float(-ts) / (1000.0 * x))), diff --git a/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py b/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py index 9b656e1853..c971e5da94 100644 --- a/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py +++ b/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py @@ -87,7 +87,8 @@ def add_state_variables(self, state_variables): @abstractmethod def get_values(self, parameters, state_variables, vertex_slice, ts): - """ Get the values to be written to the machine for this model + # The way this docstring is built *is* a hack, but nothing else works + (r""" Get the values to be written to the machine for this model :param ~spinn_utilities.ranged.RangeDictionary parameters: The holder of the parameters @@ -97,10 +98,14 @@ def get_values(self, parameters, state_variables, vertex_slice, ts): The slice of variables being retrieved :param float ts: The time to be advanced in one call to the update of this component - :return: A list with the same length as self.struct.field_types + :return: A list with the same length as + `self.`\ """ + ":py:attr:`~spynnaker.pyNN.models.neuron.implementations." + r"AbstractStandardNeuronComponent.struct`\ " + """`.`\\ :py:attr:`~spynnaker.pyNN.utilities.struct.Struct.field_types` :rtype: list(int or float or list(int) or list(float) or ~spinn_utilities.ranged.RangedList) - """ + """) def get_data(self, parameters, state_variables, vertex_slice, ts): """ Get the data *to be written to the machine* for this model. diff --git a/spynnaker/pyNN/models/neuron/master_pop_table.py b/spynnaker/pyNN/models/neuron/master_pop_table.py index 77ead72cd4..cd1cb5e930 100644 --- a/spynnaker/pyNN/models/neuron/master_pop_table.py +++ b/spynnaker/pyNN/models/neuron/master_pop_table.py @@ -206,8 +206,6 @@ def get_next_allowed_address(self, next_address): def initialise_table(self): """ Initialise the master pop data structure. - - :rtype: None """ self.__entries = dict() self.__n_addresses = 0 diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py index 624e4229d3..0be672be43 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py @@ -122,3 +122,16 @@ def elimination(self): :rtype: AbstractElimination """ + + def get_per_edge_parameters_sdram_usage_in_bytes(self): + """ Get the amount of SDRAM used by the parameters of the rules per \ + structurally-plastic synapse. + + .. note:: + The partner selection rule is shared. + + :rtype: int + """ + # pylint: disable=no-member + return (self.formation.get_parameters_sdram_usage_in_bytes() + + self.elimination.get_parameters_sdram_usage_in_bytes()) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py index 932aeb57f8..2d75e0536a 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py @@ -19,8 +19,6 @@ MICRO_TO_MILLISECOND_CONVERSION, MICRO_TO_SECOND_CONVERSION, BYTES_PER_WORD, BYTES_PER_SHORT) from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge -from .abstract_synapse_dynamics_structural import ( - AbstractSynapseDynamicsStructural) from spynnaker.pyNN.exceptions import SynapticConfigurationException from spynnaker.pyNN.utilities.utility_calls import ceildiv @@ -224,8 +222,8 @@ def write_parameters( def __get_structural_edges(self, app_graph, app_vertex): """ - :param ~pacman.model.graphs.application.ApplicationGraph app_graph: - :param ~pacman.model.graphs.application.ApplicationVertex app_vertex: + :param ~.ApplicationGraph app_graph: + :param ~.ApplicationVertex app_vertex: :rtype: list(tuple(ProjectionApplicationEdge, SynapseInformation)) """ structural_edges = list() @@ -233,8 +231,7 @@ def __get_structural_edges(self, app_graph, app_vertex): if isinstance(app_edge, ProjectionApplicationEdge): found = False for synapse_info in app_edge.synapse_information: - if isinstance(synapse_info.synapse_dynamics, - AbstractSynapseDynamicsStructural): + if synapse_info.is_structural: if found: raise SynapticConfigurationException( "Only one Projection between each pair of " @@ -247,16 +244,13 @@ def __write_common_rewiring_data( self, spec, app_vertex, post_slice, machine_time_step, n_pre_pops): """ Write the non-sub-population synapse parameters to the spec. - :param ~data_specification.DataSpecificationGenerator spec: - the data spec + :param ~.DataSpecificationGenerator spec: the data spec :param AbstractPopulationVertex app_vertex: the highest level object of the post-synaptic population :param ~pacman.model.graphs.common.Slice post_slice: the slice of the app vertex corresponding to this machine vertex :param int machine_time_step: the duration of a machine time step (ms) :param int n_pre_pops: the number of pre-populations - :return: None - :rtype: None """ if (self.__p_rew * MICRO_TO_MILLISECOND_CONVERSION < machine_time_step / MICRO_TO_MILLISECOND_CONVERSION): @@ -304,7 +298,7 @@ def __write_prepopulation_info( routing_info, weight_scales, post_slice, synapse_indices, machine_time_step): """ - :param ~data_specification.DataSpecificationGenerator spec: + :param ~.DataSpecificationGenerator spec: :param AbstractPopulationVertex app_vertex: :param structural_edges: :type structural_edges: @@ -367,7 +361,7 @@ def __write_post_to_pre_table( """ Post to pre table is basically the transpose of the synaptic\ matrix. - :param ~data_specification.DataSpecificationGenerator spec: + :param ~.DataSpecificationGenerator spec: :param pop_index: :type pop_index: dict(tuple(AbstractPopulationVertex,SynapseInformation),int) @@ -439,21 +433,18 @@ def get_parameters_sdram_usage_in_bytes( param_sizes = self.__partner_selection\ .get_parameters_sdram_usage_in_bytes() for (in_edge, synapse_info) in structural_edges: - max_atoms = in_edge.pre_vertex.get_max_atoms_per_core() - if in_edge.pre_vertex.n_atoms < max_atoms: - max_atoms = in_edge.pre_vertex.n_atoms - n_sub_edges += ceildiv(in_edge.pre_vertex.n_atoms, max_atoms) - dynamics = synapse_info.synapse_dynamics - param_sizes += dynamics.formation\ - .get_parameters_sdram_usage_in_bytes() - param_sizes += dynamics.elimination\ - .get_parameters_sdram_usage_in_bytes() - - return int((self._REWIRING_DATA_SIZE + - (self._PRE_POP_INFO_BASE_SIZE * len(structural_edges)) + - (self._KEY_ATOM_INFO_SIZE * n_sub_edges) + - (self._POST_TO_PRE_ENTRY_SIZE * n_neurons * self.__s_max) + - param_sizes)) + n_sub_edges += ceildiv(in_edge.pre_vertex.n_atoms, min( + in_edge.pre_vertex.get_max_atoms_per_core(), + in_edge.pre_vertex.n_atoms)) + param_sizes += synapse_info.synapse_dynamics.\ + get_per_edge_parameters_sdram_usage_in_bytes() + + return int( + self._REWIRING_DATA_SIZE + + (self._PRE_POP_INFO_BASE_SIZE * len(structural_edges)) + + (self._KEY_ATOM_INFO_SIZE * n_sub_edges) + + (self._POST_TO_PRE_ENTRY_SIZE * n_neurons * self.__s_max) + + param_sizes) def synaptic_data_update( self, connections, post_vertex_slice, app_edge, synapse_info, @@ -466,8 +457,7 @@ def synaptic_data_update( :param SynapseInformation synapse_info: :param ProjectionMachineEdge machine_edge: """ - if not isinstance(synapse_info.synapse_dynamics, - AbstractSynapseDynamicsStructural): + if not synapse_info.is_structural: return collector = self.__connections.setdefault( (app_edge.post_vertex, post_vertex_slice.lo_atom), []) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py index c764d2e46f..dd98b0315e 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py @@ -28,7 +28,7 @@ class SynapseDynamicsStructuralSTDP( It acts as a wrapper around :py:class:`SynapseDynamicsSTDP`, meaning rewiring can operate in parallel with STDP synapses. - Written by Petrut Bogdan. + :codeauthor: Petrut Bogdan """ __slots__ = ["__common_sp"] diff --git a/spynnaker/pyNN/models/neuron/synapse_io.py b/spynnaker/pyNN/models/neuron/synapse_io.py index e59c0fb7dd..5557bcc640 100644 --- a/spynnaker/pyNN/models/neuron/synapse_io.py +++ b/spynnaker/pyNN/models/neuron/synapse_io.py @@ -500,6 +500,11 @@ def __convert_delayed_data( self, n_synapses, pre_vertex_slice, delayed_connections): """ Take the delayed_connections and convert the source ids and delay\ values + + :param int n_synapses: + :param ~pacman.model.graphs.common.Slice pre_vertex_slice: + :param ~numpy.ndarray delayed_connections: + :rtype: ~numpy.ndarray """ synapse_ids = range(len(n_synapses)) row_stage = numpy.array([ diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index 636ed2efd7..faecca23e2 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -30,8 +30,7 @@ AbstractGenerateConnectorOnMachine) from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge from .synapse_dynamics import ( - AbstractSynapseDynamicsStructural, - AbstractGenerateOnMachine, SynapseDynamicsStructuralSTDP) + AbstractSynapseDynamicsStructural, AbstractGenerateOnMachine) from spynnaker.pyNN.models.neuron.synapse_io import SynapseIORowBased from spynnaker.pyNN.models.spike_source.spike_source_poisson_vertex import ( SpikeSourcePoissonVertex) @@ -368,7 +367,7 @@ def __add_synapse_size(self, memory_size, synapse_info, post_vertex_slice, def _get_size_of_generator_information(self, in_edges): """ Get the size of the synaptic expander parameters - :param list(.ApplicationEdge) in_edges: + :param list(~.ApplicationEdge) in_edges: :rtype: int """ gen_on_machine = False diff --git a/spynnaker/pyNN/models/recording_common.py b/spynnaker/pyNN/models/recording_common.py index d17180bd91..29e69be4ea 100644 --- a/spynnaker/pyNN/models/recording_common.py +++ b/spynnaker/pyNN/models/recording_common.py @@ -206,8 +206,6 @@ def _get_spikes(self): def _turn_off_all_recording(self, indexes=None): """ Turns off recording, is used by a pop saying `.record()` - - :rtype: None """ # check for standard record which includes spikes if isinstance(self.__population._vertex, AbstractNeuronRecordable): diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index a2436864ea..05fd6d425f 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -548,7 +548,7 @@ def reserve_memory_regions(self, spec, placement): :param ~data_specification.DataSpecification spec: the data specification writer - :param ~pacman.models.placements.Placement placement: + :param ~pacman.model.placements.Placement placement: the location this vertex resides on in the machine :return: None """ @@ -577,7 +577,7 @@ def _reserve_poisson_params_rates_region(self, placement, spec): """ Allocate space for the Poisson parameters and rates regions as\ they can be reused for setters after an initial run - :param ~pacman.models.placements.Placement placement: + :param ~pacman.model.placements.Placement placement: the location on machine for this vertex :param ~data_specification.DataSpecification spec: the DSG writer :return: None diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py index 2e6e42bf90..4073a0a2dc 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py @@ -379,6 +379,7 @@ def _get_edge_generator_size(self, synapse_info): """ Get the size of the generator data for a given synapse info object :param SynapseInformation synapse_info: + :rtype: int """ connector = synapse_info.connector dynamics = synapse_info.synapse_dynamics @@ -403,28 +404,32 @@ def _get_size_of_generator_information(self, out_edges): :param list(.ApplicationEdge) out_edges: :rtype: int """ - gen_on_machine = False size = 0 for out_edge in out_edges: if isinstance(out_edge, DelayedApplicationEdge): - for synapse_info in out_edge.synapse_information: - - # Get the number of likely vertices - max_atoms = out_edge.post_vertex.get_max_atoms_per_core() - if out_edge.post_vertex.n_atoms < max_atoms: - max_atoms = out_edge.post_vertex.n_atoms - n_edge_vertices = ceildiv( - out_edge.post_vertex.n_atoms, max_atoms) - - # Get the size - gen_size = self._get_edge_generator_size(synapse_info) - if gen_size > 0: - gen_on_machine = True - size += gen_size * n_edge_vertices - if gen_on_machine: + size += self.__size_of_edge_generator_info(out_edge) + # If there's a non-zero size, we will be generating on machine and we + # should add the baseline overhead + if size: size += _EXPANDER_BASE_PARAMS_SIZE return size + def __size_of_edge_generator_info(self, edge): + """ + :param DelayedApplicationEdge edge: + """ + # Get the number of likely vertices + max_atoms = min( + edge.post_vertex.get_max_atoms_per_core(), + edge.post_vertex.n_atoms) + n_edge_vertices = ceildiv(edge.post_vertex.n_atoms, max_atoms) + + # Get the size for each synapse type + return sum( + self._get_edge_generator_size(synapse_info) * n_edge_vertices + for synapse_info in edge.synapse_information) + + def get_dtcm_usage_for_atoms(self, vertex_slice): """ :param ~pacman.model.graphs.common.Slice vertex_slice: diff --git a/spynnaker/pyNN/utilities/bit_field_utilities.py b/spynnaker/pyNN/utilities/bit_field_utilities.py index 0b5d27e5d6..480d3d5962 100644 --- a/spynnaker/pyNN/utilities/bit_field_utilities.py +++ b/spynnaker/pyNN/utilities/bit_field_utilities.py @@ -14,13 +14,11 @@ # along with this program. If not, see . from pacman.utilities.constants import FULL_MASK -from spynnaker.pyNN.utilities.utility_calls import ceildiv from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \ import ( determine_max_atoms_for_vertex) from spinn_front_end_common.utilities.constants import BYTES_PER_WORD -from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge -from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex +from spynnaker.pyNN.utilities.utility_calls import ceildiv # number of elements ELEMENTS_USED_IN_EACH_BIT_FIELD = 3 # n words, key, pointer to bitfield @@ -43,39 +41,6 @@ BIT_IN_A_WORD = 32.0 -def get_estimated_sdram_for_bit_field_region(app_graph, vertex): - """ Estimates the SDRAM for the bit field region - - :param ~.ApplicationGraph app_graph: the app graph - :param ~.ApplicationVertex vertex: app vertex - :return: the estimated number of bytes used by the bit field region - :rtype: int - """ - sdram = 0 - for incoming_edge in app_graph.get_edges_ending_at_vertex(vertex): - if isinstance(incoming_edge, ProjectionApplicationEdge): - edge_pre_vertex = incoming_edge.pre_vertex - max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex) - if incoming_edge.pre_vertex.n_atoms < max_atoms: - max_atoms = incoming_edge.pre_vertex.n_atoms - - # Get the number of likely vertices - n_machine_vertices = ceildiv( - incoming_edge.pre_vertex.n_atoms, max_atoms) - n_atoms_per_machine_vertex = ceildiv( - incoming_edge.pre_vertex.n_atoms, n_machine_vertices) - if isinstance(edge_pre_vertex, DelayExtensionVertex): - n_atoms_per_machine_vertex *= \ - edge_pre_vertex.n_delay_stages - n_words_for_atoms = ceildiv( - n_atoms_per_machine_vertex, int(BIT_IN_A_WORD)) - sdram += ( - (ELEMENTS_USED_IN_EACH_BIT_FIELD + ( - n_words_for_atoms * n_machine_vertices)) * - BYTES_PER_WORD) - return sdram - - def get_estimated_sdram_for_key_region(app_graph, vertex): """ gets an estimate of the bitfield builder region diff --git a/spynnaker/pyNN/utilities/extracted_data.py b/spynnaker/pyNN/utilities/extracted_data.py index 9252403c1f..7ca817c9e9 100644 --- a/spynnaker/pyNN/utilities/extracted_data.py +++ b/spynnaker/pyNN/utilities/extracted_data.py @@ -50,6 +50,5 @@ def set(self, projection, attribute, data): :type attribute: list(int) or tuple(int) or None :param ConnectionHolder data: attribute data in a connection holder - :rtype: None """ self.__data[projection][attribute] = data From dcb1ea2e2d86ead4f46166bc632b2ca62a87c95b Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 10 Aug 2020 12:35:05 +0100 Subject: [PATCH 10/11] Found a way to break the import loop reported by Sphinx Also fix a few trivialities along the way --- spynnaker/pyNN/abstract_spinnaker_common.py | 21 ++++++++++++++----- ...ker_machine_bit_field_router_compressor.py | 2 +- .../delays/delay_extension_vertex.py | 1 - 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 16eb9ec123..350a76e18b 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -28,7 +28,6 @@ from spinn_front_end_common.utilities.utility_objs import ExecutableFinder from spinn_front_end_common.utilities.globals_variables import unset_simulator from spinn_front_end_common.utilities.helpful_functions import read_config -from spynnaker.pyNN import extra_algorithms, model_binaries from spynnaker.pyNN.utilities.constants import ( MAX_DELAY_BLOCKS, MAX_SUPPORTED_DELAY_TICS, MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, MIN_SUPPORTED_DELAY) @@ -37,10 +36,25 @@ from spynnaker.pyNN.utilities.extracted_data import ExtractedData from spynnaker import __version__ as version from spynnaker.pyNN.utilities.utility_calls import round_up +from spynnaker.pyNN import model_binaries logger = FormatAdapter(logging.getLogger(__name__)) +def _extra_algo_path(): + """ List containing the names of the extra algorithms config files. + + .. note:: + Need to `import` within this to avoid an import loop. + + :rtype: list(str) + """ + import spynnaker.pyNN.extra_algorithms + return [os.path.join( + os.path.dirname(spynnaker.pyNN.extra_algorithms.__file__), + "algorithms_metadata.xml")] + + class AbstractSpiNNakerCommon(with_metaclass( AbstractBase, AbstractSpinnakerBase, SpynnakerSimulatorInterface)): """ Main interface for neural code. @@ -116,10 +130,7 @@ def __init__( # create XML path for where to locate sPyNNaker related functions when # using auto pause and resume - extra_algorithm_xml_path = list() - extra_algorithm_xml_path.append(os.path.join( - os.path.dirname(extra_algorithms.__file__), - "algorithms_metadata.xml")) + extra_algorithm_xml_path = _extra_algo_path() if user_extra_algorithm_xml_path is not None: extra_algorithm_xml_path.extend(user_extra_algorithm_xml_path) diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py index 0bfa0da5d0..8a0e652f11 100644 --- a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py +++ b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py @@ -27,7 +27,7 @@ MachineBitFieldUnorderedRouterCompressor) from spinn_front_end_common.utilities import system_control_logic from spinn_front_end_common.utilities.utility_objs import ExecutableType -from spynnaker.pyNN.extra_algorithms.synapse_expander import SYNAPSE_EXPANDER +from .synapse_expander import SYNAPSE_EXPANDER logger = logging.getLogger(__name__) diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py index 4073a0a2dc..2f44a37ca2 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py @@ -429,7 +429,6 @@ def __size_of_edge_generator_info(self, edge): self._get_edge_generator_size(synapse_info) * n_edge_vertices for synapse_info in edge.synapse_information) - def get_dtcm_usage_for_atoms(self, vertex_slice): """ :param ~pacman.model.graphs.common.Slice vertex_slice: From 10c1fa7673d6433996121de0af565fae99384392 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 10 Aug 2020 18:51:44 +0100 Subject: [PATCH 11/11] Bits merged from #836 --- spynnaker/pyNN/abstract_spinnaker_common.py | 4 +- .../push_bot_spinnaker_link_retina_device.py | 13 +- .../extra_algorithms/graph_edge_filter.py | 13 +- .../graph_edge_weight_updater.py | 5 +- .../on_chip_bit_field_generator.py | 23 ++-- ...ker_machine_bit_field_router_compressor.py | 51 +++++++- .../common/abstract_neuron_recordable.py | 4 +- .../common/abstract_spike_recordable.py | 4 +- .../models/common/eieio_spike_recorder.py | 18 ++- .../models/common/multi_spike_recorder.py | 8 +- .../pyNN/models/common/neuron_recorder.py | 12 +- ...act_connector_supports_views_on_machine.py | 2 +- .../index_based_probability_connector.py | 13 +- .../connectors/kernel_connector.py | 21 ++-- .../connectors/one_to_one_connector.py | 3 +- .../neural_projections/synapse_information.py | 12 +- .../neuron/abstract_population_vertex.py | 114 ++++++++++++------ .../neuron/abstract_pynn_neuron_model.py | 16 +++ .../pyNN/models/neuron/master_pop_table.py | 12 +- .../neuron_models/abstract_neuron_model.py | 2 +- ...timing_dependence_pfister_spike_triplet.py | 21 +--- .../timing_dependence_recurrent.py | 28 ++--- .../timing_dependence_spike_nearest_pair.py | 20 +-- .../timing_dependence_spike_pair.py | 24 +--- .../timing_dependence_vogels_2011.py | 21 +--- .../weight_dependence_additive.py | 11 +- .../weight_dependence_additive_triplet.py | 15 +-- .../weight_dependence_multiplicative.py | 11 +- .../neuron/population_machine_vertex.py | 2 + .../formation/distance_dependent_formation.py | 8 +- .../last_neuron_selection.py | 2 +- .../abstract_synapse_dynamics_structural.py | 2 + .../synapse_dynamics/synapse_dynamics_stdp.py | 18 ++- .../synapse_dynamics_structural_common.py | 35 +++++- .../synapse_dynamics_structural_static.py | 2 +- .../synapse_dynamics_structural_stdp.py | 2 +- .../neuron/synapse_types/synapse_type_semd.py | 3 +- .../pyNN/models/neuron/synaptic_manager.py | 2 + .../pyNN/models/pynn_population_common.py | 4 +- .../pyNN/models/pynn_projection_common.py | 4 +- spynnaker/pyNN/models/recording_common.py | 1 - .../spike_source_poisson_vertex.py | 100 ++++++++------- .../delays/delay_extension_machine_vertex.py | 10 +- .../delays/delay_extension_vertex.py | 23 ++-- ...pynnaker_external_device_plugin_manager.py | 11 +- .../pyNN/utilities/bit_field_utilities.py | 41 ++++--- spynnaker/pyNN/utilities/struct.py | 3 +- spynnaker/pyNN/utilities/utility_calls.py | 25 +++- 48 files changed, 446 insertions(+), 353 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 350a76e18b..a029f488eb 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -101,7 +101,7 @@ def __init__( :param user_extra_algorithms_pre_run: :type user_extra_algorithms_pre_run: list(str) or None :param time_scale_factor: - :type time_scale_factor: + :type time_scale_factor: int or None :param extra_post_run_algorithms: :type extra_post_run_algorithms: list(str) or None :param extra_mapping_algorithms: @@ -109,7 +109,7 @@ def __init__( :param extra_load_algorithms: :type extra_load_algorithms: list(str) or None :param front_end_versions: - :type front_end_versions: + :type front_end_versions: list(tuple(str,str)) or None """ # pylint: disable=too-many-arguments, too-many-locals diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py index 0f663f400e..77d25a060a 100644 --- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py +++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py @@ -32,15 +32,12 @@ def __init__( board_address=default_parameters['board_address'], label=default_parameters['label']): """ - :param spinnaker_link_id: - :param protocol: - :type protocol: MunichIoSpiNNakerLinkProtocol - :param resolution: - :type resolution: PushBotRetinaResolution - :param board_address: - :param label: + :param int spinnaker_link_id: + :param MunichIoSpiNNakerLinkProtocol protocol: + :param PushBotRetinaResolution resolution: + :param str board_address: + :param str label: """ - AbstractPushBotRetinaDevice.__init__(self, protocol, resolution) ApplicationSpiNNakerLinkVertex.__init__( self, spinnaker_link_id=spinnaker_link_id, diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py index 2e00a4b414..88ca48c670 100644 --- a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py +++ b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py @@ -33,9 +33,10 @@ def __call__(self, app_graph, machine_graph): :param app_graph: The application graph :type app_graph: ~pacman.model.graphs.application.ApplicationGraph or None - :param .MachineGraph machine_graph: + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: The machine_graph whose edges are to be filtered :return: a new, filtered machine graph + :rtype: ~pacman.model.graphs.machine.MachineGraph """ new_machine_graph = MachineGraph( label=machine_graph.label, application_graph=app_graph) @@ -73,9 +74,9 @@ def __call__(self, app_graph, machine_graph): @staticmethod def _add_edge_to_new_graph(edge, partition, new_graph): """ - :param .MachineEdge edge: - :param .OutgoingEdgePartition partition: - :param .MachineGraph new_graph: + :param ~.MachineEdge edge: + :param ~.OutgoingEdgePartition partition: + :param ~.MachineGraph new_graph: """ new_graph.add_edge(edge, partition.identifier) edge.associate_application_edge() @@ -90,16 +91,18 @@ def _add_edge_to_new_graph(edge, partition, new_graph): @staticmethod def _is_filterable(edge): """ - :param .MachineEdge edge: + :param ~.MachineEdge edge: :rtype: bool """ # If our associated application edge wants to say don't filter... if (isinstance(edge.app_edge, AbstractFilterableEdge) and not edge.app_edge.filter_edge()): return False + if isinstance(edge, AbstractFilterableEdge): return edge.filter_edge() elif isinstance(edge.app_edge, ApplicationEdge): return False + # Bad graph construction? raise FilterableException( "cannot figure out if edge {} is prunable or not".format(edge)) diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py index ee9fc475f3..03529c2a76 100644 --- a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py +++ b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py @@ -23,9 +23,10 @@ class GraphEdgeWeightUpdater(object): def __call__(self, machine_graph): """ - :param machine_graph: the machine_graph whose edges are to be updated + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: + the machine_graph whose edges are to be updated + :rtype: ~pacman.model.graphs.machine.MachineGraph """ - # create progress bar progress = ProgressBar( machine_graph.n_outgoing_edge_partitions, diff --git a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py index e4ba3ad8cd..854705a738 100644 --- a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py +++ b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py @@ -61,7 +61,7 @@ class OnChipBitFieldGenerator(object): flag for making summary report """ - __slots__ = ("__transceiver", "__placements") + __slots__ = ("__transceiver", "__placements", "__binary") # flag which states that the binary finished cleanly. _SUCCESS = 0 @@ -109,6 +109,8 @@ def __call__( """ self.__transceiver = transceiver self.__placements = placements + self.__binary = executable_finder.get_executable_path( + self._BIT_FIELD_EXPANDER_APLX) # progress bar progress = ProgressBar( @@ -117,8 +119,7 @@ def __call__( # get data expander_cores = self._calculate_core_data( - app_graph, progress, executable_finder.get_executable_path( - self._BIT_FIELD_EXPANDER_APLX)) + app_graph, progress) # load data bit_field_app_id = transceiver.app_id_tracker.get_new_id() @@ -265,7 +266,6 @@ def _read_back_bit_fields( :param ~.ApplicationGraph app_graph: app graph :param str default_report_folder: the file path for where reports are """ - # generate file progress = ProgressBar( len(app_graph.vertices), "reading back bitfields from chip") @@ -308,13 +308,11 @@ def _bit_for_neuron_id(cls, bit_field, neuron_id): flag = (bit_field[word_id] >> bit_in_word) & cls._BIT_MASK return flag - def _calculate_core_data( - self, app_graph, progress, bit_field_expander_path): + def _calculate_core_data(self, app_graph, progress): """ gets the data needed for the bit field expander for the machine :param ~.ApplicationGraph app_graph: app graph :param ~.ProgressBar progress: progress bar - :param str bit_field_expander_path: where to find the executable :return: data and expander cores :rtype: ExecutableTargets """ @@ -324,23 +322,20 @@ def _calculate_core_data( # locate verts which can have a synaptic matrix to begin with for app_vertex in progress.over(app_graph.vertices, False): for placement in self.__bitfield_placements(app_vertex): - self.__write_single_core_data( - placement, bit_field_expander_path, expander_cores) + self.__write_single_core_data(placement, expander_cores) return expander_cores - def __write_single_core_data( - self, placement, bit_field_expander_path, expander_cores): + def __write_single_core_data(self, placement, expander_cores): """ :param ~.Placement placement: The vertex must support AbstractSupportsBitFieldGeneration - :param str bit_field_expander_path: :param ~.ExecutableTargets expander_cores: """ # check if the chip being considered already. expander_cores.add_processor( - bit_field_expander_path, placement.x, placement.y, - placement.p, executable_type=ExecutableType.SYSTEM) + self.__binary, placement.x, placement.y, placement.p, + executable_type=ExecutableType.SYSTEM) bit_field_builder_region = placement.vertex.bit_field_builder_region( self.__transceiver, placement) diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py index 8a0e652f11..450be66bd6 100644 --- a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py +++ b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py @@ -119,7 +119,8 @@ def __call__( def compressor_factory(self): """ Creates the specific compressor to use. - :rtype: MachineBitFieldRouterCompressor + :rtype: + ~spinn_front_end_common.interface.interface_functions.MachineBitFieldRouterCompressor """ def _locate_synaptic_expander_cores( @@ -195,6 +196,30 @@ def _rerun_synaptic_cores( class SpynnakerMachineBitFieldUnorderedRouterCompressor( SpynnakerMachineBitFieldRouterCompressor): + """ Bitfield-aware on-machine routing table compression algorithm that \ + uses the unordered routing compressor. + + :param ~pacman.model.routing_tables.MulticastRoutingTables routing_tables: + routing tables + :param ~spinnman.transceiver.Transceiver transceiver: spinnman instance + :param ~spinn_machine.Machine machine: spinnMachine instance + :param int app_id: app id of the application + :param str provenance_file_path: file path for prov data + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: + machine graph + :param ~pacman.model.placements.Placements placements: + placements on machine + :param int threshold_percentage: + the percentage of bitfields to do on chip before its considered a + success + :param executable_finder: where are binaries are located + :type executable_finder: + ~spinn_front_end_common.utilities.utility_objs.ExecutableFinder + :param bool read_algorithm_iobuf: flag saying if read iobuf + :param bool compress_as_much_as_possible: + flag asking if should compress as much as possible + :param bool read_expander_iobuf: reads the synaptic expander iobuf. + """ @overrides(SpynnakerMachineBitFieldRouterCompressor.compressor_factory) def compressor_factory(self): @@ -203,6 +228,30 @@ def compressor_factory(self): class SpynnakerMachineBitFieldPairRouterCompressor( SpynnakerMachineBitFieldRouterCompressor): + """ Bitfield-aware on-machine routing table compression algorithm that \ + uses the paired routing compressor. + + :param ~pacman.model.routing_tables.MulticastRoutingTables routing_tables: + routing tables + :param ~spinnman.transceiver.Transceiver transceiver: spinnman instance + :param ~spinn_machine.Machine machine: spinnMachine instance + :param int app_id: app id of the application + :param str provenance_file_path: file path for prov data + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: + machine graph + :param ~pacman.model.placements.Placements placements: + placements on machine + :param int threshold_percentage: + the percentage of bitfields to do on chip before its considered a + success + :param executable_finder: where are binaries are located + :type executable_finder: + ~spinn_front_end_common.utilities.utility_objs.ExecutableFinder + :param bool read_algorithm_iobuf: flag saying if read iobuf + :param bool compress_as_much_as_possible: + flag asking if should compress as much as possible + :param bool read_expander_iobuf: reads the synaptic expander iobuf. + """ @overrides(SpynnakerMachineBitFieldRouterCompressor.compressor_factory) def compressor_factory(self): diff --git a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py index c06f071664..e32c34efe3 100644 --- a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py +++ b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py @@ -28,7 +28,7 @@ class AbstractNeuronRecordable(object): @abstractmethod def get_recordable_variables(self): """ Returns a list of the PyNN names of variables this model is \ - expected to collect + expected to collect. :rtype: list(str) """ @@ -45,7 +45,7 @@ def is_recording(self, variable): @abstractmethod def set_recording(self, variable, new_state=True, sampling_interval=None, indexes=None): - """ Sets variable to being recorded + """ Sets variable to being recorded. :param str variable: PyNN name of the variable :param bool new_state: diff --git a/spynnaker/pyNN/models/common/abstract_spike_recordable.py b/spynnaker/pyNN/models/common/abstract_spike_recordable.py index 789e055033..b24c89515b 100644 --- a/spynnaker/pyNN/models/common/abstract_spike_recordable.py +++ b/spynnaker/pyNN/models/common/abstract_spike_recordable.py @@ -26,7 +26,7 @@ class AbstractSpikeRecordable(object): @abstractmethod def is_recording_spikes(self): - """ Determine if spikes are being recorded + """ Determine if spikes are being recorded. :return: True if spikes are being recorded, False otherwise :rtype: bool @@ -36,7 +36,7 @@ def is_recording_spikes(self): def set_recording_spikes( self, new_state=True, sampling_interval=None, indexes=None): """ Set spikes to being recorded. \ - If `new_state` is false all other parameters are ignored. + If `new_state` is False all other parameters are ignored. :param bool new_state: Set if the spikes are recording or not :param sampling_interval: The interval at which spikes are recorded. diff --git a/spynnaker/pyNN/models/common/eieio_spike_recorder.py b/spynnaker/pyNN/models/common/eieio_spike_recorder.py index 0e81829e03..326d208206 100644 --- a/spynnaker/pyNN/models/common/eieio_spike_recorder.py +++ b/spynnaker/pyNN/models/common/eieio_spike_recorder.py @@ -19,9 +19,9 @@ from spinn_utilities.progress_bar import ProgressBar from spinn_utilities.log import FormatAdapter from spinnman.messages.eieio.data_messages import EIEIODataHeader -from spynnaker.pyNN.models.common import recording_utils from spinn_front_end_common.utilities.constants import ( BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION) +from spynnaker.pyNN.models.common.recording_utils import make_missing_string logger = FormatAdapter(logging.getLogger(__name__)) _ONE_WORD = struct.Struct(" 0: + if n_buffer_times: + placement = placements.get_placement_of_vertex(vertex) raw_spike_data, data_missing = \ buffer_manager.get_data_by_placement(placement, region) if data_missing: missing.append(placement) self._process_spike_data( - vertex_slice, raw_spike_data, ms_per_tick, + vertex.vertex_slice, raw_spike_data, ms_per_tick, base_key_function(vertex), results) if missing: - missing_str = recording_utils.make_missing_string(missing) + missing_str = make_missing_string(missing) logger.warning( "Population {} is missing spike data in region {} from the" " following cores: {}", label, region, missing_str) diff --git a/spynnaker/pyNN/models/common/multi_spike_recorder.py b/spynnaker/pyNN/models/common/multi_spike_recorder.py index dbf4b3aee2..c4301d6913 100644 --- a/spynnaker/pyNN/models/common/multi_spike_recorder.py +++ b/spynnaker/pyNN/models/common/multi_spike_recorder.py @@ -48,14 +48,16 @@ def record(self, record): def get_sdram_usage_in_bytes(self, n_neurons, spikes_per_timestep): """ + :param int n_neurons: + :param int spikes_per_timestep: :rtype: ~pacman.model.resources.AbstractSDRAM """ if not self.__record: return ConstantSDRAM(0) - out_spike_bytes = ceildiv(n_neurons, BITS_PER_WORD) * BYTES_PER_WORD - return VariableSDRAM(0, (2 * BYTES_PER_WORD) + ( - out_spike_bytes * spikes_per_timestep)) + out_spike_words = ceildiv(n_neurons, BITS_PER_WORD) + return VariableSDRAM( + 0, (2 + out_spike_words * spikes_per_timestep) * BYTES_PER_WORD) def get_dtcm_usage_in_bytes(self): """ diff --git a/spynnaker/pyNN/models/common/neuron_recorder.py b/spynnaker/pyNN/models/common/neuron_recorder.py index 1000477a74..f8e82d8ad6 100644 --- a/spynnaker/pyNN/models/common/neuron_recorder.py +++ b/spynnaker/pyNN/models/common/neuron_recorder.py @@ -205,7 +205,7 @@ def _get_placement_matrix_data( buffer_manager, expected_rows, missing_str, sampling_rate, label): """ processes a placement for matrix data - :param variable: the variable to read + :param str variable: the variable to read :param ~pacman.model.placements.Placements placements: the placements object :param ~pacman.model.graphs.machine.MachineVertex vertex: @@ -768,20 +768,12 @@ def get_buffered_sdram(self, variable, vertex_slice, n_machine_time_steps): records = records + 1 return data_size * records - @staticmethod - def __n_bytes_to_n_words(n_bytes): - """ - :param int n_bytes: - :rtype: int - """ - return (n_bytes + (BYTES_PER_WORD - 1)) // BYTES_PER_WORD - def get_sdram_usage_in_bytes(self, vertex_slice): """ :param ~pacman.model.graphs.common.Slice vertex_slice: :rtype: int """ - n_words_for_n_neurons = self.__n_bytes_to_n_words(vertex_slice.n_atoms) + n_words_for_n_neurons = ceildiv(vertex_slice.n_atoms, BYTES_PER_WORD) n_bytes_for_n_neurons = n_words_for_n_neurons * BYTES_PER_WORD var_bytes = ( (self._N_BYTES_PER_RATE + self._N_BYTES_PER_SIZE + diff --git a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector_supports_views_on_machine.py b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector_supports_views_on_machine.py index 5fc7dd8a1a..542776deaa 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector_supports_views_on_machine.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector_supports_views_on_machine.py @@ -28,7 +28,7 @@ def get_view_lo_hi(self, indexes): :param list(int) indexes: the indexes array of a PopulationView :return: The low and high index values of the PopulationView - :rtype: uint, uint + :rtype: tuple(int, int) """ view_lo = indexes[0] view_hi = indexes[-1] diff --git a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py index a38dfbdace..4e69097e6d 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py @@ -46,9 +46,10 @@ def __init__( safe=True, callback=None, verbose=False): """ :param str index_expression: - the right-hand side of a valid python expression for - probability, involving the indices of the pre and post populations, - that can be parsed by eval(), that computes a probability dist. + the right-hand side of a valid Python expression for + probability, involving the indices of the pre- and + post-populations, that can be parsed by eval(), that computes a + probability distribution. :param bool allow_self_connections: if the connector is used to connect a Population to itself, this flag determines whether a neuron is allowed to connect to itself, @@ -178,9 +179,9 @@ def allow_self_connections(self, new_value): @property def index_expression(self): - """ The right-hand side of a valid python expression for probability,\ - involving the indices of the pre and post populations, that can\ - be parsed by eval(), that computes a probability dist. + """ The right-hand side of a valid Python expression for probability,\ + involving the indices of the pre- and post-populations, that can\ + be parsed by eval(), that computes a probability distribution. :rtype: str """ diff --git a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py index 668e3d5ca9..a5f9918e25 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py @@ -46,6 +46,15 @@ class KernelConnector(AbstractGenerateConnectorOnMachine): Should these include `allow_self_connections` and `with_replacement`? """ + __slots__ = ( + "_kernel_w", "_kernel_h", "_hlf_k_w", "_hlf_k_h", + "_pre_w", "_pre_h", "_post_w", "_post_h", + "_pre_start_w", "_pre_start_h", "_post_start_w", "_post_start_h", + "_pre_step_w", "_pre_step_h", "_post_step_w", "_post_step_h", + "_krn_weights", "_krn_delays", "_shape_pre", "_shape_post", + "_shape_common", "_common_w", "_common_h", "_post_as_pre") + + __KERNEL_ARRAY_TYPES = (numpy.ndarray, ConvolutionKernel) def __init__( self, shape_pre, shape_post, shape_kernel, weight_kernel, @@ -177,13 +186,11 @@ def __post_as_pre(self, post_vertex_slice): :param ~pacman.model.graphs.common.Slice post_vertex_slice: :rtype: tuple(~numpy.ndarray, ~numpy.ndarray) """ - # TODO: When slices become hashable, update this code to use them - # directly as the cache index - if str(post_vertex_slice) not in self._post_as_pre: + if post_vertex_slice not in self._post_as_pre: post_r, post_c = self.__to_post_coords(post_vertex_slice) - self._post_as_pre[str(post_vertex_slice)] = \ + self._post_as_pre[post_vertex_slice] = \ self.__map_to_pre_coords(post_r, post_c) - return self._post_as_pre[str(post_vertex_slice)] + return self._post_as_pre[post_vertex_slice] def __pre_as_post(self, pre_r, pre_c): """ Write pre coords as post coords. @@ -212,8 +219,8 @@ def __get_kernel_vals(self, vals): return numpy.array(vals.next(krn_size)).reshape(krn_shape) elif numpy.isscalar(vals): return vals * numpy.ones(krn_shape) - elif ((isinstance(vals, numpy.ndarray) or - isinstance(vals, ConvolutionKernel)) and + elif ( + isinstance(vals, self.__KERNEL_ARRAY_TYPES) and vals.shape[HEIGHT] == self._kernel_h and vals.shape[WIDTH] == self._kernel_w): return vals.view(ConvolutionKernel) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py index b1bbcfbbe5..77b07d6403 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py @@ -109,8 +109,7 @@ def create_synaptic_block( def __repr__(self): return "OneToOneConnector()" - def _get_pre_post_limits( - self, pre_slice, post_slice, synapse_info): + def _get_pre_post_limits(self, pre_slice, post_slice, synapse_info): """ :param ~pacman.model.graphs.common.Slice pre_slice: :param ~pacman.model.graphs.common.Slice post_slice: diff --git a/spynnaker/pyNN/models/neural_projections/synapse_information.py b/spynnaker/pyNN/models/neural_projections/synapse_information.py index e95ab89ca5..500cc32584 100644 --- a/spynnaker/pyNN/models/neural_projections/synapse_information.py +++ b/spynnaker/pyNN/models/neural_projections/synapse_information.py @@ -47,8 +47,8 @@ def __init__(self, connector, pre_population, post_population, The population sending spikes to the synapse :param PyNNPopulationCommon post_population: The population hosting the synapse - :param bool prepop_is_view: Whether the prepopulation is a view - :param bool postpop_is_view: Whether the postpopulation is a view + :param bool prepop_is_view: Whether the pre-population is a view + :param bool postpop_is_view: Whether the post-population is a view :param rng: Seeded random number generator :type rng: ~pyNN.random.NumpyRNG or None :param AbstractSynapseDynamics synapse_dynamics: @@ -96,7 +96,7 @@ def post_population(self): @property def n_pre_neurons(self): - """ The number of neurons in the prepopulation + """ The number of neurons in the pre-population :rtype: int """ @@ -104,7 +104,7 @@ def n_pre_neurons(self): @property def n_post_neurons(self): - """ The number of neurons in the postpopulation + """ The number of neurons in the post-population :rtype: int """ @@ -112,7 +112,7 @@ def n_post_neurons(self): @property def prepop_is_view(self): - """ Whether the prepopulation is a view + """ Whether the pre-population is a view :rtype: bool """ @@ -120,7 +120,7 @@ def prepop_is_view(self): @property def postpop_is_view(self): - """ Whether the postpopulation is a view + """ Whether the post-population is a view :rtype: bool """ diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index 846b401a10..5be782f0ce 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -285,6 +285,7 @@ def get_cpu_usage_for_atoms(self, vertex_slice): def get_dtcm_usage_for_atoms(self, vertex_slice): """ :param ~pacman.model.graphs.common.Slice vertex_slice: + :rtype: int """ return ( _NEURON_BASE_DTCM_USAGE_IN_BYTES + @@ -298,6 +299,7 @@ def _get_sdram_usage_for_neuron_params(self, vertex_slice): :param ~pacman.model.graphs.common.Slice vertex_slice: the slice of atoms. :return: The SDRAM required for the neuron region + :rtype: int """ return ( self._BYTES_TILL_START_OF_GLOBAL_PARAMETERS + @@ -305,7 +307,14 @@ def _get_sdram_usage_for_neuron_params(self, vertex_slice): def _get_sdram_usage_for_atoms( self, vertex_slice, graph, machine_time_step): - sdram_requirement = ( + """ + :param ~pacman.model.graphs.common.Slice vertex_slice: + :param ~.ApplicationGraph graph: + :param int machine_time_step: + :return: number of bytes + :rtype: int + """ + return ( SYSTEM_BYTES_REQUIREMENT + self._get_sdram_usage_for_neuron_params(vertex_slice) + self._neuron_recorder.get_static_sdram_usage(vertex_slice) + @@ -314,10 +323,9 @@ def _get_sdram_usage_for_atoms( self.__synapse_manager.get_sdram_usage_in_bytes( vertex_slice, machine_time_step, graph, self) + get_profile_region_size(self.__n_profile_samples) + - get_estimated_sdram_for_bit_field_region(graph, self) + + self.__estimate_sdram_for_bit_field_region(graph) + get_estimated_sdram_for_key_region(graph, self) + exact_sdram_for_bit_field_builder_region()) - return sdram_requirement def _reserve_memory_regions( self, spec, vertex_slice, vertex, machine_graph, n_key_map): @@ -330,7 +338,6 @@ def _reserve_memory_regions( :param ~.MachineVertex vertex: this vertex :param ~.MachineGraph machine_graph: machine graph :param ~.AbstractMachinePartitionNKeysMap n_key_map: nkey map - :return: None """ spec.comment("\nReserving memory space for data regions:\n\n") @@ -363,11 +370,10 @@ def _reserve_memory_regions( def _reserve_neuron_params_data_region(self, spec, vertex_slice): """ Reserve the neuron parameter data region. - :param ~data_specification.DataSpecificationGenerator spec: + :param ~.DataSpecificationGenerator spec: the spec to write the DSG region to :param ~pacman.model.graphs.common.Slice vertex_slice: the slice of atoms from the application vertex - :return: None """ params_size = self._get_sdram_usage_for_neuron_params(vertex_slice) spec.reserve_memory_region( @@ -376,6 +382,12 @@ def _reserve_neuron_params_data_region(self, spec, vertex_slice): @staticmethod def __copy_ranged_dict(source, merge=None, merge_keys=None): + """ + :param SpynnakerRangeDictionary source: + :param SpynnakerRangeDictionary merge: + :param set merge_keys: + :rtype: SpynnakerRangeDictionary + """ target = SpynnakerRangeDictionary(len(source)) for key in source.keys(): copy_list = SpynnakerRangedList(len(source)) @@ -393,7 +405,14 @@ def __copy_ranged_dict(source, merge=None, merge_keys=None): def _write_neuron_parameters( self, spec, key, vertex_slice, machine_time_step, time_scale_factor): - + """ + :param ~.DataSpecificationGenerator spec: + :param key: + :type key: int or None + :param ~pacman.model.graphs.common.Slice vertex_slice: + :param int machine_time_step: + :param int time_scale_factor: + """ # If resetting, reset any state variables that need to be reset if (self.__has_reset_last and self.__initial_state_variables is not None): @@ -466,6 +485,11 @@ def _write_neuron_parameters( def regenerate_data_specification( self, spec, placement, machine_time_step, time_scale_factor, routing_info): + """ + :param int machine_time_step: (injected) + :param int time_scale_factor: (injected) + :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected) + """ # pylint: disable=too-many-arguments, arguments-differ vertex_slice = placement.vertex.vertex_slice @@ -597,7 +621,6 @@ def generate_data_specification( @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): - # Split binary name into title and extension binary_title, binary_extension = os.path.splitext( self.__neuron_impl.binary_name) @@ -684,6 +707,11 @@ def initialize_parameters(self): return self.__pynn_model.default_initial_values.keys() def _get_parameter(self, variable): + """ + :param str variable: + :rtype: str + :raises KeyError: If the param with that name doesn't exist + """ if variable.endswith("_init"): # method called with "V_init" key = variable[:-5] @@ -754,7 +782,6 @@ def set_value(self, key, value): @overrides(AbstractReadParametersBeforeSet.read_parameters_from_machine) def read_parameters_from_machine( self, transceiver, placement, vertex_slice): - # locate SDRAM address to where the neuron parameters are stored neuron_region_sdram_address = locate_memory_region_for_placement( placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value, @@ -789,6 +816,9 @@ def weight_scale(self): @property def ring_buffer_sigma(self): + """ + :rtype: float or None + """ return self.__synapse_manager.ring_buffer_sigma @ring_buffer_sigma.setter @@ -800,6 +830,9 @@ def reset_ring_buffer_shifts(self): @property def spikes_per_second(self): + """ + :rtype: float or None + """ return self.__synapse_manager.spikes_per_second @spikes_per_second.setter @@ -926,6 +959,11 @@ def describe(self): return context def get_synapse_id_by_target(self, target): + """ Get the ID of a synapse given the name + + :param str target: The name of the synapse + :rtype: int + """ return self.__neuron_impl.get_synapse_id_by_target(target) def __str__(self): @@ -953,35 +991,33 @@ def reset_to_first_timestep(self): self.__change_requires_data_generation = True self.__change_requires_neuron_parameters_reload = False + def __estimate_sdram_for_bit_field_region(self, app_graph): + """ Estimates the SDRAM for the bit field region of this vertex -def get_estimated_sdram_for_bit_field_region(app_graph, vertex): - """ Estimates the SDRAM for the bit field region + :param ~.ApplicationGraph app_graph: the app graph + :return: the estimated number of bytes used by the bit field region + :rtype: int + """ + return sum( + self.__estimate_sdram_for_edge_bit_fields(incoming_edge) + for incoming_edge in app_graph.get_edges_ending_at_vertex(self) + if isinstance(incoming_edge, ProjectionApplicationEdge)) - :param ~.ApplicationGraph app_graph: the app graph - :param ~.ApplicationVertex vertex: app vertex - :return: the estimated number of bytes used by the bit field region - :rtype: int - """ - sdram = 0 - for incoming_edge in app_graph.get_edges_ending_at_vertex(vertex): - if isinstance(incoming_edge, ProjectionApplicationEdge): - edge_pre_vertex = incoming_edge.pre_vertex - max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex) - if incoming_edge.pre_vertex.n_atoms < max_atoms: - max_atoms = incoming_edge.pre_vertex.n_atoms - - # Get the number of likely vertices - n_machine_vertices = ceildiv( - incoming_edge.pre_vertex.n_atoms, max_atoms) - n_atoms_per_machine_vertex = ceildiv( - incoming_edge.pre_vertex.n_atoms, n_machine_vertices) - if isinstance(edge_pre_vertex, DelayExtensionVertex): - n_atoms_per_machine_vertex *= \ - edge_pre_vertex.n_delay_stages - n_words_for_atoms = ceildiv( - n_atoms_per_machine_vertex, BITS_PER_WORD) - sdram += ( - (ELEMENTS_USED_IN_EACH_BIT_FIELD + ( - n_words_for_atoms * n_machine_vertices)) * - BYTES_PER_WORD) - return sdram + @staticmethod + def __estimate_sdram_for_edge_bit_fields(edge): + """ + :param ProjectionApplicationEdge edge: + :rtype: int + """ + n_atoms = edge.pre_vertex.n_atoms + max_atoms = min( + determine_max_atoms_for_vertex(edge.pre_vertex), n_atoms) + + # Get the number of likely vertices + n_machine_vertices = ceildiv(n_atoms, max_atoms) + n_atoms_per_machine_vertex = ceildiv(n_atoms, n_machine_vertices) + if isinstance(edge.pre_vertex, DelayExtensionVertex): + n_atoms_per_machine_vertex *= edge.pre_vertex.n_delay_stages + n_words_for_atoms = ceildiv(n_atoms_per_machine_vertex, BITS_PER_WORD) + return BYTES_PER_WORD * (ELEMENTS_USED_IN_EACH_BIT_FIELD + ( + n_words_for_atoms * n_machine_vertices)) diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py index f69a8b131b..f143cb3956 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py @@ -38,15 +38,26 @@ def __init__(self, model): @property def _model(self): + """ + :rtype: AbstractNeuronImpl + """ return self.__model @classmethod def set_model_max_atoms_per_core(cls, n_atoms=DEFAULT_MAX_ATOMS_PER_CORE): + """ Set the maximum number of atoms per core for this model. + + :param int n_atoms: The new maximum + """ super(AbstractPyNNNeuronModel, cls).set_model_max_atoms_per_core( n_atoms) @classmethod def get_max_atoms_per_core(cls): + """ Get the maximum number of atoms per core for this model. + + :rtype: int + """ if cls not in super(AbstractPyNNNeuronModel, cls)._max_atoms_per_core: return DEFAULT_MAX_ATOMS_PER_CORE return super(AbstractPyNNNeuronModel, cls).get_max_atoms_per_core() @@ -56,6 +67,11 @@ def get_max_atoms_per_core(cls): def create_vertex( self, n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size): + """ + :param float spikes_per_second: + :param float ring_buffer_sigma: + :param int incoming_spike_buffer_size: + """ # pylint: disable=arguments-differ max_atoms = self.get_max_atoms_per_core() return AbstractPopulationVertex( diff --git a/spynnaker/pyNN/models/neuron/master_pop_table.py b/spynnaker/pyNN/models/neuron/master_pop_table.py index cd1cb5e930..84ce2033a1 100644 --- a/spynnaker/pyNN/models/neuron/master_pop_table.py +++ b/spynnaker/pyNN/models/neuron/master_pop_table.py @@ -63,6 +63,11 @@ def __init__(self, routing_key, mask): self.__addresses_and_row_lengths = list() def append(self, address, row_length, is_single): + """ + :param int address: + :param int row_length: + :param bool is_single: + """ index = len(self.__addresses_and_row_lengths) self.__addresses_and_row_lengths.append( (address, row_length, is_single)) @@ -88,7 +93,8 @@ def mask(self): def addresses_and_row_lengths(self): """ :return: the memory address that this master pop entry points at - (synaptic matrix) + (synaptic matrix), the length of the row, and whether the entry + is single. :rtype: list(tuple(int,int,bool)) """ return self.__addresses_and_row_lengths @@ -362,9 +368,9 @@ def _locate_entry(entries, key): :param ~numpy.ndarray entries: :param int key: the key to search the master pop table for a given entry - :return: the entry for this given key; + :return: the entry for this given key if one exists; dtype has keys: ``key``, ``mask``, ``start``, ``count`` - :rtype: ~numpy.ndarray + :rtype: ~numpy.ndarray or None """ imin = 0 imax = len(entries) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/abstract_neuron_model.py b/spynnaker/pyNN/models/neuron/neuron_models/abstract_neuron_model.py index 0a2e7317d9..71936c168d 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/abstract_neuron_model.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/abstract_neuron_model.py @@ -17,9 +17,9 @@ from six import with_metaclass from spinn_utilities.abstract_base import AbstractBase from spinn_utilities.overrides import overrides +from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spynnaker.pyNN.models.neuron.implementations import ( AbstractStandardNeuronComponent) -from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spynnaker.pyNN.utilities.struct import Struct diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py index 1651034c01..00aa32619f 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py @@ -108,19 +108,13 @@ def is_same_as(self, timing_dependence): (self.__tau_y == timing_dependence.tau_y)) @property + @overrides(AbstractTimingDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "pfister_triplet" @property + @overrides(AbstractTimingDependence.pre_trace_n_bytes) def pre_trace_n_bytes(self): - """ The number of bytes used by the pre-trace of the rule per neuron - - :rtype: int - """ # Triplet rule trace entries consists of two 16-bit traces - R1 and R2 return BYTES_PER_WORD @@ -132,16 +126,12 @@ def get_parameters_sdram_usage_in_bytes(self): return lut_array_words * BYTES_PER_WORD @property + @overrides(AbstractTimingDependence.n_weight_terms) def n_weight_terms(self): - """ The number of weight terms expected by this timing rule - - :rtype: int - """ return 2 @overrides(AbstractTimingDependence.write_parameters) def write_parameters(self, spec, machine_time_step, weight_scales): - # Write lookup tables spec.write_array(self.__tau_plus_data) spec.write_array(self.__tau_minus_data) @@ -149,11 +139,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales): spec.write_array(self.__tau_y_data) @property + @overrides(AbstractTimingDependence.synaptic_structure) def synaptic_structure(self): - """ Get the synaptic structure of the plastic part of the rows - - :rtype: AbstractSynapseStructure - """ return self.__synapse_structure @overrides(AbstractTimingDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py index 149555c46e..add3beb182 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py @@ -48,6 +48,13 @@ def __init__( mean_pre_window=default_parameters['mean_pre_window'], mean_post_window=default_parameters['mean_post_window'], dual_fsm=default_parameters['dual_fsm']): + """ + :param int accumulator_depression: + :param int accumulator_potentiation: + :param float mean_pre_window: + :param float mean_post_window: + :param bool dual_fsm: + """ # pylint: disable=too-many-arguments self.__accumulator_depression_plus_one = accumulator_depression + 1 self.__accumulator_potentiation_minus_one = \ @@ -73,21 +80,15 @@ def is_same_as(self, timing_dependence): timing_dependence.mean_post_window)) @property + @overrides(AbstractTimingDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ if self.__dual_fsm: return "recurrent_dual_fsm" return "recurrent_pre_stochastic" @property + @overrides(AbstractTimingDependence.pre_trace_n_bytes) def pre_trace_n_bytes(self): - """ The number of bytes used by the pre-trace of the rule per neuron - - :rtype: int - """ # When using the separate FSMs, pre-trace contains window length, # otherwise it's in the synapse return BYTES_PER_SHORT if self.__dual_fsm else 0 @@ -100,16 +101,12 @@ def get_parameters_sdram_usage_in_bytes(self): 2 * STDP_FIXED_POINT_ONE * BYTES_PER_SHORT) @property + @overrides(AbstractTimingDependence.n_weight_terms) def n_weight_terms(self): - """ The number of weight terms expected by this timing rule - - :rtype: int - """ return 1 @overrides(AbstractTimingDependence.write_parameters) def write_parameters(self, spec, machine_time_step, weight_scales): - # Write parameters spec.write_value(data=self.__accumulator_depression_plus_one, data_type=DataType.INT32) @@ -140,11 +137,8 @@ def _write_exp_dist_lut(spec, mean): inv_cdf.astype(numpy.uint16), data_type=DataType.UINT16) @property + @overrides(AbstractTimingDependence.synaptic_structure) def synaptic_structure(self): - """ Get the synaptic structure of the plastic part of the rows - - :rtype: AbstractSynapseStructure - """ return self.__synapse_structure @overrides(AbstractTimingDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py index 35673a8729..fd0f58afc1 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py @@ -76,19 +76,13 @@ def is_same_as(self, timing_dependence): self.__tau_minus == timing_dependence.tau_minus) @property + @overrides(AbstractTimingDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "nearest_pair" @property + @overrides(AbstractTimingDependence.pre_trace_n_bytes) def pre_trace_n_bytes(self): - """ The number of bytes used by the pre-trace of the rule per neuron - - :rtype: int - """ # Pair rule requires no pre-synaptic trace when only the nearest # Neighbours are considered and, a single 16-bit R1 trace return 0 @@ -99,11 +93,8 @@ def get_parameters_sdram_usage_in_bytes(self): len(self.__tau_minus_data)) @property + @overrides(AbstractTimingDependence.n_weight_terms) def n_weight_terms(self): - """ The number of weight terms expected by this timing rule - - :rtype: int - """ return 1 @overrides(AbstractTimingDependence.write_parameters) @@ -114,11 +105,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales): spec.write_array(self.__tau_minus_data) @property + @overrides(AbstractTimingDependence.synaptic_structure) def synaptic_structure(self): - """ Get the synaptic structure of the plastic part of the rows - - :rtype: AbstractSynapseStructure - """ return self.__synapse_structure @overrides(AbstractTimingDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py index 89e20f045e..b1671c2020 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py @@ -24,7 +24,8 @@ class TimingDependenceSpikePair(AbstractTimingDependence): - """ A basic timing dependence STDP rule. + """ A basic timing dependence STDP rule where relevance decays \ + exponentially. """ __slots__ = [ "__synapse_structure", @@ -73,19 +74,13 @@ def is_same_as(self, timing_dependence): self.__tau_minus == timing_dependence.tau_minus) @property + @overrides(AbstractTimingDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "pair" @property + @overrides(AbstractTimingDependence.pre_trace_n_bytes) def pre_trace_n_bytes(self): - """ The number of bytes used by the pre-trace of the rule per neuron - - :rtype: int - """ # Pair rule requires no pre-synaptic trace when only the nearest # Neighbours are considered and, a single 16-bit R1 trace return BYTES_PER_SHORT @@ -96,26 +91,19 @@ def get_parameters_sdram_usage_in_bytes(self): len(self.__tau_minus_data)) @property + @overrides(AbstractTimingDependence.n_weight_terms) def n_weight_terms(self): - """ The number of weight terms expected by this timing rule - - :rtype: int - """ return 1 @overrides(AbstractTimingDependence.write_parameters) def write_parameters(self, spec, machine_time_step, weight_scales): - # Write lookup tables spec.write_array(self.__tau_plus_data) spec.write_array(self.__tau_minus_data) @property + @overrides(AbstractTimingDependence.synaptic_structure) def synaptic_structure(self): - """ Get the synaptic structure of the plastic part of the rows - - :rtype: AbstractSynapseStructure - """ return self.__synapse_structure @overrides(AbstractTimingDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py index de788709fd..a5d7efb0e8 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py @@ -75,19 +75,13 @@ def is_same_as(self, timing_dependence): self.__alpha == timing_dependence.alpha) @property + @overrides(AbstractTimingDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "vogels_2011" @property + @overrides(AbstractTimingDependence.pre_trace_n_bytes) def pre_trace_n_bytes(self): - """ The number of bytes used by the pre-trace of the rule per neuron - - :rtype: int - """ # Trace entries consist of a single 16-bit number return BYTES_PER_SHORT @@ -96,16 +90,12 @@ def get_parameters_sdram_usage_in_bytes(self): return BYTES_PER_WORD + BYTES_PER_WORD * len(self.__tau_data) @property + @overrides(AbstractTimingDependence.n_weight_terms) def n_weight_terms(self): - """ The number of weight terms expected by this timing rule - - :rtype: int - """ return 1 @overrides(AbstractTimingDependence.write_parameters) def write_parameters(self, spec, machine_time_step, weight_scales): - # Write alpha to spec fixed_point_alpha = float_to_fixed(self.__alpha) spec.write_value(data=fixed_point_alpha, data_type=DataType.INT32) @@ -114,11 +104,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales): spec.write_array(self.__tau_data) @property + @overrides(AbstractTimingDependence.synaptic_structure) def synaptic_structure(self): - """ Get the synaptic structure of the plastic part of the rows - - :rtype: AbstractSynapseStructure - """ return self.__synapse_structure @overrides(AbstractTimingDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py index 24099adaf4..08cf9ea586 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py @@ -68,11 +68,8 @@ def is_same_as(self, weight_dependence): (self.A_minus == weight_dependence.A_minus)) @property + @overrides(AbstractWeightDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "additive" @overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes) @@ -106,12 +103,8 @@ def write_parameters( data_type=DataType.INT32) @property + @overrides(AbstractWeightDependence.weight_maximum) def weight_maximum(self): - """ The maximum weight that will ever be set in a synapse as a result\ - of this rule - - :rtype: float - """ return self.__w_max @overrides(AbstractWeightDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py index e2a112411b..23322ffca7 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py @@ -98,11 +98,8 @@ def is_same_as(self, weight_dependence): (self.__a3_minus == weight_dependence.A3_minus)) @property + @overrides(AbstractWeightDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "additive" @overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes) @@ -110,16 +107,14 @@ def get_parameters_sdram_usage_in_bytes( self, n_synapse_types, n_weight_terms): if n_weight_terms != 2: raise NotImplementedError( - "Additive weight dependence only supports one or two terms") + "Additive weight dependence only supports two terms") return _SPACE_PER_SYNAPSE_TYPE * n_synapse_types @overrides(AbstractWeightDependence.write_parameters) def write_parameters( self, spec, machine_time_step, weight_scales, n_weight_terms): - # Loop through each synapse type's weight scale for w in weight_scales: - # Scale the weights spec.write_value( data=int(round(self.__w_min * w)), data_type=DataType.INT32) @@ -143,12 +138,8 @@ def write_parameters( data_type=DataType.INT32) @property + @overrides(AbstractWeightDependence.weight_maximum) def weight_maximum(self): - """ The maximum weight that will ever be set in a synapse as a result\ - of this rule - - :rtype: float - """ return self.__w_max @overrides(AbstractWeightDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py index 5b5ccce85e..3aee0581c2 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py @@ -67,11 +67,8 @@ def is_same_as(self, weight_dependence): (self.A_minus == weight_dependence.A_minus)) @property + @overrides(AbstractWeightDependence.vertex_executable_suffix) def vertex_executable_suffix(self): - """ The suffix to be appended to the vertex executable for this rule - - :rtype: str - """ return "multiplicative" @overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes) @@ -103,12 +100,8 @@ def write_parameters( data=int(round(self.A_minus * w)), data_type=DataType.INT32) @property + @overrides(AbstractWeightDependence.weight_maximum) def weight_maximum(self): - """ The maximum weight that will ever be set in a synapse as a result\ - of this rule - - :rtype: float - """ return self.__w_max @overrides(AbstractWeightDependence.get_parameter_names) diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index 30f6f79aab..89d60a4e07 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -37,6 +37,8 @@ class PopulationMachineVertex( ProvidesProvenanceDataFromMachineImpl, AbstractRecordable, AbstractHasProfileData, AbstractSupportsBitFieldGeneration, AbstractSupportsBitFieldRoutingCompression): + """ A machine vertex that implements a neural population. + """ __slots__ = [ "__recorded_region_ids", diff --git a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py index e30b6fe8e4..7eb543f7c0 100644 --- a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py +++ b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py @@ -15,9 +15,9 @@ import numpy from spinn_utilities.overrides import overrides -from .abstract_formation import AbstractFormation from data_specification.enums.data_type import DataType from spinn_front_end_common.utilities.constants import BYTES_PER_WORD +from .abstract_formation import AbstractFormation # 6 32-bit words (grid_x, grid_y, grid_x_recip, grid_y_recep, ff_prob_size, # lat_prob_size) @@ -63,10 +63,10 @@ def __init__( self.__sigma_form_lateral = sigma_form_lateral self.__ff_distance_probabilities = \ - self.generate_distance_probability_array( + self._generate_distance_probability_array( self.__p_form_forward, self.__sigma_form_forward) self.__lat_distance_probabilities = \ - self.generate_distance_probability_array( + self._generate_distance_probability_array( self.__p_form_lateral, self.__sigma_form_lateral) @property @@ -80,7 +80,7 @@ def get_parameters_sdram_usage_in_bytes(self): len(self.__ff_distance_probabilities) * 2 + len(self.__lat_distance_probabilities) * 2) - def generate_distance_probability_array(self, probability, sigma): + def _generate_distance_probability_array(self, probability, sigma): """ Generate the exponentially decaying probability LUTs. :param float probability: peak probability diff --git a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py index e2b03a3b39..15864a00b1 100644 --- a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py +++ b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py @@ -26,7 +26,7 @@ class LastNeuronSelection(AbstractPartnerSelection): def __init__(self, spike_buffer_size=64): """ - :param spike_buffer_size: The size of the buffer for holding spikes + :param int spike_buffer_size: The size of the buffer for holding spikes """ self.__spike_buffer_size = spike_buffer_size diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py index 0be672be43..abfa0cf52f 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py @@ -86,6 +86,8 @@ def s_max(self): @abstractproperty def seed(self): """ The seed to control the randomness + + :rtype: int """ @abstractproperty diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index f55497817e..895c6590a1 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -29,6 +29,7 @@ # How large are the time-stamps stored with each event TIME_STAMP_BYTES = BYTES_PER_WORD +_HALF_WORDS_PER_WORD = 2 class SynapseDynamicsSTDP( @@ -284,25 +285,20 @@ def _n_header_bytes(self): def __get_n_connections(self, n_connections, check_length_padded=True): """ :param int n_connections: - :rtype: int :param bool check_length_padded: - :rtype: bool + :rtype: int """ synapse_structure = self.__timing_dependence.synaptic_structure if self.__pad_to_length is not None and check_length_padded: n_connections = max(n_connections, self.__pad_to_length) if n_connections == 0: return 0 - # 2 == two half words per word - fp_size_words = ( - n_connections // 2 if n_connections % 2 == 0 - else (n_connections + 1) // 2) - pp_size_bytes = ( - self._n_header_bytes + - (synapse_structure.get_n_half_words_per_connection() * - BYTES_PER_SHORT * n_connections)) - pp_size_words = ceildiv(pp_size_bytes, BYTES_PER_WORD) + fp_size_words = ceildiv(n_connections, _HALF_WORDS_PER_WORD) + pp_size_bytes = self._n_header_bytes + ( + synapse_structure.get_n_half_words_per_connection() * + BYTES_PER_SHORT * n_connections) + pp_size_words = ceildiv(pp_size_bytes, BYTES_PER_WORD) return fp_size_words + pp_size_words def get_n_words_for_plastic_connections(self, n_connections): diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py index 2d75e0536a..77b8f5c109 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py @@ -103,7 +103,7 @@ def __init__( :param float initial_weight: Initial weight assigned to a newly formed connection :param initial_delay: Delay assigned to a newly formed connection - :type initial_delay: int or (int, int) + :type initial_delay: int or float or tuple(int or float, int or float) :param int s_max: Maximum fan-in per target layer neuron :param int seed: seed the random number generators """ @@ -154,7 +154,7 @@ def p_rew(self): """ The period of rewiring. :return: The period of rewiring - :rtype: int + :rtype: float """ return self.__p_rew @@ -225,6 +225,8 @@ def __get_structural_edges(self, app_graph, app_vertex): :param ~.ApplicationGraph app_graph: :param ~.ApplicationVertex app_vertex: :rtype: list(tuple(ProjectionApplicationEdge, SynapseInformation)) + :raises SynapticConfigurationException: + if there are two structurally-plastic projections on an edge """ structural_edges = list() for app_edge in app_graph.get_edges_ending_at_vertex(app_vertex): @@ -508,41 +510,64 @@ def is_same_as(self, synapse_dynamics): @property def initial_weight(self): + """ Initial weight assigned to a newly formed connection + + :rtype: float + """ return self.__initial_weight @property def initial_delay(self): + """ Delay assigned to a newly formed connection + + :rtype: int or float or tuple(int or float, int or float) + """ return self.__initial_delay @property def f_rew(self): + """ Frequency of rewiring (Hz) + + :rtype: float + """ return self.__f_rew @property def s_max(self): + """ Maximum fan-in per target layer neuron + + :rtype: int + """ return self.__s_max @property def seed(self): + """ seed for the random number generators + + :rtype: int + """ return self.__seed @property def partner_selection(self): - """ + """ The partner selection rule + :rtype: AbstractPartnerSelection """ return self.__partner_selection @property def formation(self): - """ + """ The formation rule + :rtype: AbstractFormation """ return self.__formation @property def elimination(self): - """ + """ The elimination rule + :rtype: AbstractElimination """ return self.__elimination diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py index 80fbaae48c..b4311afc5a 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py @@ -54,7 +54,7 @@ def __init__( a fixed delay value, or a tuple of two values means the delay will be chosen at random from a uniform distribution between the given values - :type initial_delay: float or (float, float) + :type initial_delay: int or float or tuple(int or float, int or float) :param int s_max: Maximum fan-in per target layer neuron :param int seed: seed the random number generators :param float weight: The weight of connections formed by the connector diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py index dd98b0315e..d0739801d5 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py @@ -61,7 +61,7 @@ def __init__( a fixed delay value, or a tuple of two values means the delay will be chosen at random from a uniform distribution between the given values - :type initial_delay: float or tuple(float, float) + :type initial_delay: int or float or tuple(int or float, int or float) :param int s_max: Maximum fan-in per target layer neuron :param int seed: seed the random number generators :param float weight: The weight of connections formed by the connector diff --git a/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py b/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py index 3e7a73cb27..c3cd1f94b2 100644 --- a/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py +++ b/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py @@ -42,6 +42,8 @@ class SynapseTypeSEMD(AbstractSynapseType): + """ Synaptic type for a spiking elementary motion detector. + """ __slots__ = [ "__tau_syn_E", "__tau_syn_E2", @@ -141,7 +143,6 @@ def init(x): @overrides(AbstractSynapseType.update_values) def update_values(self, values, parameters, state_variables): - # Read the data (_decay_E, _init_E, isyn_exc, _decay_E2, _init_E2, isyn_exc2, _decay_I, _init_I, isyn_inh, _multiplicator, exc2_old) = values diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index faecca23e2..4cf4264317 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -127,6 +127,7 @@ def __init__(self, n_synapse_types, ring_buffer_sigma, spikes_per_second, self.__n_synapse_types = n_synapse_types self.__ring_buffer_sigma = ring_buffer_sigma self.__spikes_per_second = spikes_per_second + # Overridable (for testing only) region IDs self._synapse_params_region = \ POPULATION_BASED_REGIONS.SYNAPSE_PARAMS.value self._pop_table_region = \ @@ -243,6 +244,7 @@ def spikes_per_second(self, spikes_per_second): def get_maximum_delay_supported_in_ms(self, machine_time_step): """ + :param int machine_time_step: :rtype: int or None """ return self.__synapse_io.get_maximum_delay_supported_in_ms( diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index 81df354f2b..53bd02b32d 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -487,9 +487,7 @@ def set_by_selector(self, selector, parameter, value=None): self.__vertex.set_value_by_selector(selector, key, value) def _read_parameters_before_set(self): - """ Reads parameters from the machine before "set" completes - - :return: None + """ Reads parameters from the machine before "set" completes. """ # If the tools have run before, and not reset, and the read diff --git a/spynnaker/pyNN/models/pynn_projection_common.py b/spynnaker/pyNN/models/pynn_projection_common.py index 0c770a2526..44a16dd003 100644 --- a/spynnaker/pyNN/models/pynn_projection_common.py +++ b/spynnaker/pyNN/models/pynn_projection_common.py @@ -249,8 +249,8 @@ def _find_existing_edge(self, pre_synaptic_vertex, post_synaptic_vertex): :param post_synaptic_vertex: The destination vertex of the multapse :type post_synaptic_vertex: ~pacman.model.graphs.application.ApplicationVertex - :return: None or the edge going to these vertices. - :rtype: ~.ApplicationEdge + :return: the edge going to these vertices, if one exists. + :rtype: ~.ApplicationEdge or None """ # Find edges ending at the postsynaptic vertex diff --git a/spynnaker/pyNN/models/recording_common.py b/spynnaker/pyNN/models/recording_common.py index 29e69be4ea..bfc86ad998 100644 --- a/spynnaker/pyNN/models/recording_common.py +++ b/spynnaker/pyNN/models/recording_common.py @@ -65,7 +65,6 @@ def _record(self, variable, sampling_interval=None, to_file=None, :param int sampling_interval: the interval to record them :param indexes: List of indexes to record or None for all :type indexes: list(int) or None - :return: None """ get_simulator().verify_not_running() diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index 05fd6d425f..7ba1a6b40c 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -31,9 +31,12 @@ AbstractRewritesDataSpecification) from spinn_front_end_common.abstract_models.impl import ( ProvidesKeyToAtomMappingImpl) -from spinn_front_end_common.interface.simulation import simulation_utilities -from spinn_front_end_common.interface.buffer_management import ( - recording_utilities) +from spinn_front_end_common.interface.simulation.simulation_utilities import ( + get_simulation_header_array) +from spinn_front_end_common.interface.buffer_management.recording_utilities \ + import ( + get_recording_header_size, get_recording_data_constant_size, + get_recording_header_array) from spinn_front_end_common.utilities.constants import ( SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BYTES_PER_WORD) from spinn_front_end_common.utilities.globals_variables import get_simulator @@ -49,13 +52,13 @@ LIVE_POISSON_CONTROL_PARTITION_ID, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.abstract_models import ( AbstractReadParametersBeforeSet) -from .spike_source_poisson_machine_vertex import ( - SpikeSourcePoissonMachineVertex) from spynnaker.pyNN.utilities.utility_calls import ( validate_mars_kiss_64_seed, ceildiv, round_up) from spynnaker.pyNN.utilities.struct import Struct from spynnaker.pyNN.utilities.ranged import ( SpynnakerRangeDictionary, SpynnakerRangedList) +from .spike_source_poisson_machine_vertex import ( + SpikeSourcePoissonMachineVertex) logger = logging.getLogger(__name__) @@ -154,14 +157,18 @@ def __init__( max_rate=None): """ :param int n_neurons: - :param constraints: + :param list(~pacman.model.constrants.AbstractConstraint) constraints: :param str label: :param float seed: :param int max_atoms_per_core: - :param model: - :param iterable of float rate: - :param iterable of int start: - :param iterable of int duration: + :param AbstractPyNNModel model: + :param float rate: + :param int start: + :param int duration: + :param iterable(float) rates: + :param iterable(int) starts: + :param iterable(int) durations: + :param float max_rate: """ # pylint: disable=too-many-arguments super(SpikeSourcePoissonVertex, self).__init__( @@ -446,6 +453,7 @@ def set_value(self, key, value): def _max_spikes_per_ts(self, machine_time_step): """ :param int machine_time_step: + :rtype: int or float """ ts_per_second = MICROSECONDS_PER_SECOND / float(machine_time_step) if float(self.__max_rate) / ts_per_second < \ @@ -479,8 +487,7 @@ def get_recording_sdram_usage(self, vertex_slice, machine_time_step): ) def get_resources_used_by_atoms(self, vertex_slice, machine_time_step): """ - :param ~pacman.model.graphs.common.Slice vertex_slice: - :param int machine_time_step: + :param int machine_time_step: (injected) """ # pylint: disable=arguments-differ poisson_params_sz = self.get_rates_bytes(vertex_slice) @@ -488,8 +495,8 @@ def get_resources_used_by_atoms(self, vertex_slice, machine_time_step): SYSTEM_BYTES_REQUIREMENT + SpikeSourcePoissonMachineVertex.get_provenance_data_size(0) + poisson_params_sz + - recording_utilities.get_recording_header_size(1) + - recording_utilities.get_recording_data_constant_size(1) + + get_recording_header_size(1) + + get_recording_data_constant_size(1) + get_profile_region_size(self.__n_profile_samples)) recording = self.get_recording_sdram_usage( @@ -546,11 +553,10 @@ def reserve_memory_regions(self, spec, placement): """ Reserve memory regions for Poisson source parameters and output\ buffer. - :param ~data_specification.DataSpecification spec: + :param ~data_specification.DataSpecificationGenerator spec: the data specification writer :param ~pacman.model.placements.Placement placement: the location this vertex resides on in the machine - :return: None """ spec.comment("\nReserving memory space for data regions:\n\n") @@ -565,7 +571,7 @@ def reserve_memory_regions(self, spec, placement): spec.reserve_memory_region( region=_REGIONS.SPIKE_HISTORY_REGION.value, - size=recording_utilities.get_recording_header_size(1), + size=get_recording_header_size(1), label="Recording") reserve_profile_region( @@ -577,10 +583,8 @@ def _reserve_poisson_params_rates_region(self, placement, spec): """ Allocate space for the Poisson parameters and rates regions as\ they can be reused for setters after an initial run - :param ~pacman.model.placements.Placement placement: - the location on machine for this vertex - :param ~data_specification.DataSpecification spec: the DSG writer - :return: None + :param ~.Placement placement: the location on machine for this vertex + :param ~.DataSpecificationGenerator spec: the DSG writer """ spec.reserve_memory_region( region=_REGIONS.POISSON_PARAMS_REGION.value, @@ -595,11 +599,10 @@ def _write_poisson_parameters( vertex_slice, machine_time_step, time_scale_factor): """ Generate Parameter data for Poisson spike sources - :param ~data_specification.DataSpecification spec: - the data specification writer - :param ~pacman.model.graphs.machine.MachineGraph graph: - :param ~pacman.model.placements.Placement placement: - :param ~pacman.model.routing_info.RoutingInfo routing_info: + :param ~.DataSpecificationGenerator spec: the data specification writer + :param ~.MachineGraph graph: + :param ~.Placement placement: + :param ~.RoutingInfo routing_info: :param ~pacman.model.graphs.common.Slice vertex_slice: the slice of atoms a machine vertex holds from its application vertex @@ -701,7 +704,7 @@ def _write_poisson_rates(self, spec, vertex_slice, machine_time_step, first_machine_time_step): """ Generate Rate data for Poisson spike sources - :param ~data_specification.DataSpecification spec: + :param ~.DataSpecificationGenerator spec: the data specification writer :param ~pacman.model.graphs.common.Slice vertex_slice: the slice of atoms a machine vertex holds from its application @@ -808,15 +811,15 @@ def _write_poisson_rates(self, spec, vertex_slice, machine_time_step, @staticmethod def _convert_ms_to_n_timesteps(value, machine_time_step): + """ + :param ~numpy.ndarray value: + :param int machine_time_step: + :rtype: ~numpy.ndarray + """ return numpy.round( value * (MICROSECONDS_PER_MILLISECOND / float(machine_time_step))).astype("uint32") - @staticmethod - def _convert_n_timesteps_to_ms(value, machine_time_step): - return ( - value / (MICROSECONDS_PER_MILLISECOND / float(machine_time_step))) - @overrides(AbstractSpikeRecordable.is_recording_spikes) def is_recording_spikes(self): return self.__spike_recorder.record @@ -840,10 +843,16 @@ def get_spikes_sampling_interval(self): @staticmethod def get_dtcm_usage_for_atoms(): + """ + :rtype: int + """ return 0 @staticmethod def get_cpu_usage_for_atoms(): + """ + :rtype: int + """ return 0 @inject_items({ @@ -861,11 +870,11 @@ def regenerate_data_specification( self, spec, placement, machine_time_step, time_scale_factor, routing_info, graph, first_machine_time_step): """ - :param int machine_time_step: - :param int time_scale_factor: - :param ~pacman.model.routing_info.RoutingInfo routing_info: - :param ~pacman.model.graphs.machine.MachineGraph graph: - :param int first_machine_time_step: + :param int machine_time_step: (injected) + :param int time_scale_factor: (injected) + :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected) + :param ~pacman.model.graphs.machine.MachineGraph graph: (injected) + :param int first_machine_time_step: (injected) """ # pylint: disable=too-many-arguments, arguments-differ @@ -982,12 +991,12 @@ def generate_data_specification( self, spec, placement, machine_time_step, time_scale_factor, routing_info, data_n_time_steps, graph, first_machine_time_step): """ - :param int machine_time_step: - :param int time_scale_factor: - :param ~pacman.model.routing_info.RoutingInfo routing_info: - :param int data_n_time_steps: - :param ~pacman.model.graphs.machine.MachineGraph graph: - :param int first_machine_time_step: + :param int machine_time_step: (injected) + :param int time_scale_factor: (injected) + :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected) + :param int data_n_time_steps: (injected) + :param ~pacman.model.graphs.machine.MachineGraph graph: (injected) + :param int first_machine_time_step: (injected) """ # pylint: disable=too-many-arguments, arguments-differ self.__machine_time_step = machine_time_step @@ -1000,7 +1009,7 @@ def generate_data_specification( # write setup data spec.switch_write_focus(_REGIONS.SYSTEM_REGION.value) - spec.write_array(simulation_utilities.get_simulation_header_array( + spec.write_array(get_simulation_header_array( self.get_binary_file_name(), machine_time_step, time_scale_factor)) @@ -1008,8 +1017,7 @@ def generate_data_specification( spec.switch_write_focus(_REGIONS.SPIKE_HISTORY_REGION.value) sdram = self.get_recording_sdram_usage(vertex_slice, machine_time_step) recorded_region_sizes = [sdram.get_total_sdram(data_n_time_steps)] - spec.write_array(recording_utilities.get_recording_header_array( - recorded_region_sizes)) + spec.write_array(get_recording_header_array(recorded_region_sizes)) # write parameters self._write_poisson_parameters( diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py index 23c7aef405..f02ca1c6d9 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py @@ -23,6 +23,8 @@ class DelayExtensionMachineVertex( MachineVertex, ProvidesProvenanceDataFromMachineImpl): + """ Implements long delays of spikes. + """ __slots__ = [ "__resources"] @@ -48,11 +50,13 @@ def __init__(self, resources_required, label, constraints=None, :param ~pacman.model.resources.ResourceContainer resources_required: The resources required by the vertex :param str label: The optional name of the vertex - :param iterable(AbstractConstraint) constraints: + :param constraints: The optional initial constraints of the vertex - :param ~pacman.model.graphs.application.ApplicationVertex app_vertex: + :type constraints: + iterable(~pacman.model.constraints.AbstractConstraint) + :param DelayExtensionVertex app_vertex: The application vertex that caused this machine vertex to be - created. If None, there is no such application vertex. + created. :param ~pacman.model.graphs.common.Slice vertex_slice: The slice of the application vertex that this machine vertex implements. diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py index 2f44a37ca2..1e71dd2659 100644 --- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py +++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py @@ -285,7 +285,7 @@ def generate_data_specification( def _write_setup_info(self, spec, machine_time_step, time_scale_factor): """ - :param ~data_specification.DataSpecificationGenerator spec: + :param ~.DataSpecificationGenerator spec: :param int machine_time_step: :param int time_scale_factor: """ @@ -390,24 +390,22 @@ def _get_edge_generator_size(self, synapse_info): synapse_gen = isinstance( dynamics, AbstractGenerateOnMachine) if connector_gen and synapse_gen: - return sum(( - DelayGeneratorData.BASE_SIZE, - connector.gen_delay_params_size_in_bytes( - synapse_info.delays), - connector.gen_connector_params_size_in_bytes, - )) + return ( + DelayGeneratorData.BASE_SIZE + + connector.gen_delay_params_size_in_bytes(synapse_info.delays) + + connector.gen_connector_params_size_in_bytes) return 0 def _get_size_of_generator_information(self, out_edges): """ Get the size of the generator data for all edges - :param list(.ApplicationEdge) out_edges: + :param list(~.ApplicationEdge) out_edges: :rtype: int """ - size = 0 - for out_edge in out_edges: - if isinstance(out_edge, DelayedApplicationEdge): - size += self.__size_of_edge_generator_info(out_edge) + size = sum( + self.__size_of_edge_generator_info(edge) + for edge in out_edges + if isinstance(edge, DelayedApplicationEdge)) # If there's a non-zero size, we will be generating on machine and we # should add the baseline overhead if size: @@ -417,6 +415,7 @@ def _get_size_of_generator_information(self, out_edges): def __size_of_edge_generator_info(self, edge): """ :param DelayedApplicationEdge edge: + :rtype: int """ # Get the number of likely vertices max_atoms = min( diff --git a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py index d71995b7a8..9d80087bc5 100644 --- a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py +++ b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py @@ -294,7 +294,7 @@ def add_edge(vertex, device_vertex, partition_id): :param ~pacman.model.graphs.application.ApplicationVertex vertex: the pre-vertex to connect the edge from - :param device_vertex: the post vertex to connect the edge to + :param device_vertex: the post-vertex to connect the edge to :type device_vertex: ~pacman.model.graphs.application.ApplicationVertex :param str partition_id: the partition identifier for making nets @@ -304,12 +304,21 @@ def add_edge(vertex, device_vertex, partition_id): @staticmethod def add_application_vertex(vertex): + """ + :param ~pacman.model.graphs.application.ApplicationVertex vertex: + """ get_simulator().add_application_vertex(vertex) @staticmethod def machine_time_step(): + """ + :rtype: int + """ return get_simulator().machine_time_step @staticmethod def time_scale_factor(): + """ + :rtype: int + """ return get_simulator().time_scale_factor diff --git a/spynnaker/pyNN/utilities/bit_field_utilities.py b/spynnaker/pyNN/utilities/bit_field_utilities.py index 480d3d5962..3e4528cbb4 100644 --- a/spynnaker/pyNN/utilities/bit_field_utilities.py +++ b/spynnaker/pyNN/utilities/bit_field_utilities.py @@ -18,7 +18,7 @@ import ( determine_max_atoms_for_vertex) from spinn_front_end_common.utilities.constants import BYTES_PER_WORD -from spynnaker.pyNN.utilities.utility_calls import ceildiv +from .utility_calls import ceildiv # number of elements ELEMENTS_USED_IN_EACH_BIT_FIELD = 3 # n words, key, pointer to bitfield @@ -42,14 +42,15 @@ def get_estimated_sdram_for_key_region(app_graph, vertex): - """ gets an estimate of the bitfield builder region + """ gets an estimate of the bitfield builder region size - :param ~.ApplicationGraph app_graph: the app graph - :param ~.ApplicationVertex vertex: app vertex - :return: sdram needed + :param ~pacman.model.graphs.application.ApplicationGraph app_graph: + the app graph + :param ~pacman.model.graphs.application.ApplicationVertex vertex: + app vertex + :return: SDRAM needed :rtype: int """ - # basic sdram sdram = N_KEYS_DATA_SET_IN_WORDS * BYTES_PER_WORD for in_edge in app_graph.get_edges_ending_at_vertex(vertex): @@ -91,6 +92,7 @@ def exact_sdram_for_bit_field_builder_region(): """ Gets the SDRAM requirement for the builder region :return: returns the SDRAM requirement for the builder region + :rtype: int """ return N_REGIONS_ADDRESSES * BYTES_PER_WORD @@ -100,7 +102,7 @@ def _exact_sdram_for_bit_field_key_region(machine_graph, vertex): :param ~.MachineGraph machine_graph: machine graph :param ~.MachineVertex vertex: machine vertex - :return: bytes + :return: number of bytes :rtype: int """ return ( @@ -114,16 +116,17 @@ def reserve_bit_field_regions( bit_filter_region, bit_field_key_region): """ reserves the regions for the bitfields - :param ~.DataSpecificationGenerator spec: dsg file - :param ~.MachineGraph machine_graph: machine graph - :param ~.AbstractMachinePartitionNKeysMap n_key_map: + :param ~data_specification.DataSpecificationGenerator spec: dsg file + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: + machine graph + :param ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap \ + n_key_map: map between partitions and n keys - :param ~.MachineVertex vertex: machine vertex + :param ~pacman.model.graphs.machine.MachineVertex vertex: machine vertex :param int bit_field_builder_region: region id for the builder region :param int bit_filter_region: region id for the bitfield region :param int bit_field_key_region: region id for the key map """ - # reserve the final destination for the bitfields spec.reserve_memory_region( region=bit_filter_region, @@ -152,11 +155,15 @@ def write_bitfield_init_data( structural_dynamics_region_id, has_structural_dynamics_region): """ writes the init data needed for the bitfield generator - :param ~.DataSpecificationGenerator spec: data spec writer - :param ~.MachineVertex machine_vertex: machine vertex - :param ~.MachineGraph machine_graph: machine graph - :param ~.RoutingInfo routing_info: keys - :param ~.AbstractMachinePartitionNKeysMap n_key_map: map for edge to n keys + :param ~data_specification.DataSpecificationGenerator spec: data spec writer + :param ~pacman.model.graphs.machine.MachineVertex machine_vertex: + machine vertex + :param ~pacman.model.graphs.machine.MachineGraph machine_graph: + machine graph + :param ~pacman.model.routing_info.RoutingInfo routing_info: keys + :param ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap \ + n_key_map: + map for edge to n keys :param int bit_field_builder_region: the region id for the bitfield builder :param int master_pop_region_id: the region id for the master pop table :param int synaptic_matrix_region_id: the region id for the synaptic matrix diff --git a/spynnaker/pyNN/utilities/struct.py b/spynnaker/pyNN/utilities/struct.py index 567047fb80..81bd4cf668 100644 --- a/spynnaker/pyNN/utilities/struct.py +++ b/spynnaker/pyNN/utilities/struct.py @@ -65,7 +65,8 @@ def get_size_in_whole_words(self, array_size=1): return (size_in_bytes + (BYTES_PER_WORD - 1)) // BYTES_PER_WORD def get_data(self, values, offset=0, array_size=1): - """ Get a numpy array of uint32 of data for the given values + """ Get a numpy array of uint32 of data for the given values. \ + The array will be suitable for being written to SpiNNaker. :param values: A list of values with length the same size as the number of fields diff --git a/spynnaker/pyNN/utilities/utility_calls.py b/spynnaker/pyNN/utilities/utility_calls.py index 4cf09fd99c..53b3428b41 100644 --- a/spynnaker/pyNN/utilities/utility_calls.py +++ b/spynnaker/pyNN/utilities/utility_calls.py @@ -14,7 +14,7 @@ # along with this program. If not, see . """ -utility class containing simple helper methods +Utility package containing simple helper functions. """ import math import os @@ -65,7 +65,6 @@ def convert_param_to_numpy(param, no_atoms): :return: the converted param as an array of floats :rtype: ~numpy.ndarray(float) """ - # Deal with random distributions by generating values if isinstance(param, RandomDistribution): @@ -201,6 +200,8 @@ def get_probable_maximum_selected( """ Get the likely maximum number of items that will be selected from a\ set of n_trials from a total set of n_total_trials\ with a probability of selection of selection_prob + + :rtype: float """ prob = 1.0 - (chance / float(n_total_trials)) return binom.ppf(prob, n_trials, selection_prob) @@ -209,6 +210,8 @@ def get_probable_maximum_selected( def get_probability_within_range(dist, lower, upper): """ Get the probability that a value will fall within the given range for\ a given RandomDistribution + + :rtype: float """ stats = STATS_BY_NAME[dist.name] return (stats.cdf(dist, upper) - stats.cdf(dist, lower)) @@ -217,6 +220,8 @@ def get_probability_within_range(dist, lower, upper): def get_maximum_probable_value(dist, n_items, chance=(1.0 / 100.0)): """ Get the likely maximum value of a RandomDistribution given a\ number of draws + + :rtype: float """ stats = STATS_BY_NAME[dist.name] prob = 1.0 - (chance / float(n_items)) @@ -226,6 +231,8 @@ def get_maximum_probable_value(dist, n_items, chance=(1.0 / 100.0)): def get_minimum_probable_value(dist, n_items, chance=(1.0 / 100.0)): """ Get the likely minimum value of a RandomDistribution given a\ number of draws + + :rtype: float """ stats = STATS_BY_NAME[dist.name] prob = chance / float(n_items) @@ -234,6 +241,8 @@ def get_minimum_probable_value(dist, n_items, chance=(1.0 / 100.0)): def get_mean(dist): """ Get the mean of a RandomDistribution + + :rtype: float """ stats = STATS_BY_NAME[dist.name] return stats.mean(dist) @@ -241,6 +250,8 @@ def get_mean(dist): def get_standard_deviation(dist): """ Get the standard deviation of a RandomDistribution + + :rtype: float """ stats = STATS_BY_NAME[dist.name] return stats.std(dist) @@ -248,6 +259,8 @@ def get_standard_deviation(dist): def get_variance(dist): """ Get the variance of a RandomDistribution + + :rtype: float """ stats = STATS_BY_NAME[dist.name] return stats.var(dist) @@ -257,6 +270,8 @@ def high(dist): """ Gets the high or max boundary value for this distribution Could return None + + :rtype: float or None """ stats = STATS_BY_NAME[dist.name] return stats.high(dist) @@ -266,6 +281,8 @@ def low(dist): """ Gets the high or min boundary value for this distribution Could return None + + :rtype: float or None """ stats = STATS_BY_NAME[dist.name] return stats.low(dist) @@ -293,7 +310,7 @@ def round_up(value): def get_n_bits(n_values): - """ Determine how many bits are required for the given number of values + """ Determine how many bits are required for the given number of values. :param int n_values: the number of values (starting at 0) :return: the number of bits required to express that many values @@ -303,7 +320,7 @@ def get_n_bits(n_values): return 0 if n_values == 1: return 1 - return round_up(math.log(n_values, 2)) + return (n_values - 1).bit_length() def ceildiv(x, y):