Beispiel #1
0
    def __init__(self, target, variables):
        self.target = target
        for mon_var in variables:
            if not hasattr(target, mon_var):
                raise errors.ModelDefError(
                    f"Item {mon_var} isn't defined in model {target}, "
                    f"so it can not be monitored.")

        item_names = []
        mon_indices = []
        item_content = {}
        if variables is not None:
            if isinstance(variables, (list, tuple)):
                for mon_var in variables:
                    if isinstance(mon_var, str):
                        var_data = getattr(target, mon_var)
                        mon_key = mon_var
                        mon_idx = None
                        mon_shape = ops.shape(var_data)
                    elif isinstance(mon_var, (tuple, list)):
                        mon_key = mon_var[0]
                        var_data = getattr(target, mon_key)
                        mon_idx = mon_var[1]
                        mon_shape = ops.shape(mon_idx)  # TODO: matrix index
                    else:
                        raise errors.ModelUseError(
                            f'Unknown monitor item: {str(mon_var)}')
                    item_names.append(mon_key)
                    mon_indices.append(mon_idx)
                    dtype = var_data.dtype if hasattr(var_data,
                                                      'dtype') else None
                    item_content[mon_var] = ops.zeros((1, ) + mon_shape,
                                                      dtype=dtype)
            elif isinstance(variables, dict):
                for k, v in variables.items():
                    item_names.append(k)
                    mon_indices.append(v)
                    if v is None:
                        shape = ops.shape(getattr(target, k))
                    else:
                        shape = ops.shape(v)
                    val_data = getattr(target, k)
                    dtype = val_data.dtype if hasattr(val_data,
                                                      'dtype') else None
                    item_content[k] = ops.zeros((1, ) + shape, dtype=dtype)
            else:
                raise errors.ModelUseError(
                    f'Unknown monitors type: {type(variables)}')

        self.ts = None
        self.item_names = item_names
        self.item_indices = mon_indices
        self.item_contents = item_content
        self.num_item = len(item_content)
Beispiel #2
0
    def __init__(self, v0, delay_len, before_t0=0., t0=0., dt=None):
        # size
        self.size = ops.shape(v0)

        # delay_len
        self.delay_len = delay_len
        self.dt = backend.get_dt() if dt is None else dt
        self.num_delay = int(math.ceil(delay_len / self.dt))

        # other variables
        self._delay_in = self.num_delay - 1
        self._delay_out = 0
        self.current_time = t0

        # before_t0
        self.before_t0 = before_t0

        # delay data
        self.data = ops.zeros((self.num_delay + 1,) + self.size)
        if callable(before_t0):
            for i in range(self.num_delay):
                self.data[i] = before_t0(t0 + (i - self.num_delay) * self.dt)
        else:
            self.data[:-1] = before_t0
        self.data[-1] = v0
Beispiel #3
0
    def run(self, duration, inputs=(), report=False, report_percent=0.1):
        """The running function.

        Parameters
        ----------
        duration : float, int, tuple, list
            The running duration.
        inputs : list, tuple
            The model inputs with the format of ``[(key, value [operation])]``.
        report : bool
            Whether report the running progress.
        report_percent : float
            The percent of progress to report.
        """

        # times
        # ------
        start, end = utils.check_duration(duration)
        times = ops.arange(start, end, backend.get_dt())
        run_length = ops.shape(times)[0]

        # build run function
        # ------------------
        self.run_func = self.build(inputs, inputs_is_formatted=False, mon_length=run_length, return_code=False)

        # run the model
        # -------------
        res = utils.run_model(self.run_func, times, report, report_percent)
        self.mon.ts = times
        return res
Beispiel #4
0
def period_input(values, durations, dt=None, return_length=False):
    """Format an input current with different periods.

    For example:

    If you want to get an input where the size is 0 bwteen 0-100 ms,
    and the size is 1. between 100-200 ms.
    >>> import numpy as np
    >>> period_input(values=[0, 1],
    >>>              durations=[100, 100])

    Parameters
    ----------
    values : list, np.ndarray
        The current values for each period duration.
    durations : list, np.ndarray
        The duration for each period.
    dt : float
        Default is None.
    return_length : bool
        Return the final duration length.

    Returns
    -------
    current_and_duration : tuple
        (The formatted current, total duration)
    """
    assert len(durations) == len(values), f'"values" and "durations" must be the same length, while ' \
                                          f'we got {len(values)} != {len(durations)}.'

    dt = backend.get_dt() if dt is None else dt

    # get input current shape, and duration
    I_duration = sum(durations)
    I_shape = ()
    for val in values:
        shape = ops.shape(val)
        if len(shape) > len(I_shape):
            I_shape = shape

    # get the current
    start = 0
    I_current = ops.zeros((int(math.ceil(I_duration / dt)),) + I_shape)
    for c_size, duration in zip(values, durations):
        length = int(duration / dt)
        I_current[start: start + length] = c_size
        start += length

    if return_length:
        return I_current, I_duration
    else:
        return I_current
