def build_and_connect_devices(nest_instance, devices, nest_nodes): from six import string_types # Build devices by their model (IndexedOrderedDict), # target nodes (IndexedOrderedDict), # and population (IndexedOrderedDict) for faster reading nest_devices = IndexedOrderedDict(OrderedDict( {})) # TODO: find out why it copies nest_nodes if not {} in the input for device in ensure_list(devices): dev_model = device["model"] if dev_model in NESTInputDeviceDict.keys(): build_device = \ lambda nest_instance, device, populations: \ build_and_connect_input_device(nest_instance, device, populations) elif dev_model in NESTOutputDeviceDict.keys(): build_device = \ lambda nest_instance, device, populations: \ build_and_connect_output_device(nest_instance, device, populations) else: raise ValueError( "Device model %s is neither one of available input devices:\n%s\n" "nor of output ones!:\n%s" % (dev_model, NESTInputDeviceDict.keys(), NESTOutputDeviceDict.keys())) device_target_nodes = device.pop("nodes", None) if device_target_nodes is None: device_target_nodes = nest_nodes.values() else: device_target_nodes = nest_nodes[device_target_nodes] # Determine the connections from variables to measure/stimulate to NEST node populations connections = device["connections"] # either a variable name or a dict if isinstance(connections, string_types): connections = { connections: slice(None) } # return all population types # For every distinct quantity to be measured from NEST or stimulated towards NEST nodes... for name, populations in connections.items(): # This set of devices will be for variable... nest_devices.update( {name: NESTDeviceSet(name, dev_model, OrderedDict({}))}) # and for every target region node... for node in device_target_nodes: # and for every target node and population group... # create a device nest_devices[name].update({ node.label: build_device(nest_instance, device, node[populations]) }) return nest_devices
def _build_tvb_to_nest_interfaces(self): # This method will create the necessary NEST input devices and connect them to their target NEST nodes. # If the nest proxy doesn't need to be a device, we just add it to the list tvb_to_nest_interfaces = IndexedOrderedDict({}) # Create a list of input devices for every TVB node inside NEST and connect them to the target NEST nodes: for interface in self.tvb_to_nest_interfaces: model = interface.get("model", None) if model in NESTInputDeviceDict.keys(): tvb_to_nest_interfaces.update(self._build_tvb_to_nest_input_devices(interface)) else: tvb_to_nest_interfaces.update(self._build_tvb_to_nest_parameter_input(interface)) return tvb_to_nest_interfaces
def build_and_connect_devices_one_to_many(nest_instance, device, nest_nodes, names): # This function is mostly used when a stimulation (input) device targets more than one NEST node, # as it is the case for TVB state variables-per-node proxies # Build devices by their population (Series) # and target nodes (Series) for faster reading nest_devices = Series() if device["model"] in NESTInputDeviceDict.keys(): build_device = lambda nest_instance, device: build_input_device( nest_instance, device) elif device["model"] in NESTOutputDeviceDict.keys(): build_device = lambda nest_instance, device: build_output_device( nest_instance, device) else: raise ValueError( "Device model %s is neither one of available input devices:\n%s\n" "nor of output ones!:\n%s" % (device["model"], NESTInputDeviceDict.keys(), NESTOutputDeviceDict.keys())) # Determine the connections from variables to measure/stimulate to NEST node populations connections, device_target_nodes = _get_connections(device, nest_nodes) # Determine the device's parameters and connections' properties params, weights, delays, receptor_types = \ _get_device_props_with_correct_shape(device, (len(names), len(device_target_nodes))) # For every NEST population variable to be stimulated or measured... for pop_var, populations in connections.items(): # This set of devices will be for variable pop_var... nest_devices[pop_var] = NESTDeviceSet(pop_var, device["model"]) # and for every target region node... for i_dev, dev_name in enumerate(names): # and for every target node and population group... # create a device nest_devices[pop_var][dev_name] = build_device( nest_instance, device) for i_node, node in enumerate(device_target_nodes): nest_devices[pop_var][dev_name] = \ connect_device(nest_instance, nest_devices[pop_var][dev_name], node[populations], weights[i_dev, i_node], delays[i_dev, i_node], receptor_types[i_dev, i_node]) return nest_devices
def build_interface(self, tvb_nest_interface): """ Configure the TVB NEST interface of the fine scale as well other aspects of its interface with TVB :return: tvb_nest_interface object """ tvb_nest_interface.config = self.config tvb_nest_interface.nest_instance = self.nest_instance # TODO: find out why the model instance is different in simulator and interface... tvb_nest_interface.tvb_model = self.tvb_model tvb_nest_interface.dt = self.tvb_dt tvb_nest_interface.tvb_nodes_ids = self.tvb_nodes_ids tvb_nest_interface.nest_nodes_ids = self.nest_nodes_ids tvb_nest_interface.exclusive_nodes = self.exclusive_nodes tvb_nest_interface.nest_network = self.nest_network tvb_nest_interface.transforms = self.generate_transforms() tvb_nest_interface.tvb_to_nest_interfaces = Series({}) # Create a list of input devices for every TVB node inside NEST and connect them to the target NEST nodes: for interface in self.tvb_to_nest_interfaces: model = interface.get("model", None) if model in NESTInputDeviceDict.keys(): tvb_nest_interface.tvb_to_nest_interfaces = \ tvb_nest_interface.tvb_to_nest_interfaces.append( TVBtoNESTDeviceInterfaceBuilder([], self.nest_instance, self.nest_nodes, self.nest_nodes_ids, self.tvb_nodes_ids, self.tvb_model, self.tvb_weights, self.tvb_delays, self.tvb_connectivity.region_labels, self.tvb_dt, self.exclusive_nodes).build_interface(interface) ) else: tvb_nest_interface.tvb_to_nest_interfaces = \ tvb_nest_interface.tvb_to_nest_interfaces.append( TVBtoNESTParameterInterfaceBuilder([], self.nest_instance, self.nest_nodes, self.nest_nodes_ids, self.tvb_nodes_ids, self.tvb_model, self.exclusive_nodes). build_interface(interface) ) tvb_nest_interface.nest_to_tvb_interfaces = \ NESTtoTVBInterfaceBuilder(self.nest_to_tvb_interfaces, self.nest_instance, self.nest_nodes, self.nest_nodes_ids, self.tvb_nodes_ids, self.tvb_model, self.exclusive_nodes).build() return tvb_nest_interface
def __init__(self, nest_instance=None, region_nodes=IndexedOrderedDict({}), output_devices=IndexedOrderedDict({}), stimulation_devices=IndexedOrderedDict({}), config=CONFIGURED): self.config = config if nest_instance is None: nest_instance = load_nest() self.nest_instance = nest_instance if isinstance(region_nodes, IndexedOrderedDict) and \ np.all([isinstance(node, NESTRegionNode) for node in region_nodes.values()]): self.region_nodes = region_nodes else: raise ValueError( "Input region_nodes is not a IndexedOrderedDict of NESTRegionNode objects!: \n %s" % str(region_nodes)) self.output_devices = output_devices if isinstance(output_devices, IndexedOrderedDict) and \ np.all([isinstance(dev, NESTDeviceSet) and (dev.model in NESTOutputDeviceDict.keys() or len(dev.model) == 0) for dev in output_devices.values()]): self.output_devices = output_devices else: raise ValueError( "Input output_devices is not a IndexedOrderedDict of output NESTDeviceSet objects!:\n %s" % str(output_devices)) if isinstance(stimulation_devices, IndexedOrderedDict) and \ np.all([isinstance(dev, NESTDeviceSet) and (dev.model in NESTInputDeviceDict.keys() or len(dev.model) == 0) for dev in stimulation_devices.values()]): self.stimulation_devices = stimulation_devices else: raise ValueError( "Input stimulation_devices is not a IndexedOrderedDict of input NESTDeviceSet objects!:\n %s" % str(stimulation_devices)) LOG.info("%s created!" % self.__class__)
def _get_device_props_with_correct_shape(device, shape): dummy = np.ones(shape).astype("i") params = device.get("params", {}) if isinstance(params, dict): params = np.tile(params, dummy.shape) else: params = np.array(params) if params.shape != shape: if params.size == 0: params = np.tile(params, shape) else: raise_value_error( "Device parameters are neither of shape (n_devices, n_nodes) = %s" "nor of size 1:\n%s" % (str(shape), str(params))) weights = device.get("weights", 1.0) * dummy delays = device.get("delays", 0.0) * dummy if device["model"] in NESTInputDeviceDict.keys(): receptor_types = device.get("receptor_types", 0) * dummy else: receptor_types = 0 * dummy return params, weights, delays, receptor_types
# -*- coding: utf-8 -*- from abc import ABCMeta from six import add_metaclass from xarray import DataArray import pandas as pd from tvb_nest.config import CONFIGURED from tvb_nest.simulator_nest.models.devices import NESTInputDeviceDict from tvb_scripts.utils.log_error_utils import initialize_logger from tvb_scripts.utils.data_structures_utils import is_integer from tvb_scripts.time_series.model import TimeSeries, TimeSeriesRegion LOG = initialize_logger(__name__) DEVICES = NESTInputDeviceDict.keys() PARAMETERS = ["current", "potential"] @add_metaclass(ABCMeta) class TVBNESTInterface(object): nest_instance = None tvb_model = None dt = 0.1 tvb_nodes_ids = [] nest_nodes_ids = [] nest_network = None tvb_to_nest_interfaces = None