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)
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
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
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])
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)
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)
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)'], }
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']