Beispiel #5
0
def constant_input(I_and_duration, dt=None):
    """Format constant input in durations.

    For example:

    If you want to get an input where the size is 0 bwteen 0-100 ms,
    and the size is 1. between 100-200 ms.
    >>> import numpy as np
    >>> constant_input([(0, 100), (1, 100)])
    >>> constant_input([(np.zeros(100), 100), (np.random.rand(100), 100)])

    Parameters
    ----------
    I_and_duration : list
        This parameter receives the current size and the current
        duration pairs, like `[(Isize1, duration1), (Isize2, duration2)]`.
    dt : float
        Default is None.

    Returns
    -------
    current_and_duration : tuple
        (The formatted current, total duration)
    """
    dt = backend.get_dt() if dt is None else dt

    # get input current dimension, shape, and duration
    I_duration = 0.
    I_dim = 0
    I_shape = ()
    for I in I_and_duration:
        I_duration += I[1]
        shape = ops.shape(I[0])
        if len(shape) > len(I_shape):
            I_shape = shape

    # get the current
    I_current = ops.zeros((int(math.ceil(I_duration / dt)),) + I_shape)
    start = 0
    for c_size, duration in I_and_duration:
        length = int(duration / dt)
        I_current[start: start + length] = c_size
        start += length
    return I_current, I_duration
Beispiel #6
0
    def __init__(self, size, delay_time):
        if isinstance(size, int):
            size = (size, )
        self.size = tuple(size)
        self.delay_time = delay_time

        if isinstance(delay_time, (int, float)):
            self.uniform_delay = True
            self.delay_num_step = int(math.ceil(
                delay_time / backend.get_dt())) + 1
            self.delay_data = ops.zeros((self.delay_num_step, ) + self.size)
        else:
            if not len(self.size) == 1:
                raise NotImplementedError(
                    f'Currently, BrainPy only supports 1D heterogeneous delays, while does '
                    f'not implement the heterogeneous delay with {len(self.size)}-dimensions.'
                )
            self.num = size2len(size)
            if isinstance(delay_time, type(ops.as_tensor([1]))):
                assert ops.shape(delay_time) == self.size
            elif callable(delay_time):
                delay_time2 = ops.zeros(size)
                for i in range(size[0]):
                    delay_time2[i] = delay_time()
                delay_time = delay_time2
            else:
                raise NotImplementedError(
                    f'Currently, BrainPy does not support delay type '
                    f'of {type(delay_time)}: {delay_time}')
            self.uniform_delay = False
            delay = delay_time / backend.get_dt()
            dint = ops.as_tensor(delay_time / backend.get_dt(), dtype=int)
            ddiff = (delay - dint) >= 0.5
            self.delay_num_step = ops.as_tensor(delay + ddiff, dtype=int) + 1
            self.delay_data = ops.zeros((max(self.delay_num_step), ) + size)
            self.diag = ops.arange(self.num)

        self.delay_in_idx = self.delay_num_step - 1
        if self.uniform_delay:
            self.delay_out_idx = 0
        else:
            self.delay_out_idx = ops.zeros(self.num, dtype=int)
        self.name = None
Beispiel #7
0
def mat2ij(conn_mat):
    """Get the i-j connections from connectivity matrix.

    Parameters
    ----------
    conn_mat : np.ndarray
        Connectivity matrix with `(num_pre, num_post)` shape.

    Returns
    -------
    conn_tuple : tuple
        (Pre-synaptic neuron indexes,
         post-synaptic neuron indexes).
    """
    if len(ops.shape(conn_mat)) != 2:
        raise errors.ModelUseError('Connectivity matrix must be in the '
                                   'shape of (num_pre, num_post).')
    pre_ids, post_ids = ops.where(conn_mat > 0)
    return ops.as_tensor(pre_ids, dtype=ops.int), \
           ops.as_tensor(post_ids, dtype=ops.int)
Beispiel #8
0
    def run(self, duration, report=False, report_percent=0.1):
        if isinstance(duration, (int, float)):
            duration = [0, duration]
        elif isinstance(duration, (tuple, list)):
            assert len(duration) == 2
            duration = tuple(duration)
        else:
            raise ValueError

        # get the times
        times = ops.arange(duration[0], duration[1], backend.get_dt())
        # reshape the monitor
        for key in self.mon.keys():
            self.mon[key] = ops.zeros((len(times), ) +
                                      ops.shape(self.mon[key])[1:])
        # run the model
        run_model(run_func=self.run_func,
                  times=times,
                  report=report,
                  report_percent=report_percent)
