def _return_by_type(self, values_dict, return_type="dict", concatenation_index_name="Region", name=None): if return_type == "values": return list(values_dict.values()) elif return_type == "dict": return values_dict elif return_type == "Series": return pd.Series(values_dict, name=name) elif return_type == "xarray": if name is None: name = self.name for key, val in values_dict.items(): if isinstance(val, xr.DataArray): val.name = key else: raise_value_error("DataArray concatenation not possible! " "Not all outputs are DataArrays!:\n %s" % str(values_dict)) dims = list(values_dict.keys()) values = list(values_dict.values()) if len(values) == 0: return xr.DataArray([]) output = xr.concat(values, dim=pd.Index(dims, name=concatenation_index_name)) output.name = name return output else: return values_dict
def plot_time_series_interactive(self, time_series, first_n=-1, **kwargs): if isinstance(time_series, TimeSeriesTVB): self.plot_tvb_time_series_interactive(time_series, first_n, **kwargs) elif isinstance(time_series, TimeSeries): self.plot_tvb_time_series_interactive(time_series._tvb, first_n, **kwargs) elif isinstance(time_series, numpy.ndarray): self.plot_tvb_time_series_interactive(TimeSeries(data=time_series), first_n, **kwargs) elif isinstance(time_series, (list, tuple)): self.plot_tvb_time_series_interactive( TimeSeries(data=TimeSeriesTVB( data=numpy.stack(time_series, axis=1))), first_n, **kwargs) elif isinstance(time_series, dict): ts = numpy.stack(time_series.values(), axis=1) time_series = TimeSeriesTVB( data=ts, labels_dimensions={"State Variable": time_series.keys()}) self.plot_tvb_time_series_interactive(time_series, first_n, **kwargs) else: raise_value_error( "Input time_series: %s \n" "is not on of one of the following types: " "[TimeSeries (tvb-scripts), TimeSeriesTVB (TVB), numpy.ndarray, dict, list, tuple]" % str(time_series))
def get_subset(self, list_of_indices_or_labels, dim, **kwargs): assert dim in [0, 1, 2, 3] list_of_indices_or_labels = ensure_list(list_of_indices_or_labels) if numpy.all([ is_integer(ind_or_lbl) for ind_or_lbl in list_of_indices_or_labels ]): return self.get_subset_by_index(list_of_indices_or_labels, dim, **kwargs) else: if dim == 0: if not numpy.all([ is_numeric(ind_or_lbl) for ind_or_lbl in list_of_indices_or_labels ]): raise_value_error( "Input consists neither of integer indices nor of points in time (floats)!: %s" % list_of_indices_or_labels) time_indices = [ self._get_index_for_time(time) for time in list_of_indices_or_labels ] return self.get_subset_by_index(time_indices, 0, **kwargs) else: if not numpy.all([ isinstance(ind_or_lbl, string_types) for ind_or_lbl in list_of_indices_or_labels ]): raise_value_error( "Input consists neither of integer indices nor of label strings!: %s" % list_of_indices_or_labels) return self.get_subset_by_label(list_of_indices_or_labels, dim, **kwargs)
def __init__(self, spiking_network, name, model, parameter="", tvb_coupling_id=0, nodes_ids=[], scale=np.array([1.0]), neurons=Series()): super(TVBtoSpikeNetParameterInterface, self).__init__(neurons) self.spiking_network = spiking_network self.name = str(name) self.model = str(model) if self.model not in self._available_input_parameters.keys(): raise_value_error( "model %s is not one of the available parameter interfaces!" % self.model) self.parameter = str( parameter) # The string of the target parameter name if len(parameter) == 0: self.parameter = self._available_input_parameters[self.model] else: if self.parameter != self._available_input_parameters[self.model]: LOG.warning( "Parameter %s is different to the default one %s " "for parameter interface model %s" % (self.parameter, self._available_input_parameters[self.model], self.model)) self.tvb_coupling_id = int(tvb_coupling_id) # The target Spiking Network region nodes which coincide with the source TVB region nodes # (i.e., region i of TVB modifies a parameter in region i implemented in Spiking Network): self.nodes_ids = nodes_ids self.scale = scale # a scaling weight LOG.info("%s of model %s for %s created!" % (self.__class__, self.model, self.name))
def connect_device(nest_device, neurons, weight=1.0, delay=0.0, receptor_type=0, config=CONFIGURED, nest_instance=None): if nest_instance is None: raise_value_error("There is no NEST instance!") delay = np.maximum(delay, nest_instance.GetKernelStatus("resolution")) if nest_device.model == "spike_detector": # source -> target nest_instance.Connect(neurons, nest_device.device, syn_spec={ "weight": weight, "delay": delay, "receptor_type": receptor_type }) else: nest_instance.Connect(nest_device.device, neurons, syn_spec={ "weight": weight, "delay": delay, "receptor_type": receptor_type }) # nest_device.update_number_of_connections() return nest_device
def normalize_signals(signals, normalization=None, axis=None, percent=None): # Following pylab demean: def matrix_subtract_along_axis(x, y, axis=0): "Return x minus y, where y corresponds to some statistic of x along the specified axis" if axis == 0 or axis is None or x.ndim <= 1: return x - y ind = [slice(None)] * x.ndim ind[axis] = np.newaxis return x - y[ind] def matrix_divide_along_axis(x, y, axis=0): "Return x divided by y, where y corresponds to some statistic of x along the specified axis" if axis == 0 or axis is None or x.ndim <= 1: return x / y ind = [slice(None)] * x.ndim ind[axis] = np.newaxis return x / y[ind] for norm, ax, prcnd in zip(ensure_list(normalization), cycle(ensure_list(axis)), cycle(ensure_list(percent))): if isinstance(norm, string_types): if isequal_string(norm, "zscore"): signals = zscore(signals, axis=ax) # / 3.0 elif isequal_string(norm, "baseline-std"): signals = normalize_signals(["baseline", "std"], axis=axis) elif norm.find("baseline") == 0 and norm.find("amplitude") >= 0: signals = normalize_signals(signals, ["baseline", norm.split("-")[1]], axis=axis, percent=percent) elif isequal_string(norm, "minmax"): signals = normalize_signals(signals, ["min", "max"], axis=axis) elif isequal_string(norm, "mean"): signals = demean(signals, axis=ax) elif isequal_string(norm, "baseline"): if prcnd is None: prcnd = 1 signals = matrix_subtract_along_axis(signals, np.percentile(signals, prcnd, axis=ax), axis=ax) elif isequal_string(norm, "min"): signals = matrix_subtract_along_axis(signals, np.min(signals, axis=ax), axis=ax) elif isequal_string(norm, "max"): signals = matrix_divide_along_axis(signals, np.max(signals, axis=ax), axis=ax) elif isequal_string(norm, "std"): signals = matrix_divide_along_axis(signals, signals.std(axis=ax), axis=ax) elif norm.find("amplitude") >= 0: if prcnd is None: prcnd = [1, 99] amplitude = np.percentile(signals, prcnd[1], axis=ax) - np.percentile(signals, prcnd[0], axis=ax) this_ax = ax if isequal_string(norm.split("amplitude")[0], "max"): amplitude = amplitude.max() this_ax = None elif isequal_string(norm.split("amplitude")[0], "mean"): amplitude = amplitude.mean() this_ax = None signals = matrix_divide_along_axis(signals, amplitude, axis=this_ax) else: raise_value_error("Ignoring signals' normalization " + normalization + ",\nwhich is not one of the currently available " + str(NORMALIZATION_METHODS) + "!") return signals
def read_connectivity(self, path): if os.path.isfile(path): conn = Connectivity.from_file(path) conn.file_path = path conn.configure() return conn else: raise_value_error( ("\n No Connectivity file found at path %s!" % str(path)))
def _configure_connections(self, connections, default_connection): for i_con, connection in enumerate(connections): for pop in ["source", "target"]: if len(connection.get(pop, "")) == 0: raise_value_error("No %s population in connection!:\n%s" % (pop, str(connection))) temp_conn = dict(default_connection) temp_conn.update(connection) connections[i_con] = temp_conn return connections
def read_connectivity(self, path): """ :param path: Path towards a custom Connectivity H5 file :return: Connectivity object """ self.logger.info("Starting to read a Connectivity from: %s" % path) if os.path.isfile(path): h5_file = h5py.File(path, 'r', libver='latest') weights = h5_file['/' + ConnectivityH5Field.WEIGHTS][()] try: tract_lengths = h5_file['/' + ConnectivityH5Field.TRACTS][()] except: tract_lengths = numpy.array([]) try: region_centres = h5_file['/' + ConnectivityH5Field.CENTERS][()] except: region_centres = numpy.array([]) try: region_labels = h5_file['/' + ConnectivityH5Field.REGION_LABELS][()] except: region_labels = numpy.array([]) try: orientations = h5_file['/' + ConnectivityH5Field.ORIENTATIONS][()] except: orientations = numpy.array([]) try: hemispheres = h5_file['/' + ConnectivityH5Field.HEMISPHERES][()] except: hemispheres = numpy.array([]) try: areas = h5_file['/' + ConnectivityH5Field.AREAS][()] except: areas = numpy.array([]) h5_file.close() conn = Connectivity(file_path=path, weights=weights, tract_lengths=tract_lengths, region_labels=region_labels, region_centres=region_centres, hemispheres=hemispheres, orientations=orientations, areas=areas) conn.configure() self.logger.info("Successfully read connectvity from: %s" % path) return conn else: raise_value_error( ("\n No Connectivity file found at path %s!" % str(path)))
def _assert_connection_populations(self, connection): # This method will make sure that there source and target user inputs for every population connection # and that every source/target population is already among the populations to be generated. for pop in ["source", "target"]: pops_labels = connection.get(pop, None) if pops_labels is None: raise_value_error("No %s population in connection!:\n%s" % (pop, str(connection))) for pop_lbl in ensure_list(pops_labels): assert pop_lbl in self.populations_labels return pops_labels
def from_device_set(self, device_set, tvb_sv_id=None, name=None): if isinstance(device_set, DeviceSet): super(SpikeNetToTVBinterface, self).__init__(device_set.name, device_set.model, device_set) else: raise_value_error("Input device_set is not a DeviceSet!: %s" % str(device_set)) self.tvb_sv_id = tvb_sv_id if isinstance(name, string_types): self.name = name self.update_model() return self
def _assert_conn_params_shape(p, p_name, shape): if isinstance(p, dict): return np.tile(p, shape) elif not isinstance(p, np.ndarray): p = np.array(p) if np.any(p.shape != shape): if p.size == 1: return np.tile(p, shape) else: raise_value_error("Device %s are neither of shape (n_devices, n_nodes) = %s" "nor of size 1:\n%s" % (p_name, str(shape), str(p))) return p
def from_device_set(self, device_set, tvb_sv_id=0, name=None): # Generate the interface from a DeviceSet (that corresponds to a collection of devices => proxy-nodes) if isinstance(device_set, DeviceSet): super(TVBtoSpikeNetDeviceInterface, self).__init__(device_set.name, device_set.model, device_set) else: raise_value_error("Input device_set is not a DeviceSet!: %s" % str(device_set)) self.tvb_sv_id = tvb_sv_id if isinstance(name, string_types): self.name = name self.update_model() return self
def plot_time_series(self, time_series, mode="ts", subplots=None, special_idx=[], subtitles=[], offset=0.5, title=None, figure_name=None, figsize=None, **kwargs): if isinstance(time_series, TimeSeries): if title is None: title = time_series.title return self.plot_ts(numpy.swapaxes(time_series.data, 1, 2), time_series.time, time_series.variables_labels, mode, subplots, special_idx, subtitles, time_series.space_labels, offset, time_series.time_unit, title, figure_name, figsize) elif isinstance(time_series, TimeSeriesTVB): self.plot_tvb_time_series(time_series, mode, subplots, special_idx, subtitles, offset, title, figure_name, figsize) elif isinstance(time_series, (numpy.ndarray, dict, list, tuple)): time = kwargs.get("time", None) time_unit = kwargs.get("time_unit", "ms") labels = kwargs.get("labels", []) var_labels = kwargs.get("var_labels", []) if title is None: title = "Time Series" return self.plot_ts(time_series, time=time, mode=mode, time_unit=time_unit, labels=labels, var_labels=var_labels, subplots=subplots, special_idx=special_idx, subtitles=subtitles, offset=offset, title=title, figure_name=figure_name, figsize=figsize) else: raise_value_error( "Input time_series: %s \n" "is not on of one of the following types: " "[TimeSeries (tvb-scripts), TimeSeries (TVB), numpy.ndarray, dict]" % str(time_series))
def _assert_synapse_model(self, synapse_model, delay): if synapse_model.find("rate") > -1: if synapse_model == "rate_connection_instantaneous" and delay != 0.0: raise_value_error("Coupling neurons with rate_connection_instantaneous synapse " "and delay = %f != 0.0 is not possible!" % delay) elif delay == 0.0 and synapse_model == "rate_connection_delayed": raise_value_error("Coupling neurons with rate_connection_delayed synapse " "and delay = %f <= 0.0 is not possible!" % delay) elif delay == 0.0: return "rate_connection_instantaneous" else: return "rate_connection_delayed" else: return synapse_model
def set_sensors(self, input_sensors, s_type=SensorTypes.TYPE_EEG.value, reset=False): if not isinstance(input_sensors, (Sensors, dict, list, tuple)): return raise_value_error("Invalid input sensors instance''!: %s" % str(input_sensors)) if s_type not in SensorTypesNames: raise_value_error("Invalid input sensor type!: %s" % str(s_type)) sensors_set = self.get_sensors(s_type)[0] if reset is True: sensors_set = OrderedDict() if isinstance(input_sensors, dict): input_projections = input_sensors.values() input_sensors = input_sensors.keys() else: if isinstance(input_sensors, Sensors): input_sensors = [input_sensors] else: input_sensors = list(input_sensors) input_projections = [None] * len(input_sensors) for sensor, projection in zip(input_sensors, input_projections): if not isinstance(sensor, Sensors): raise_value_error( "Input sensors:\n%s" "\nis not a valid Sensors object of type %s!" % (str(sensor), s_type)) if sensor.sensors_type != s_type: raise_value_error("Sensors %s \nare not of type %s!" % (str(sensor), s_type)) if not isinstance(projection, ProjectionMatrix): warning("projection is not set for sensor with name:\n%s!" % sensor.name) sensors_set.update({sensor: None}) else: if projection.projection_type != SensorTypesToProjectionDict[ s_type]: raise_value_error( "Disaggreement between sensors'type %s and projection's type %s!" % (sensor.sensors_type, projection.projection_type)) good_sensor_shape = (sensor.number_of_sensors, self.number_of_regions) if projection.projection_data.shape != good_sensor_shape: warning( "projections' shape %s of sensor %s " "is not equal to (number_of_sensors, number_of_regions)=%s!" % (str(projection.projection_data.shape), sensor.name, str(good_sensor_shape))) sensors_set.update({sensor: projection}) self.sensors[s_type] = sensors_set
def node_key_index_and_label(node, labels): if isinstance(node, string_types): try: i_node = labels.index(node) label = node node_key = "%d-%s" % (node, i_node) except: raise_value_error("Node %s is not a region node modeled in NEST!" % node) else: try: label = labels.index(node) i_node = node node_key = "%d-%s" % (label, node) except: raise_value_error("Node %d is not a region node modeled in NEST!" % node) return node_key, i_node, label
def build_interface(self, interface): # One interface for every combination of Spiking node # and TVB state variable to be transmitted # from TVB to Spiking Network connections = interface["connections"] if isinstance(connections, string_types): connections = { connections: slice(None) } # return all population types default_parameter = self._build_target_class._available_input_parameters[ interface["model"]] spiking_nodes_ids = interface.get("nodes", self.spiking_nodes_ids) if spiking_nodes_ids is None: spiking_nodes_ids = self.spiking_nodes_ids spiking_nodes_ids = list(spiking_nodes_ids) if self.exclusive_nodes: assert np.all(spiking_node not in self.tvb_nodes_ids for spiking_node in spiking_nodes_ids) interface_weights = 1.0 * np.ones( (len(spiking_nodes_ids), )).astype("f") interface_weight_fun = property_to_fun( interface.get("interface_weights", 1.0)) for i_w, spiking_node_id in enumerate(spiking_nodes_ids): interface_weights[i_w] = interface_weight_fun(spiking_node_id) tvb_to_spikeNet_interfaces = Series() for name, populations in connections.items(): try: tvb_coupling_id = self.tvb_model.cvar.tolist().index( self.tvb_model.state_variables.index(name)) except: raise_value_error( "Failed to compute the coupling index of TVB state variable %s!" % name) tvb_to_spikeNet_interfaces[name] = \ self._build_target_class(self.spiking_network, name, interface["model"], interface.get("parameter", default_parameter), tvb_coupling_id, spiking_nodes_ids, interface_weights) for node in self.spiking_nodes: tvb_to_spikeNet_interfaces[name][ node.label] = node[populations] return tvb_to_spikeNet_interfaces
def plot_spectral_analysis_raster(self, time_series, freq=None, spectral_options={}, special_idx=[], labels=[], title='Spectral Analysis', figure_name=None, figsize=None, **kwargs): if isinstance(time_series, TimeSeries): return self.plot_ts_spectral_analysis_raster(numpy.swapaxes(time_series._tvb.data, 1, 2).squeeze(), time_series.time, time_series.time_unit, freq, spectral_options, special_idx, labels, title, figure_name, figsize) elif isinstance(time_series, TimeSeriesTVB): return self.plot_ts_spectral_analysis_raster(numpy.swapaxes(time_series.data, 1, 2).squeeze(), time_series.time, time_series.time_unit, freq, spectral_options, special_idx, labels, title, figure_name, figsize) elif isinstance(time_series, (numpy.ndarray, dict, list, tuple)): time = kwargs.get("time", None) return self.plot_ts_spectral_analysis_raster(time_series, time=time, freq=freq, spectral_options=spectral_options, special_idx=special_idx, labels=labels, title=title, figure_name=figure_name, figsize=figsize) else: raise_value_error("Input time_series: %s \n" "is not on of one of the following types: " "[TimeSeries (tvb-scripts), TimeSeries (TVB), numpy.ndarray, dict]" % str(time_series))
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
def concatenate(self, time_series_list, dim, **kwargs): time_series_list = ensure_list(time_series_list) n_ts = len(time_series_list) if n_ts > 0: out_time_series, select_funs = self.select(time_series_list[0], **kwargs) if n_ts > 1: dim_label = out_time_series.get_dimension_name(dim) for id, time_series in enumerate(time_series_list[1:]): if np.float32(out_time_series.sample_period) != np.float32(time_series.sample_period): raise ValueError("Timeseries concatenation failed!\n" "Timeseries %d have a different time step %s \n " "than the concatenated ones %s!" % (id, str(np.float32(time_series.sample_period)), str(np.float32(out_time_series.sample_period)))) else: time_series = self.select(time_series, select_funs)[0] labels_dimensions = dict(out_time_series.labels_dimensions) out_labels = out_time_series.get_dimension_labels(dim) if out_labels is not None and len(out_labels) == out_time_series.shape[dim]: time_series_labels = time_series.get_dimension_labels(dim) if time_series_labels is not None and len(time_series_labels) == time_series.shape[dim]: labels_dimensions[dim_label] =\ np.array(ensure_list(out_labels) + ensure_list(time_series_labels)) else: del labels_dimensions[dim_label] warning("Dimension labels for dimensions %s cannot be concatenated! " "Deleting them!" % dim_label) try: out_data = np.concatenate([out_time_series.data, time_series.data], axis=dim) except: raise_value_error("Timeseries concatenation failed!\n" "Timeseries %d have a shape %s and the concatenated ones %s!" % (id, str(out_time_series.shape), str(time_series.shape))) out_time_series = out_time_series.duplicate(data=out_data, labels_dimensions=labels_dimensions) return out_time_series else: return out_time_series else: raise ValueError("Cannot concatenate empty list of TimeSeries!")
def concatenate(self, time_series_list, dim, **kwargs): time_series_list = ensure_list(time_series_list) n_ts = len(time_series_list) if n_ts > 0: out_time_series, select_fun = self.select(time_series_list[0], **kwargs) if n_ts > 1: for id, time_series in enumerate(time_series_list[1:]): if np.float32(out_time_series.sample_period) != np.float32(time_series.sample_period): raise_value_error("Timeseries concatenation failed!\n" "Timeseries %d have a different time step (%s) \n " "than the concatenated ones (%s)!" % (id, str(np.float32(time_series.sample_period)), str(np.float32(out_time_series.sample_period)))) else: time_series = self.select(time_series, select_fun)[0] try: out_time_series.set_data(np.concatenate([out_time_series.data, time_series.data], axis=dim)) if len(out_time_series.labels_dimensions[out_time_series.labels_ordering[dim]]) > 0: dim_label = out_time_series.labels_ordering[dim] out_time_series.labels_dimensions[dim_label] = \ np.array(ensure_list(out_time_series.labels_dimensions[dim_label]) + ensure_list(time_series.labels_dimensions[dim_label])) except: raise_value_error("Timeseries concatenation failed!\n" "Timeseries %d have a shape (%s) and the concatenated ones (%s)!" % (id, str(out_time_series.shape), str(time_series.shape))) return out_time_series else: return out_time_series else: raise_value_error("Cannot concatenate empty list of TimeSeries!")
def get_sensors(self, s_type=SensorTypes.TYPE_EEG.value, name_or_index=None): sensors_set = OrderedDict() if s_type not in SensorTypesNames: raise_value_error("Invalid input sensor type!: %s" % str(s_type)) else: sensors_set = self.sensors.get(s_type, None) out_sensor = None out_projection = None if isinstance(sensors_set, OrderedDict): if isinstance(name_or_index, string_types): for sensor, projection in sensors_set.items(): if isequal_string(sensor.name, name_or_index): out_sensor = sensor out_projection = projection elif is_integer(name_or_index): out_sensor = sensors_set.keys()[name_or_index] out_projection = sensors_set.values()[name_or_index] else: return sensors_set return out_sensor, out_projection
def create_device(device_model, device_name=None, params=None, config=CONFIGURED, nest_instance=None): if nest_instance is None: nest_instance = load_nest(config=config) return_nest = True else: return_nest = False if not isinstance(device_name, string_types): device_name = device_model else: # ...assert the type... device_model = device_to_dev_model(device_name) if device_model in NESTInputDeviceDict.keys(): devices_dict = NESTInputDeviceDict default_params_dict = config.NEST_INPUT_DEVICES_PARAMS_DEF elif device_model in NESTOutputDeviceDict.keys(): devices_dict = NESTOutputDeviceDict default_params_dict = config.NEST_OUTPUT_DEVICES_PARAMS_DEF else: raise_value_error( "%s is neither one of the available input devices: %s\n " "nor of the output ones: %s!" % (device_model, str(config.NEST_INPUT_DEVICES_PARAMS_DEF), str(config.NEST_OUTPUT_DEVICES_PARAMS_DEF))) default_params = dict(default_params_dict.get(device_name, {})) if isinstance(params, dict) and len(params) > 0: default_params.update(params) if return_nest: return devices_dict[device_name](nest_instance.Create(device_model, params=default_params), nest_instance), \ nest_instance else: return devices_dict[device_name](nest_instance.Create( device_model, params=default_params), nest_instance)
def _assert_delay(self, delay, synapse_model="static_synapse"): if synapse_model.find("rate") > -1: if synapse_model == "rate_connection_instantaneous" and delay != 0.0: raise_value_error("Coupling neurons with rate_connection_instantaneous synapse " "and delay = %f != 0.0 is not possible!" % delay) elif synapse_model == "rate_connection_delayed" and delay <= 0.0: raise_value_error("Coupling neurons with rate_connection_delayed synapse " "and delay = %f <= 0.0 is not possible!" % delay) elif delay < 0.0: raise_value_error("Coupling rate neurons with negative delay = %f < 0.0 is not possible!" % delay) elif delay < self.spiking_dt: LOG.warning("Coupling spiking neurons with delay = %f < NEST integration step = %s is not possible!\n" "Setting delay equal to NEST integration step!" % (delay, self.spiking_dt)) return self.default_min_delay else: return delay
def concatenate(self, time_series_list, dim, **kwargs): time_series_list = ensure_list(time_series_list) n_ts = len(time_series_list) if n_ts > 0: out_time_series, select_funs = self.select(time_series_list[0], **kwargs) if n_ts > 1: for id, time_series in enumerate(time_series_list[1:]): if np.float32(out_time_series.sample_period) != np.float32(time_series.sample_period): raise_value_error("Timeseries concatenation failed!\n" "Timeseries %d have a different time step %s \n " "than the concatenated ones %s!" % (id, str(np.float32(time_series.sample_period)), str(np.float32(out_time_series.sample_period)))) else: time_series = self.select(time_series, select_funs)[0] # try: out_time_series.data = np.concatenate([out_time_series.data, time_series.data], axis=dim) if len(out_time_series.get_dimension_labels(dim)) > 0: if len(time_series.get_dimension_labels(dim)) > 0: dim_label = out_time_series.get_dimension_name(dim) out_time_series.labels_dimensions[dim_label] = \ np.array(ensure_list(out_time_series.get_dimension_labels(dim)) + ensure_list(time_series.get_dimension_labels(dim))) else: raise_value_error("TimeSeries to concatenate %s \n " "has no dimension labels across the concatenation axis,\n" "unlike the TimeSeries to be appended to: %s!" % (str(time_series), str(out_time_series))) # except: # raise_value_error("Timeseries concatenation failed!\n" # "Timeseries %d have a shape %s and the concatenated ones %s!" % # (id, str(out_time_series.shape), str(time_series.shape))) return out_time_series else: return out_time_series else: raise_value_error("Cannot concatenate empty list of TimeSeries!")
def build_interface(self, interface): # One NEST stimulation device for every combination of # TVB node and state variable to be transmitted from TVB to NEST source_tvb_nodes = interface.pop("source_nodes", self.tvb_nodes_ids) if source_tvb_nodes is None: source_tvb_nodes = self.tvb_nodes_ids source_tvb_nodes = list(source_tvb_nodes) target_nest_nodes = interface.pop("target_nodes", self.nest_nodes_ids) if target_nest_nodes is None: target_nest_nodes = self.nest_nodes_ids target_nest_nodes = list(target_nest_nodes) if self.exclusive_nodes: # TODO: decide about the following: can a TVB node be updated from a NEST node via a NEST -> TVB interface, # get simulated in TVB and again update NEST via a TVB -> NEST interface? # Will it depend on whether there is also a directly coupling of that NEST node with other NEST nodes? assert np.all(node not in self.tvb_nodes_ids for node in target_nest_nodes) assert np.all(node not in self.nest_nodes_ids for node in source_tvb_nodes) interface_weight = property_to_fun( interface.pop("interface_weights", 1.0)) interface_weights = np.ones((len(source_tvb_nodes), )).astype("f") weight = property_to_fun(interface.pop("weights", 1.0)) delay = property_to_fun(interface.pop("delays", 0.0)) receptor_type = property_to_fun(interface.pop("receptor_types", 0)) # TODO: Find a way to change self directed weights in cases of non exclusive TVB and NEST nodes! weights = self.tvb_weights[source_tvb_nodes][:, target_nest_nodes] delays = self.tvb_delays[source_tvb_nodes][:, target_nest_nodes] receptor_types = np.zeros(delays.shape).astype("i") target_nest_nodes_ids = [ np.where(self.nest_nodes_ids == trg_node)[0][0] for trg_node in target_nest_nodes ] interface["nodes"] = target_nest_nodes_ids device_names = [] for src_node in source_tvb_nodes: i_src = np.where(self.tvb_nodes_ids == src_node)[0][0] interface_weights[i_src] = interface_weight(src_node) device_names.append(self.node_labels[src_node]) for trg_node, i_trg in zip(target_nest_nodes, target_nest_nodes_ids): weights[i_src, i_trg] *= weight(src_node, trg_node) delays[i_src, i_trg] += delay(src_node, trg_node) receptor_types[i_src, i_trg] = receptor_type(src_node, trg_node) interface["weights"] = weights interface["delays"] = delays interface["receptor_types"] = receptor_types interface["names"] = device_names devices = build_and_connect_output_devices(self.nest_instance, [interface], self.nest_nodes) tvb_to_nest_interface = Series() for name, device in devices.items(): try: tvb_sv_id = self.tvb_model.state_variables.index(name) except: raise_value_error( "Interface with %s doesn't correspond to a TVB state variable!" ) try: interface_builder = INPUT_INTERFACES_DICT[device.model] except: raise_value_error("Interface model %s is not supported yet!" % device.model) tvb_to_nest_interface[name] = \ interface_builder(self.nest_instance, nodes_ids=source_tvb_nodes, target_nodes=target_nest_nodes, scale=interface_weights, dt=self.tvb_dt).from_device_set(device, tvb_sv_id, name) if len(source_tvb_nodes) * len(target_nest_nodes) > 0: assert np.abs( np.max(tvb_to_nest_interface[name].weights - weights)) < 0.001 assert np.abs( np.max(tvb_to_nest_interface[name].delays - delays)) < 1.0 # ms assert np.abs( np.max(tvb_to_nest_interface[name].receptors - receptor_types)) < 1 # integers return tvb_to_nest_interface
def _configure_history(self, initial_conditions): """ Set initial conditions for the simulation using either the provided initial_conditions or, if none are provided, the model's initial() method. This method is called durin the Simulator's __init__(). Any initial_conditions that are provided as an argument are expected to have dimensions 1, 2, and 3 with shapse corresponding to the number of state_variables, nodes and modes, respectively. If the provided inital_conditions are shorter in time (dim=0) than the required history the model's initial() method is called to make up the difference. """ rng = numpy.random if hasattr(self.integrator, 'noise'): rng = self.integrator.noise.random_stream # Default initial conditions if initial_conditions is None: n_time, n_svar, n_node, n_mode = self.good_history_shape LOG.info( 'Preparing initial history of shape %r using model.initial()', self.good_history_shape) if self.surface is not None: n_node = self.number_of_nodes history = self.model.initial(self.integrator.dt, (n_time, n_svar, n_node, n_mode), rng) # ICs provided else: # history should be [timepoints, state_variables, nodes, modes] LOG.info('Using provided initial history of shape %r', initial_conditions.shape) n_time, n_svar, n_node, n_mode = ic_shape = initial_conditions.shape nr = self.connectivity.number_of_regions if self.surface is not None and n_node == nr: initial_conditions = initial_conditions[:, :, self._regmap] return self._configure_history(initial_conditions) elif ic_shape[1:] != self.good_history_shape[1:]: raise_value_error( "Incorrect history sample shape %s, expected %s" % ic_shape[1:], self.good_history_shape[1:]) else: if ic_shape[0] >= self.horizon: LOG.debug("Using last %d time-steps for history.", self.horizon) history = initial_conditions[ -self.horizon:, :, :, :].copy() else: LOG.debug('Padding initial conditions with model.initial') history = self.model.initial(self.integrator.dt, self.good_history_shape, rng) shift = self.current_step % self.horizon history = numpy.roll(history, -shift, axis=0) history[:ic_shape[0], :, :, :] = initial_conditions history = numpy.roll(history, shift, axis=0) self.current_step += ic_shape[0] - 1 # Make sure that history values are bounded, # and any possible non-state variables are initialized # based on state variable ones (but with no coupling yet...) self._update_and_bound_history(numpy.swapaxes(history, 0, 1)) LOG.info('Final initial history shape is %r', history.shape) # create initial state from history self.current_state = history[self.current_step % self.horizon].copy() LOG.debug('initial state has shape %r' % (self.current_state.shape, )) if self.surface is not None and history.shape[ 2] > self.connectivity.number_of_regions: n_reg = self.connectivity.number_of_regions (nt, ns, _, nm), ax = history.shape, (2, 0, 1, 3) region_history = numpy.zeros((nt, ns, n_reg, nm)) numpy_add_at(region_history.transpose(ax), self._regmap, history.transpose(ax)) region_history /= numpy.bincount(self._regmap).reshape((-1, 1)) history = region_history # create history query implementation self.history = SparseHistory(self.connectivity.weights, self.connectivity.idelays, self.model.cvar, self.model.number_of_modes) # initialize its buffer self.history.initialize(history)
def plot_ts(self, data, time=None, var_labels=[], mode="ts", subplots=None, special_idx=[], subtitles=[], labels=[], offset=0.5, time_unit="ms", title='Time series', figure_name=None, figsize=None): if not isinstance(figsize, (list, tuple)): figsize = self.config.figures.LARGE_SIZE if isinstance(data, dict): var_labels = data.keys() data = data.values() elif isinstance(data, numpy.ndarray): if len(data.shape) < 3: if len(data.shape) < 2: data = numpy.expand_dims(data, 1) data = numpy.expand_dims(data, 2) data = [data] else: # Assuming a structure of Time X Space X Variables X Samples data = [ data[:, :, iv].squeeze() for iv in range(data.shape[2]) ] elif isinstance(data, (list, tuple)): data = ensure_list(data) else: raise_value_error("Input timeseries: %s \n" "is not on of one of the following types: " "[numpy.ndarray, dict, list, tuple]" % str(data)) n_vars = len(data) data_lims = [] for id, d in enumerate(data): if isequal_string(mode, "raster"): data[id] = (d - d.mean(axis=0)) drange = numpy.max(data[id].max(axis=0) - data[id].min(axis=0)) data[id] = data[id] / drange # zscore(d, axis=None) data_lims.append([d.min(), d.max()]) data_shape = data[0].shape if len(data_shape) == 1: n_times = data_shape[0] nTS = 1 for iV in range(n_vars): data[iV] = data[iV][:, numpy.newaxis] else: n_times, nTS = data_shape[:2] if len(data_shape) > 2: nSamples = data_shape[2] else: nSamples = 1 if special_idx is None: special_idx = [] n_special_idx = len(special_idx) if len(subtitles) == 0: subtitles = var_labels if isinstance(labels, list) and len(labels) == n_vars: labels = [ generate_region_labels(nTS, label, ". ", self.print_ts_indices) for label in labels ] else: labels = [ generate_region_labels(nTS, labels, ". ", self.print_ts_indices) for _ in range(n_vars) ] if isequal_string(mode, "traj"): data_fun, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits = \ self._trajectories_plot(n_vars, nTS, nSamples, subplots) else: if isequal_string(mode, "raster"): data_fun, time, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits, axYticks = \ self._ts_plot(time, n_vars, nTS, n_times, time_unit, 0, offset, data_lims) else: data_fun, time, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits, axYticks = \ self._ts_plot(time, n_vars, nTS, n_times, time_unit, ensure_list(subplots)[0]) alpha_ratio = 1.0 / nSamples alphas = numpy.maximum( numpy.array([def_alpha] * nTS) * alpha_ratio, 0.1) alphas[special_idx] = numpy.maximum(alpha_ratio, 0.1) if isequal_string(mode, "traj") and (n_cols * n_rows > 1): colors = numpy.zeros((nTS, 4)) colors[special_idx] = \ numpy.array([numpy.array([1.0, 0, 0, 1.0]) for _ in range(n_special_idx)]).reshape((n_special_idx, 4)) else: cmap = matplotlib.cm.get_cmap('jet') colors = numpy.array([cmap(0.5 * iTS / nTS) for iTS in range(nTS)]) colors[special_idx] = \ numpy.array([cmap(1.0 - 0.25 * iTS / nTS) for iTS in range(n_special_idx)]).reshape((n_special_idx, 4)) colors[:, 3] = alphas lines = [] pyplot.figure(title, figsize=figsize) axes = [] for icol in range(n_cols): if n_rows == 1: # If there are no more rows, create axis, and set its limits, labels and possible subtitle axes += ensure_list( pyplot.subplot(n_rows, n_cols, icol + 1, projection=projection)) axlimits(data_lims, time, n_vars, icol) axlabels(labels[icol % n_vars], var_labels, n_vars, n_rows, 1, 0) pyplot.gca().set_title(subtitles[icol]) for iTS in loopfun(nTS, n_rows, icol): if n_rows > 1: # If there are more rows, create axes, and set their limits, labels and possible subtitles axes += ensure_list( pyplot.subplot(n_rows, n_cols, iTS + 1, projection=projection)) axlimits(data_lims, time, n_vars, icol) subtitle(labels[icol % n_vars], iTS) axlabels(labels[icol % n_vars], var_labels, n_vars, n_rows, (iTS % n_rows) + 1, iTS) lines += ensure_list( plot_lines(data_fun(data, time, icol), iTS, colors, labels[icol % n_vars])) if isequal_string( mode, "raster"): # set yticks as labels if this is a raster plot axYticks(labels[icol % n_vars], nTS) yticklabels = pyplot.gca().yaxis.get_ticklabels() self.tick_font_size = numpy.minimum( self.tick_font_size, int(numpy.round(self.tick_font_size * 100.0 / nTS))) for iTS in range(nTS): yticklabels[iTS].set_fontsize(self.tick_font_size) if iTS in special_idx: yticklabels[iTS].set_color(colors[iTS, :3].tolist() + [1]) pyplot.gca().yaxis.set_ticklabels(yticklabels) pyplot.gca().invert_yaxis() if self.config.figures.MOUSE_HOOVER: for line in lines: self.HighlightingDataCursor(line, formatter='{label}'.format, bbox=dict(fc='white'), arrowprops=dict( arrowstyle='simple', fc='white', alpha=0.5)) self._save_figure(pyplot.gcf(), figure_name) self._check_show() return pyplot.gcf(), axes, lines
def configure(self, tvb_spikeNet_interface, full_configure=True): """Configure simulator and its components. The first step of configuration is to run the configure methods of all the Simulator's components, ie its traited attributes. Configuration of a Simulator primarily consists of calculating the attributes, etc, which depend on the combinations of the Simulator's traited attributes (keyword args). Converts delays from physical time units into integration steps and updates attributes that depend on combinations of the 6 inputs. Returns ------- sim: Simulator The configured Simulator instance. """ if full_configure: # When run from GUI, preconfigure is run separately, and we want to avoid running that part twice self.preconfigure() # Make sure spatialised model parameters have the right shape (number_of_nodes, 1) self.tvb_spikeNet_interface = tvb_spikeNet_interface # TODO: decide if this is really necessary... if self.integrator.dt >= 2 * self.tvb_spikeNet_interface.spikeNet_min_delay: self.integrator.dt = int(numpy.round(self.integrator.dt / self.tvb_spikeNet_interface.spikeNet_min_delay)) * \ self.tvb_spikeNet_interface.spikeNet_min_delay else: raise_value_error( "TVB integration time step dt=%f " "is not equal or greater than twice the Spiking Network minimum delay min_delay=%f!" % (self.integrator.dt, self.tvb_spikeNet_interface.spikeNet_min_delay)) excluded_params = ("state_variable_range", "state_variable_boundaries", "variables_of_interest", "noise", "psi_table", "nerf_table", "gid") spatial_reshape = self.model.spatial_param_reshape for param in type(self.model).declarative_attrs: if param in excluded_params: continue # If it's a surface sim and model parameters were provided at the region level region_parameters = getattr(self.model, param) if self.surface is not None: if region_parameters.size == self.connectivity.number_of_regions: new_parameters = region_parameters[ self.surface.region_mapping].reshape(spatial_reshape) setattr(self.model, param, new_parameters) region_parameters = getattr(self.model, param) if hasattr( region_parameters, "size") and region_parameters.size == self.number_of_nodes: new_parameters = region_parameters.reshape(spatial_reshape) setattr(self.model, param, new_parameters) # Configure spatial component of any stimuli self._configure_stimuli() # Set delays, provided in physical units, in integration steps. self.connectivity.set_idelays(self.integrator.dt) self.horizon = self.connectivity.idelays.max() + 1 # Reshape integrator.noise.nsig, if necessary. if isinstance(self.integrator, integrators.IntegratorStochastic): self._configure_integrator_noise() # Configure Monitors to work with selected Model, etc... self._configure_monitors() # TODO: find out why the model instance is different in simulator and interface... self.tvb_spikeNet_interface.configure(self.model) dummy = -numpy.ones((self.connectivity.number_of_regions, )) dummy[self.tvb_spikeNet_interface.spiking_nodes_ids] = 0.0 # Create TVB model parameter for SpikeNet to target for param in self.tvb_spikeNet_interface.spikeNet_to_tvb_params: setattr(self.model, param, dummy) # Setup Spiking Simulator configure() and Run() method self.configure_spiking_simulator = self.tvb_spikeNet_interface.spiking_network.configure self.run_spiking_simulator = self.tvb_spikeNet_interface.spiking_network.Run # If there are Spiking nodes and are represented exclusively in Spiking Network... if self.tvb_spikeNet_interface.exclusive_nodes and len( self.tvb_spikeNet_interface.spiking_nodes_ids) > 0: # ...zero coupling interface_weights among Spiking nodes: self.connectivity.weights[self.tvb_spikeNet_interface.spiking_nodes_ids] \ [:, self.tvb_spikeNet_interface.spiking_nodes_ids] = 0.0 # Setup history # TODO: Reflect upon the idea to allow SpikeNet initialization and history setting via TVB self._configure_history(self.initial_conditions) # TODO: Shall we implement a parallel implentation for multiple modes for SpikeNet as well?! if self.current_state.shape[2] > 1: raise_value_error( "Multiple modes' simulation not supported for TVB multiscale simulations!\n" "Current modes number is %d." % self.initial_conditions.shape[3]) # Estimate of memory usage. self._census_memory_requirement() return self