コード例 #1
0
ファイル: base.py プロジェクト: PKU-NIP-Lab/BrainPy
    def __init__(self, steps=None, name=None):
        super(DynamicalSystem, self).__init__(name=name)

        # step functions
        if steps is None:
            steps = ('update', )
        self.steps = Collector()
        if isinstance(steps, tuple):
            for step in steps:
                if isinstance(step, str):
                    self.steps[step] = getattr(self, step)
                elif callable(step):
                    self.steps[step.__name__] = step
                else:
                    raise ModelBuildError(
                        _error_msg.format(steps[0].__class__, str(steps[0])))
        elif isinstance(steps, dict):
            for key, step in steps.items():
                if callable(step):
                    self.steps[key] = step
                else:
                    raise ModelBuildError(
                        _error_msg.format(steps.__class__, str(steps)))
        else:
            raise ModelBuildError(
                _error_msg.format(steps.__class__, str(steps)))
コード例 #2
0
ファイル: base.py プロジェクト: PKU-NIP-Lab/BrainPy
    def __init__(self, *ds_tuple, steps=None, name=None, **ds_dict):
        # integrative step function
        if steps is None:
            steps = ('update', )
        super(Container, self).__init__(steps=steps, name=name)

        # children dynamical systems
        self.implicit_nodes = Collector()
        for ds in ds_tuple:
            if not isinstance(ds, DynamicalSystem):
                raise ModelBuildError(
                    f'{self.__class__.__name__} receives instances of '
                    f'DynamicalSystem, however, we got {type(ds)}.')
            if ds.name in self.implicit_nodes:
                raise ValueError(
                    f'{ds.name} has been paired with {ds}. Please change a unique name.'
                )
        self.register_implicit_nodes({node.name: node for node in ds_tuple})
        for key, ds in ds_dict.items():
            if not isinstance(ds, DynamicalSystem):
                raise ModelBuildError(
                    f'{self.__class__.__name__} receives instances of '
                    f'DynamicalSystem, however, we got {type(ds)}.')
            if key in self.implicit_nodes:
                raise ValueError(
                    f'{key} has been paired with {ds}. Please change a unique name.'
                )
        self.register_implicit_nodes(ds_dict)
コード例 #3
0
 def check_post_attrs(self, *attrs):
     """Check whether post group satisfies the requirement."""
     if not hasattr(self, 'post'):
         raise ModelBuildError('Please call __init__ function first.')
     for attr in attrs:
         if not isinstance(attr, str):
             raise ValueError(f'Must be string. But got {attr}.')
         if not hasattr(self.post, attr):
             raise ModelBuildError(
                 f'{self} need "pre" neuron group has attribute "{attr}".')
コード例 #4
0
ファイル: delays.py プロジェクト: PKU-NIP-Lab/BrainPy
    def __init__(self, size, delay, dtype=None, dt=None, **kwargs):
        # dt
        self.dt = bm.get_dt() if dt is None else dt

        # data size
        if isinstance(size, int): size = (size, )
        if not isinstance(size, (tuple, list)):
            raise ModelBuildError(
                f'"size" must a tuple/list of int, but we got {type(size)}: {size}'
            )
        self.size = tuple(size)

        # delay time length
        self.delay = delay

        # data and operations
        if isinstance(delay, (int, float)):  # uniform delay
            self.uniform_delay = True
            self.num_step = int(pm.ceil(delay / self.dt)) + 1
            self.out_idx = bm.Variable(bm.array([0], dtype=bm.uint32))
            self.in_idx = bm.Variable(
                bm.array([self.num_step - 1], dtype=bm.uint32))
            self.data = bm.Variable(
                bm.zeros((self.num_step, ) + self.size, dtype=dtype))

        else:  # non-uniform delay
            self.uniform_delay = False
            if not len(self.size) == 1:
                raise NotImplementedError(
                    f'Currently, BrainPy only supports 1D heterogeneous '
                    f'delays, while we got the heterogeneous delay with '
                    f'{len(self.size)}-dimensions.')
            self.num = size2len(size)
            if bm.ndim(delay) != 1:
                raise ModelBuildError(f'Only support a 1D non-uniform delay. '
                                      f'But we got {delay.ndim}D: {delay}')
            if delay.shape[0] != self.size[0]:
                raise ModelBuildError(
                    f"The first shape of the delay time size must "
                    f"be the same with the delay data size. But "
                    f"we got {delay.shape[0]} != {self.size[0]}")
            delay = bm.around(delay / self.dt)
            self.diag = bm.array(bm.arange(self.num), dtype=bm.int_)
            self.num_step = bm.array(delay, dtype=bm.uint32) + 1
            self.in_idx = bm.Variable(self.num_step - 1)
            self.out_idx = bm.Variable(bm.zeros(self.num, dtype=bm.uint32))
            self.data = bm.Variable(
                bm.zeros((self.num_step.max(), ) + size, dtype=dtype))

        super(ConstantDelay, self).__init__(**kwargs)
