# ---LICENSE-BEGIN - DO NOT CHANGE OR MOVE THIS HEADER
# This file is part of the Neurorobotics Platform software
# Copyright (C) 2014,2015,2016,2017 Human Brain Project
# https://www.humanbrainproject.eu
#
# The Human Brain Project is a European Commission funded project
# in the frame of the Horizon2020 FET Flagship plan.
# http://ec.europa.eu/programmes/horizon2020/en/h2020-section/fet-flagships
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# ---LICENSE-END
'''
NengoControlAdapter.py
moduleauthor: krach@fzi.de
'''
from __future__ import division
from builtins import range
from past.utils import old_div
from hbp_nrp_cle.brainsim import IBrainControlAdapter
from hbp_nrp_cle.brainsim.nengo.NengoInfo import is_population, NengoPopulationInfo
from hbp_nrp_cle.brainsim.nengo import NengoBrainLoader
from hbp_nrp_cle.cle.CLEInterface import BrainRuntimeException
import nengo
import nengo_loihi
import logging
from os import path
logger = logging.getLogger(__name__)
__author__ = 'Sebastian Krach'
[docs]class NengoControlAdapter(IBrainControlAdapter):
"""
Represents a controller object for the neuronal simulator
"""
def __init__(self, nengo_simulation_state, loihi=False):
"""
Initializes the Nengo control adapter
:param sim: The simulator module
"""
self.__is_initialized = False
self._nengo_simulation_state = nengo_simulation_state
self._params = {'dt': 0.001}
self._is_loihi_simulation = loihi
[docs] def load_populations(self, populations):
"""
Load (or reload) populations into the brain
:param populations: A dictionary indexed by population names and
containing neuron indices. Neuron indices can be defined by a single integer,
list of integers or python slices. Python slices can be replaced by a
dictionary containing the 'from', 'to' and 'step' values.
"""
if populations:
raise NotImplementedError(
"The Nengo Brain Adapter currently does not support selecting populations"
" based on BIBI file attributes. You can provide named populations by"
" having the brain module declare these as attribute.")
[docs] def load_brain(self, brain_file, populations=None):
"""
Loads the neuronal network contained in the given file
:param brain_file: The path to the neuronal network file
:param populations: UNUSED
"""
extension = path.splitext(brain_file)[1]
if extension == ".py":
self._nengo_simulation_state.load_brain(brain_file)
import hbp_nrp_cle.tf_framework.config as tf_config
tf_config.brain_populations = {}
NengoBrainLoader.setup_access_to_population(
tf_config.brain_root, *self.get_populations())
else:
msg = "Neuronal network format {0} not supported".format(extension)
raise Exception(msg)
[docs] def initialize(self, **sim_params):
"""
Initializes the neuronal simulator. All additional keyword parameters are passed to
the constructor of the simulator.
:return: True if the simulator is initialized, otherwise False
"""
if not self.__is_initialized:
self._params.update(sim_params)
if self._is_loihi_simulation:
self._nengo_simulation_state.initialize(
lambda brain_root: nengo_loihi.Simulator(brain_root, **self._params))
else:
self._nengo_simulation_state.initialize(lambda brain_root: nengo.Simulator(
brain_root, **self._params))
self.__is_initialized = True
logger.info("neuronal simulator initialized")
else:
logger.warn(
"trying to initialize an already initialized controller")
return self.__is_initialized
@staticmethod
def _is_population(candidate):
"""
Determines whether the candidate is a population
:param candidate: The candidate
"""
return is_population(candidate)
@staticmethod
def _create_population_info(population, name):
"""
Creates a population info object for the given population
:param population: The population
:param name: The name of the population
"""
# Currently the Nengo Brain Adapter implementation does not provide population specific
# information. This might need to be enhanced once visualization requirements are clear.
parameters = {}
return NengoPopulationInfo(population, name, parameters)
def __find_all_populations(self, candidate, member_name, populations):
"""
Finds all populations under the given object and adds them to the list of populations
:param candidate: The object tree
:param member_name: The base member name
:param populations: The list of populations
"""
if self._is_population(candidate):
populations.append(
self._create_population_info(candidate, member_name))
elif isinstance(candidate, list):
for index, cand in enumerate(candidate):
self.__find_all_populations(
cand, '{name}[{i}]'.format(name=member_name, i=index), populations)
[docs] def get_populations(self):
"""
Gets an information about the populations currently available
:return: A list of population infos
"""
import hbp_nrp_cle.tf_framework.config as config
populations = []
for member in dir(config.brain_root):
candidate = getattr(config.brain_root, member)
self.__find_all_populations(candidate, member, populations)
return populations
@property
def is_initialized(self): # pragma: no cover
"""
Gets a value indicating whether initialize has been called
"""
return self.__is_initialized
[docs] def is_alive(self): # -> bool: # pragma: no cover
"""
Gets a status whether the neuronal simulator is still alive
When the simulator is loihi we have to avoid checking the closed
attribute because Nengo loihi has a check that throws when we instantiate
a simulator without a network attached to it. This is the case
when we check the is_alive function. Better to avoid this
check for loihi until a better solution is found.
:return: True if the simulator is alive, otherwise False
"""
return not self.is_loihi() and not self._nengo_simulation_state.simulator.closed
[docs] def run_step(self, dt): # -> None:
"""
Runs the neuronal simulator for the given amount of simulated time
:param dt: the simulated time in milliseconds
"""
try:
_sim = self._nengo_simulation_state.simulator
for _ in range(int(old_div(dt, (_sim.dt * 1000)))):
_sim.step()
except Exception as e:
raise BrainRuntimeException(str(e))
[docs] def shutdown(self): # pragma: no cover
"""
Shuts down the neuronal simulator
"""
self.__is_initialized = False
logger.info("neuronal simulator ended")
[docs] def reset(self): # pragma: no cover
"""
Resets the neuronal simulator
"""
self._nengo_simulation_state.reset_simulator()
logger.info("neuronal simulator reset")
# pylint: disable=no-self-use
[docs] def get_Timeout(self): # pragma: no cover
"""
returns The maximum amount of time (in seconds) to wait for the end of this step
"""
return 5
[docs] def is_loihi(self):
"""
Determines whether loihi is used as a backend
"""
return self._is_loihi_simulation