Example #1
0
 def __init__(self, variables):
     mon_items = []
     mon_indices = []
     item_content = {}
     if variables is not None:
         if isinstance(variables, (list, tuple)):
             for var in variables:
                 if isinstance(var, str):
                     mon_items.append(var)
                     mon_indices.append(None)
                     item_content[var] = backend.zeros((1, 1))
                 elif isinstance(var, (tuple, list)):
                     mon_items.append(var[0])
                     mon_indices.append(var[1])
                     item_content[var[0]] = backend.zeros((1, 1))
                 else:
                     raise errors.ModelUseError(
                         f'Unknown monitor item: {str(var)}')
         elif isinstance(variables, dict):
             for k, v in variables.items():
                 mon_items.append(k)
                 mon_indices.append(v)
                 item_content[k] = backend.zeros((1, 1))
         else:
             raise errors.ModelUseError(
                 f'Unknown monitors type: {type(variables)}')
     super(Monitor, self).__init__(ts=None,
                                   vars=mon_items,
                                   indices=mon_indices,
                                   num_item=len(item_content),
                                   **item_content)
Example #2
0
def ij2mat(i, j, num_pre=None, num_post=None):
    """Convert i-j connection to matrix connection.

    Parameters
    ----------
    i : list, np.ndarray
        Pre-synaptic neuron index.
    j : list, np.ndarray
        Post-synaptic neuron index.
    num_pre : int
        The number of the pre-synaptic neurons.
    num_post : int
        The number of the post-synaptic neurons.

    Returns
    -------
    conn_mat : np.ndarray
        A 2D ndarray connectivity matrix.
    """
    if len(i) != len(j):
        raise errors.ModelUseError('"i" and "j" must be the equal length.')
    if num_pre is None:
        print(
            'WARNING: "num_pre" is not provided, the result may not be accurate.'
        )
        num_pre = i.max()
    if num_post is None:
        print(
            'WARNING: "num_post" is not provided, the result may not be accurate.'
        )
        num_post = j.max()
    conn_mat = backend.zeros((num_pre, num_post))
    conn_mat[i, j] = 1.
    return conn_mat
Example #3
0
    def __init__(self, v0, delay_len, before_t0=0., t0=0., dt=None):
        # size
        self.size = backend.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 = backend.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
Example #4
0
 def reshape(self, run_length):
     for var in self['vars']:
         val = self[var]
         shape = backend.shape(val)
         if run_length < shape[0]:
             self[var] = val[:run_length]
         elif run_length > shape[0]:
             append = backend.zeros((run_length - shape[0], ) + shape[1:])
             self[var] = backend.vstack([val, append])
Example #5
0
    def __init__(self, size, delay_time):
        self.delay_time = delay_time
        self.delay_num_step = int(math.ceil(delay_time / backend.get_dt())) + 1
        self.delay_in_idx = 0
        self.delay_out_idx = self.delay_num_step - 1

        if isinstance(size, int):
            size = (size, )
        size = tuple(size)
        self.delay_data = backend.zeros((self.delay_num_step + 1, ) + size)
Example #6
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 = backend.arange(duration[0], duration[1], backend.get_dt())
        # reshape the monitor
        for key in self.mon.keys():
            self.mon[key] = backend.zeros((len(times), ) +
                                          backend.shape(self.mon[key])[1:])
        # run the model
        run_model(run_func=self.run_func,
                  times=times,
                  report=report,
                  report_percent=report_percent)
Example #7
0
    def get_monitor_func(self, mon_length, show_code=False):
        mon = self.host.mon
        if len(mon['vars']) > 0:
            monitor_func_name = 'monitor_step'
            host = self.host.name
            code_scope = {host: self.host}
            code_lines = [f'def {monitor_func_name}(_i):']
            for key in mon['vars']:
                if not hasattr(self.host, key):
                    raise errors.ModelUseError(
                        f'{self.host} do not have {key}, '
                        f'thus it cannot be monitored.')

                # initialize monitor array #
                shape = backend.shape(getattr(self.host, key))
                mon[key] = backend.zeros((mon_length, ) + shape)

                # add line #
                line = f'  {host}.mon["{key}"][_i] = {host}.{key}'
                code_lines.append(line)

            # function
            code = '\n'.join(code_lines)
            if show_code:
                print(code)
                print(code_scope)
                print()
            exec(compile(code, '', 'exec'), code_scope)
            self.set_data(monitor_func_name, code_scope[monitor_func_name])
            # results
            self.formatted_funcs['monitor'] = {
                'func': code_scope[monitor_func_name],
                'scope': {
                    host: self.host
                },
                'call': [f'{host}.{monitor_func_name}(_i)'],
            }
Example #8
0
    def __init__(self,
                 size,
                 integrals,
                 target_vars,
                 fixed_vars,
                 pars_update,
                 scope,
                 show_code=False):
        """Trajectory Class.

        Parameters
        ----------
        size : int, tuple, list
            The network size.
        integrals : list of functions, function
            The integral functions.
        target_vars : dict
            The target variables, with the format of "{key: initial_v}".
        fixed_vars : dict
            The fixed variables, with the format of "{key: fixed_v}".
        pars_update : dict
            The parameters to update.
        scope :
        """
        if callable(integrals):
            integrals = (integrals, )
        elif isinstance(integrals, (list, tuple)) and callable(integrals[0]):
            integrals = tuple(integrals)
        else:
            raise ValueError
        self.integrals = integrals
        self.target_vars = target_vars
        self.fixed_vars = fixed_vars
        self.pars_update = pars_update
        self.scope = {key: val for key, val in scope.items()}
        self.show_code = show_code

        # check network size
        if isinstance(size, int):
            size = (size, )
        elif isinstance(size, (tuple, list)):
            assert isinstance(size[0], int)
            size = tuple(size)
        else:
            raise ValueError

        # monitors, variables, parameters
        self.mon = DictPlus()
        self.vars_and_pars = DictPlus()
        for key, val in target_vars.items():
            self.vars_and_pars[key] = backend.ones(size) * val
            self.mon[key] = backend.zeros((1, ) + size)
        for key, val in fixed_vars.items():
            self.vars_and_pars[key] = backend.ones(size) * val
        for key, val in pars_update.items():
            self.vars_and_pars[key] = val
        self.scope['VP'] = self.vars_and_pars
        self.scope['MON'] = self.mon
        self.scope['_fixed_vars'] = fixed_vars

        code_lines = ['def run_func(_t, _i, _dt):']
        for integral in integrals:
            func_name = integral.__name__
            self.scope[func_name] = integral
            # update the step function
            assigns = [f'VP["{var}"]' for var in integral.variables]
            calls = [f'VP["{var}"]' for var in integral.variables]
            calls.append('_t')
            calls.extend([f'VP["{var}"]' for var in integral.parameters[1:]])
            code_lines.append(
                f'  {", ".join(assigns)} = {func_name}({", ".join(calls)})')
            # reassign the fixed variables
            for key, val in fixed_vars.items():
                code_lines.append(f'  VP["{key}"][:] = _fixed_vars["{key}"]')
        # monitor the target variables
        for key in target_vars.keys():
            code_lines.append(f'  MON["{key}"][_i] = VP["{key}"]')
        # compile
        code = '\n'.join(code_lines)
        if show_code:
            print(code)
            print(self.scope)
            print()

        # recompile
        exec(compile(code, '', 'exec'), self.scope)
        self.run_func = self.scope['run_func']