def setUpClass(cls): """ Compile the network for this test """ # neuron defintions common used for test cases local_eq = Neuron( equations=""" noise = Uniform(0,1) r = t """ ) global_eq = Neuron( equations=""" noise = Uniform(0,1) : population glob_r = t : population r = t """ ) mixed_eq = Neuron( parameters="glob_par = 1.0: population", equations=""" r = t + glob_par """ ) bound_eq = Neuron( parameters=""" min_r=1.0: population max_r=3.0: population """, equations=""" r = t : min=min_r, max=max_r """ ) tc_loc_up_pop = Population(3, local_eq) tc_glob_up_pop = Population(3, global_eq) tc_mixed_up_pop = Population(3, mixed_eq) tc_bound_up_pop = Population(3, bound_eq) m = Monitor(tc_bound_up_pop, 'r') cls.test_net = Network() cls.test_net.add([tc_loc_up_pop, tc_glob_up_pop, tc_mixed_up_pop, tc_bound_up_pop, m]) cls.test_net.compile(silent=True) cls.net_loc_pop = cls.test_net.get(tc_loc_up_pop) cls.net_glob_pop = cls.test_net.get(tc_glob_up_pop) cls.net_mix_pop = cls.test_net.get(tc_mixed_up_pop) cls.net_bound_pop = cls.test_net.get(tc_bound_up_pop) cls.net_m = cls.test_net.get(m)
def setUpClass(self): """ Compile the network for this test. Adapted the example from documentation. """ SimpleSpike = Neuron(equations="mp=g_exc", spike="mp >= 1.0", reset="") inp = Population(1, neuron=Neuron(equations="r=sin(t)")) out = Population(1, neuron=SimpleSpike) m = Monitor(out, "mp") proj = CurrentInjection(inp, out, 'exc') proj.connect_current() self.test_net = Network() self.test_net.add([inp, out, proj, m]) self.test_net.compile(silent=True) self.output = self.test_net.get(out) self.m = self.test_net.get(m)
def setUpClass(cls): """ Build up the network """ simple_emit = Neuron(spike="t==1", ) simple_recv = Neuron(equations=""" g_exc1 = 0 g_exc2 = 0 g_exc3 = 0 """, spike="g_exc1>30") # simple in/out populations in_pop = Population(5, neuron=simple_emit) out_pop = Population(2, neuron=simple_recv) # create the projections for the test cases (TC) # TC: no delay proj = Projection(pre=in_pop, post=out_pop, target="exc1") proj.connect_all_to_all(weights=1.0, storage_format="csr") # TC: uniform delay proj_u = Projection(pre=in_pop, post=out_pop, target="exc2") proj_u.connect_all_to_all(weights=1.0, delays=2.0, storage_format="csr") # TC: non-uniform delay proj_nu = Projection(pre=in_pop, post=out_pop, target="exc3") proj_nu.connect_all_to_all(weights=1.0, delays=Uniform(2, 10)) # Monitor to record the currents m = Monitor(out_pop, ["g_exc1", "g_exc2", "g_exc3"]) # build network and store required object # instances net = Network() net.add([in_pop, out_pop, proj, proj_u, proj_nu, m]) cls.test_net = net cls.test_net.compile(silent=True) cls.test_g_exc_m = net.get(m) cls.test_proj = net.get(proj_nu)
def setUpClass(self): """ Compile the network for this test """ BuiltinFuncs = Neuron(parameters=""" base = 2.0 """, equations=""" r = modulo(t,3) pr = power(base,3) clip_below = clip(-2, -1, 1) clip_within = clip(0, -1, 1) clip_above = clip(2, -1, 1) """) pop1 = Population(1, BuiltinFuncs) mon = Monitor(pop1, ['r', 'pr', 'clip_below', 'clip_within', 'clip_above']) self.test_net = Network() self.test_net.add([pop1, mon]) self.test_net.compile(silent=True) self.test_mon = self.test_net.get(mon)
v_tmp = v/(2*pi) : int v_new = (v/(2*pi) - v_tmp)*2*pi """, spike="(v_new > pi)*(v_old < pi)") # population setup pop1 = Population(N, neuron=Theta, name="ThetaPop1") pop1.eta = eta + D * np.tan( (np.pi / 2) * (2 * np.arange(1, N + 1) - N - 1) / (N + 1)) # projection setup proj = Projection(pre=pop1, post=pop1, target='exc', name='fb') proj.connect_all_to_all(100.0 / N, allow_self_connections=False) # monitoring obs = Monitor(pop1, variables=['spike', 'v_new'], start=True, period=0.01) # simulation compile() simulate(duration=T) # conversion to pyrates theta = pyrates_from_annarchy(monitors=[obs], vars=['v_new'], pop_average=False) rate = pyrates_from_annarchy(monitors=[obs], vars=['spike'], pop_average=True) plt.plot(theta) plt.figure() plt.plot(rate) plt.show()
# input #steps = int(T/dt) #I_e_tmp = 5.0 + np.random.randn(steps, Ne) * 50.0 * np.sqrt(dt) # input current for excitatory neurons #I_i_tmp = 4.0 + np.random.randn(steps, Ni) * 44.0 * np.sqrt(dt) # input current for inhibitory neurons #I_e = TimedArray(rates=I_e_tmp, name="E_inp") #I_i = TimedArray(rates=I_i_tmp, name="I_inp") #inp_e = Projection(pre=I_e, post=E, target='exc') #inp_i = Projection(pre=I_i, post=I, target='exc') #inp_e.connect_one_to_one(1.0) #inp_i.connect_one_to_one(1.0) E.i_offset = 5.0 I.i_offset = 2.0 # monitoring obs_e = Monitor(E, variables=['spike', 'v'], start=True) obs_i = Monitor(I, variables=['spike', 'v'], start=True) # simulation ############ # annarchy simulation net = Network(everything=True) net.compile() net.simulate(duration=T) # conversion to pyrates rate_e = pyrates_from_annarchy(monitors=[net.get(obs_e)], vars=['spike'], pop_average=True) rate_i = pyrates_from_annarchy(monitors=[net.get(obs_i)],
def grid_search_annarchy(param_grid: dict, param_map: dict, dt: float, simulation_time: float, inputs: dict, outputs: dict, sampling_step_size: Optional[float] = None, permute_grid: bool = False, circuit=None, **kwargs) -> DataFrame: """Function that runs multiple parametrizations of the same circuit in parallel and returns a combined output. Parameters ---------- param_grid Key-value pairs for each circuit parameter that should be altered over different circuit parametrizations. param_map Key-value pairs that map the keys of param_grid to concrete circuit variables. dt Simulation step-size in s. simulation_time Simulation time in s. inputs Inputs as provided to the `run` method of `:class:ComputeGraph`. outputs Outputs as provided to the `run` method of `:class:ComputeGraph`. sampling_step_size Sampling step-size as provided to the `run` method of `:class:ComputeGraph`. permute_grid If true, all combinations of the provided param_grid values will be realized. If false, the param_grid values will be traversed pairwise. circuit Instance of ANNarchy network. kwargs Additional keyword arguments passed to the `:class:ComputeGraph` initialization. Returns ------- DataFrame Simulation results stored in a multi-index data frame where each index lvl refers to one of the parameters of param_grid. """ from ANNarchy import Population, Projection, Network, TimedArray, Monitor, ANNarchyException # linearize parameter grid if necessary if type(param_grid) is dict: param_grid = linearize_grid(param_grid, permute_grid) # create annarchy net if necessary if circuit is None: circuit = Network(everything=True) # assign parameter updates to each circuit and combine them to unconnected network circuit_names = [] param_info = [] param_split = "__" val_split = "--" comb = "_" populations, projections = {}, {} for n in range(param_grid.shape[0]): # copy and re-parametrize populations try: for p in circuit.get_populations(): name = f'net{n}/{p.name}' p_new = Population(geometry=p.geometry, neuron=p.neuron_type, name=name, stop_condition=p.stop_condition, storage_order=p._storage_order, copied=False) p_new = adapt_pop(p_new, param_grid.iloc[n, :], param_map) populations[name] = p_new # add input to population for node, inp in inputs.items(): if node in name: inp_name = f'{name}_inp' inp = TimedArray(rates=inp, name=inp_name) proj = Projection(pre=inp, post=p_new, target='exc') proj.connect_one_to_one(1.0) populations[inp_name] = inp projections[inp_name] = proj except ANNarchyException: pass # copy and re-parametrize projections try: for c in circuit.get_projections(): source = c.pre if type(c.pre) is str else c.pre.name target = c.post if type(c.post) is str else c.post.name source = f'net{n}/{source}' target = f'net{n}/{target}' name = f'{source}/{target}/{c.name}' c_new = Projection(pre=source, post=target, target=c.target, synapse=c.synapse_type, name=name, copied=False) c_new._store_connectivity(c._connection_method, c._connection_args, c._connection_delay, c._storage_format) c_new = adapt_proj(c_new, param_grid.iloc[n, :], param_map) projections[name] = c_new except ANNarchyException: pass # collect parameter and circuit name infos circuit_names.append(f'net{n}') param_names = list(param_grid.columns.values) param_info_tmp = [f"{param_names[i]}{val_split}{val}" for i, val in enumerate(param_grid.iloc[n, :])] param_info.append(param_split.join(param_info_tmp)) net = Network() for p in populations.values(): net.add(p) for c in projections.values(): net.add(c) # adjust output of simulation to combined network nodes = [p.name for p in circuit.get_populations()] out_names, var_names, out_lens, monitors, monitor_names = [], [], [], [], [] for out_key, out in outputs.copy().items(): out_names_tmp, out_lens_tmp = [], [] if out[0] in nodes: for i, name in enumerate(param_info): out_tmp = list(out) out_tmp[0] = f'{circuit_names[i]}/{out_tmp[0]}' p = net.get_population(out_tmp[0]) monitors.append(Monitor(p, variables=out_tmp[-1], period=sampling_step_size, start=True, net_id=net.id)) monitor_names.append(f'{name}{param_split}out_var{val_split}{out_key}{comb}{out[0]}') var_names.append(out_tmp[-1]) out_names_tmp.append(f'{out_key}{comb}{out[0]}') out_lens_tmp.append(p.geometry[0]) elif out[0] == 'all': for node in nodes: for i, name in enumerate(param_info): out_tmp = list(out) out_tmp[0] = f'{circuit_names[i]}/{node}' p = net.get_population(out_tmp[0]) monitors.append(Monitor(p, variables=out_tmp[-1], period=sampling_step_size, start=True, net_id=net.id)) monitor_names.append(f'{name}{param_split}out_var{val_split}{out_key}{comb}{node}') var_names.append(out_tmp[-1]) out_names_tmp.append(f'{out_key}{comb}{node}') out_lens_tmp.append(p.geometry[0]) else: node_found = False for node in nodes: if out[0] in node: node_found = True for i, name in enumerate(param_info): out_tmp = list(out) out_tmp[0] = f'{circuit_names[i]}/{node}' p = net.get_population(out_tmp[0]) monitors.append(Monitor(p, variables=out_tmp[-1], period=sampling_step_size, start=True, net_id=net.id)) monitor_names.append(f'{name}{param_split}out_var{val_split}{out_key}{comb}{node}') var_names.append(out_tmp[-1]) out_names_tmp.append(f'{out_key}{comb}{node}') out_lens_tmp.append(p.geometry[0]) if not node_found: raise ValueError(f'Invalid output identifier in output: {out_key}. ' f'Node {out[0]} is not part of this network') out_names += list(set(out_names_tmp)) out_lens += list(set(out_lens_tmp)) #net.add(monitors) # simulate the circuits behavior net.compile() net.simulate(duration=simulation_time) # transform output into pyrates-compatible data format results = pyrates_from_annarchy(monitors, vars=list(set(var_names)), monitor_names=monitor_names, **kwargs) # transform results into long-form dataframe with changed parameters as columns multi_idx = [param_grid[key].values for key in param_grid.keys()] n_iters = len(multi_idx[0]) outs = [] for out_name, out_len in zip(out_names, out_lens): outs += [f'{out_name}_n{i}' for i in range(out_len)] * n_iters multi_idx_final = [] for idx in multi_idx: for val in idx: for out_len in out_lens: multi_idx_final += [val]*len(out_names)*out_len index = MultiIndex.from_arrays([multi_idx_final, outs], names=list(param_grid.keys()) + ["out_var"]) index = MultiIndex.from_tuples(list(set(index)), names=list(param_grid.keys()) + ["out_var"]) results_final = DataFrame(columns=index, data=np.zeros_like(results.values), index=results.index) for col in results.keys(): params = col.split(param_split) indices = [None] * len(results_final.columns.names) for param in params: var, val = param.split(val_split)[:2] idx = list(results_final.columns.names).index(var) try: indices[idx] = float(val) except ValueError: indices[idx] = val results_final.loc[:, tuple(indices)] = results[col].values return results_final