コード例 #5
0
ファイル: neurons.py プロジェクト: PKU-NIP-Lab/BrainPy
  def __init__(self, size, times, indices, need_sort=True, name=None):
    super(SpikeTimeInput, self).__init__(size=size, name=name)

    # parameters
    if len(indices) != len(times):
      raise ModelBuildError(f'The length of "indices" and "times" must be the same. '
                            f'However, we got {len(indices)} != {len(times)}.')
    self.num_times = len(times)

    # data about times and indices
    self.i = bm.Variable(bm.zeros(1, dtype=bm.int_))
    self.times = bm.Variable(bm.asarray(times, dtype=bm.float_))
    self.indices = bm.Variable(bm.asarray(indices, dtype=bm.int_))
    self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))
    if need_sort:
      sort_idx = bm.argsort(times)
      self.indices.value = self.indices[sort_idx]
      self.times.value = self.times[sort_idx]

    # functions
    def cond_fun(t):
      return bm.logical_and(self.i[0] < self.num_times, t >= self.times[self.i[0]])

    def body_fun(t):
      self.spike[self.indices[self.i[0]]] = True
      self.i[0] += 1

    self._run = bm.make_while(cond_fun, body_fun, dyn_vars=self.vars())
コード例 #6
0
ファイル: base.py プロジェクト: PKU-NIP-Lab/BrainPy
    def register_constant_delay(self, key, size, delay, dtype=None):
        """Register a constant delay, whose update method will be appended into
    the ``self.steps`` in this host class.

    >>> import brainpy as bp
    >>> group = bp.NeuGroup(10)
    >>> group.steps
    {'update': <bound method NeuGroup.update of <brainpy.simulation.brainobjects.neuron.NeuGroup object at 0xxxx>>}
    >>> delay1 = group.register_constant_delay('delay1', size=(10,), delay=2)
    >>> delay1
    <brainpy.simulation.brainobjects.delays.ConstantDelay at 0x219d5188280>
    >>> group.steps
    {'update': <bound method NeuGroup.update of <brainpy.simulation.brainobjects.neuron.NeuGroup object at 0xxxx>>,
     'delay1_update': <bound method ConstantDelay.update of <brainpy.simulation.brainobjects.delays.ConstantDelay object at 0xxxx>>}
    >>> delay1.data.shape
    (20, 10)

    Parameters
    ----------
    key : str
      The delay name.
    size : int, list of int, tuple of int
      The delay data size.
    delay : int, float, ndarray
      The delay time, with the unit same with `brainpy.math.get_dt()`.
    dtype : optional
      The data type.

    Returns
    -------
    delay : ConstantDelay
        An instance of ConstantDelay.
    """
        global ConstantDelay
        if ConstantDelay is None:
            from brainpy.building.brainobjects.delays import ConstantDelay

        if not hasattr(self, 'steps'):
            raise ModelBuildError(
                'Please initialize the super class first before '
                'registering constant_delay. \n\n'
                'super(YourClassName, self).__init__(**kwargs)')
        if not key.isidentifier():
            raise ValueError(f'{key} is not a valid identifier.')
        cdelay = ConstantDelay(size=size,
                               delay=delay,
                               name=f'{self.name}_delay_{key}',
                               dtype=dtype)
        self.steps[f'{key}_update'] = cdelay.update
        return cdelay
コード例 #7
0
    def __init__(self, pre, post, conn=None, name=None, steps=('update', )):
        # pre or post neuron group
        # ------------------------
        if not isinstance(pre, NeuGroup):
            raise ModelBuildError('"pre" must be an instance of NeuGroup.')
        if not isinstance(post, NeuGroup):
            raise ModelBuildError('"post" must be an instance of NeuGroup.')
        self.pre = pre
        self.post = post

        # connectivity
        # ------------
        if isinstance(conn, TwoEndConnector):
            self.conn = conn(pre.size, post.size)
        elif isinstance(conn, math.ndarray):
            if (pre.num, post.num) != conn.shape:
                raise ModelBuildError(
                    f'"conn" is provided as a matrix, and it is expected '
                    f'to be an array with shape of (pre.num, post.num) = '
                    f'{(pre.num, post.num)}, however we got {conn.shape}')
            self.conn = MatConn(conn_mat=conn)
        elif isinstance(conn, dict):
            if not ('i' in conn and 'j' in conn):
                raise ModelBuildError(
                    f'"conn" is provided as a dict, and it is expected to '
                    f'be a dictionary with "i" and "j" specification, '
                    f'however we got {conn}')
            self.conn = IJConn(i=conn['i'], j=conn['j'])
        elif conn is None:
            self.conn = conn
        else:
            raise ModelBuildError(f'Unknown "conn" type: {conn}')

        # initialize
        # ----------
        super(TwoEndConn, self).__init__(steps=steps, name=name)