Beispiel #9
0
def format_net_level_inputs(inputs, run_length):
    """Format the inputs of a network.

    Parameters
    ----------
    inputs : tuple
        The inputs.
    run_length : int
        The running length.

    Returns
    -------
    formatted_input : dict
        The formatted input.
    """
    from brainpy.simulation.dynamic_system import DynamicSystem

    # 1. format the inputs to standard
    #    formats and check the inputs
    if not isinstance(inputs, (tuple, list)):
        raise errors.ModelUseError('"inputs" must be a tuple/list.')
    if len(inputs) > 0 and not isinstance(inputs[0], (list, tuple)):
        if isinstance(inputs[0], DynamicSystem):
            inputs = [inputs]
        else:
            raise errors.ModelUseError('Unknown input structure. Only supports '
                                       '"(target, key, value, [operation])".')
    for input in inputs:
        if not 3 <= len(input) <= 4:
            raise errors.ModelUseError('For each target, you must specify '
                                       '"(target, key, value, [operation])".')
        if len(input) == 4:
            if input[3] not in SUPPORTED_INPUT_OPS:
                raise errors.ModelUseError(f'Input operation only supports '
                                           f'"{SUPPORTED_INPUT_OPS}", '
                                           f'not "{input[3]}".')

    # 2. format inputs
    formatted_inputs = {}
    for input in inputs:
        # target
        if isinstance(input[0], DynamicSystem):
            target = input[0]
            target_name = input[0].name
        else:
            raise KeyError(f'Unknown input target: {str(input[0])}')

        # key
        key = input[1]
        if not isinstance(key, str):
            raise errors.ModelUseError('For each input, input[1] must be a string '
                                       'to specify variable of the target.')
        if not hasattr(target, key):
            raise errors.ModelUseError(f'Target {target} does not have key {key}. '
                                       f'So, it can not assign input to it.')

        # value and data type
        val = input[2]
        if isinstance(input[2], (int, float)):
            data_type = 'fix'
        else:
            shape = ops.shape(val)
            if shape[0] == run_length:
                data_type = 'iter'
            else:
                data_type = 'fix'

        # operation
        if len(input) == 4:
            operation = input[3]
        else:
            operation = '+'

        # final result
        if target_name not in formatted_inputs:
            formatted_inputs[target_name] = []
        format_inp = (key, val, operation, data_type)
        formatted_inputs[target_name].append(format_inp)
    return formatted_inputs
Beispiel #10
0
def format_pop_level_inputs(inputs, host, mon_length):
    """Format the inputs of a population.

    Parameters
    ----------
    inputs : tuple, list
        The inputs of the population.
    host : Population
        The host which contains all data.
    mon_length : int
        The monitor length.

    Returns
    -------
    formatted_inputs : tuple, list
        The formatted inputs of the population.
    """
    if inputs is None:
        inputs = []
    if not isinstance(inputs, (tuple, list)):
        raise errors.ModelUseError('"inputs" must be a tuple/list.')
    if len(inputs) > 0 and not isinstance(inputs[0], (list, tuple)):
        if isinstance(inputs[0], str):
            inputs = [inputs]
        else:
            raise errors.ModelUseError('Unknown input structure, only support inputs '
                                       'with format of "(key, value, [operation])".')
    for input in inputs:
        if not 2 <= len(input) <= 3:
            raise errors.ModelUseError('For each target, you must specify "(key, value, [operation])".')
        if len(input) == 3 and input[2] not in SUPPORTED_INPUT_OPS:
            raise errors.ModelUseError(f'Input operation only supports '
                                       f'"{SUPPORTED_INPUT_OPS}", '
                                       f'not "{input[2]}".')

    # format inputs
    # -------------
    formatted_inputs = []
    for input in inputs:
        # key
        if not isinstance(input[0], str):
            raise errors.ModelUseError('For each input, input[0] must be a string '
                                       'to specify variable of the target.')
        key = input[0]
        if not hasattr(host, key):
            raise errors.ModelUseError(f'Input target key "{key}" is not defined in {host}.')

        # value and data type
        val = input[1]
        if isinstance(input[1], (int, float)):
            data_type = 'fix'
        else:
            shape = ops.shape(input[1])
            if shape[0] == mon_length:
                data_type = 'iter'
            else:
                data_type = 'fix'

        # operation
        if len(input) == 3:
            operation = input[2]
        else:
            operation = '+'
        if operation not in SUPPORTED_INPUT_OPS:
            raise errors.ModelUseError(f'Currently, BrainPy only support operations '
                                       f'{SUPPORTED_INPUT_OPS}, '
                                       f'not {operation}')
        # input
        format_inp = (key, val, operation, data_type)
        formatted_inputs.append(format_inp)

    return formatted_inputs