OSCR

A NEST-based framework unlocks massively parallel simulation of networks of multi-compartment neurons with customizable subcellular dynamics.

Code ↔ Paper

5 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 5 matches
  1. [1] § Methods › Simulation details › Winner-take-all network ↔ prepare_nest_parameters.py, lines 46 to 109 · score 0.79 · Poisson noise, excitatory populations, Poisson generators, inhibitory neurons, stimulated, recurrently · Report a mismatch
  2. [2] § Methods › Simulation details › Benchmarking and scaling experiments ↔ nest_reset_create_connect_simulate.py, lines 187 to 225 · score 0.70 · inh connections, inh exc, inhibitory neurons, excitatory neurons, synapses, weight · Report a mismatch
  3. [3] § Results › Toolchain overview ↔ cm_neuron.py, lines 25 to 68 · score 0.63 · reversal potential, coupling conductance, leak conductance, capacitance · Report a mismatch
  4. [4] § Results › Toolchain overview ↔ cm_neuron_nestml.py, lines 37 to 107 · score 0.63 · reversal potential, coupling conductance, leak conductance, capacitance · Report a mismatch
  5. [5] § Methods › Simulation details › Winner-take-all network ↔ nest_reset_create_connect_simulate.py, lines 12 to 69 · score 0.53 · Ca AdEx, excitatory neurons, plastic, populations, connected, NESTML · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 637 lines · 32 KB · no license · 2 matches

  1. import nest
  2. from cm_neuron import create_cm_neuron
  3. from cm_neuron_nestml import create_nestml_neuron, create_receptor_mapping
  4. from synaptic_io import *
  5. # 2024-1002
  6. # List of receptors used in Ca-AdEx neuron
  7. # It should be moved in a different file (eg. Ca-AdEx_neural_params.yaml)
  8. GABA_soma, AMPA_soma, GABA_dist, AMPA_dist, REFRACT_soma, ADAPT_soma, BETA_dist, NMDA_soma, AMPA_NMDA_soma, ALPHAexc_soma, ALPHAinh_soma, ALPHAexc_dist, ALPHAinh_dist, NMDA_dist, AMPA_NMDA_dist = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  9. def nest_reset_create_connect_simulate(nest_pms, num_threads, verbose):
  10. sim_completed=False
  11. sim_pms=nest_pms["sim_pms"]
  12. use_nestml=nest_pms["use_nestml"]
  13. nest.ResetKernel()
  14. nest.local_num_threads = 4
  15. if use_nestml:
  16. nest.Install("ca_adex_2expsyn_module")
  17. nest.SetKernelStatus({"resolution": sim_pms["resolution_ms"]})
  18. nest.SetKernelStatus({'local_num_threads':num_threads})
  19. num_exc_neu_per_pop = nest_pms["network"]["num_exc_neu_per_pop"]
  20. num_exc_pop = nest_pms["network"]["num_exc_pop"]
  21. conn_rule = nest_pms["network"]["conn_rule"]
  22. p_conn_exc = nest_pms["network"]["p_conn_exc"]
  23. p_conn_inh = nest_pms["network"]["p_conn_exc"]
  24. default_plasticity = nest_pms["network"]["default_plasticity"]
  25. use_single_compartment_environment = nest_pms["use_single_compartment_environment"]
  26. print("IN nest_reset_create_connect_simulate: use_single_compartment_environment =", use_single_compartment_environment)
  27. print("IN nest_reset_create_connect_simulate: use_nestml =", use_nestml)
  28. exc_neu_params=nest_pms['exc_neu_params']
  29. if not use_nestml:
  30. if use_single_compartment_environment:
  31. # Create excitatory neuron populations
  32. params=exc_neu_params['equation_params']
  33. params["tau_minus"]={}
  34. params["tau_minus"]=20.0
  35. #nest.Create("iaf_psc_alpha", params={"tau_minus": 20.0})
  36. neurons = [
  37. nest.Create(
  38. "aeif_cond_alpha",
  39. num_exc_neu_per_pop,
  40. params=params
  41. )
  42. for _ in range(num_exc_pop)
  43. ]
  44. else:
  45. # Create excitatory Ca-AdEx neuron populations
  46. nest.CopyModel('static_synapse', 'REFRACT_syn')
  47. nest.CopyModel('static_synapse', 'ADAPT_syn')
  48. nest.CopyModel('static_synapse', 'BAP_syn')
  49. neurons = [
  50. create_cm_neuron(num_exc_neu_per_pop, params=exc_neu_params['equation_params']) for _ in range(num_exc_pop)
  51. ]
  52. else:
  53. neurons = [
  54. create_nestml_neuron(
  55. num_exc_neu_per_pop,
  56. params=exc_neu_params['equation_params'],
  57. multi_comp=not(use_single_compartment_environment)
  58. ) for _ in range(num_exc_pop)
  59. ]
  60. ri = create_receptor_mapping(multi_comp=not(use_single_compartment_environment))
  61. # Create inhibitory neurons
  62. inh_neu_params = nest_pms["inh_neu_params"]
  63. num_inh_neu = nest_pms["network"]["num_inh_neu"]
  64. inh_neurons = nest.Create(
  65. "aeif_cond_alpha",
  66. num_inh_neu,
  67. params=inh_neu_params,
  68. )
  69. # Spike recorders for excitatory and inhibitory populations
  70. recording_pms=nest_pms["recording_pms"]
  71. spike_recorders = [nest.Create("spike_recorder",
  72. {"start": recording_pms["start_ms"], "stop": recording_pms["stop_ms"]})
  73. for _ in range(num_exc_pop)]
  74. inh_spike_recorder = nest.Create("spike_recorder",
  75. {"start": recording_pms["start_ms"], "stop": recording_pms["stop_ms"]})
  76. # Connect spike detectors
  77. for i in range(num_exc_pop):
  78. nest.Connect(neurons[i], spike_recorders[i])
  79. nest.Connect(inh_neurons, inh_spike_recorder)
  80. # 2024-1002
  81. # Added multimeter on Ca-AdEx only (temporary solution)
  82. # Target pop and neu and all the parameters to be specified in a yaml
  83. if not use_nestml:
  84. if use_single_compartment_environment:
  85. multimeter = nest.Create('multimeter', 1, {'record_from': ['V_m'], 'interval': .1,
  86. 'start': recording_pms['start_ms'], 'stop': recording_pms['stop_ms']})
  87. pop = 0
  88. neu = 0
  89. # nest.Connect(multimeter, neurons[pop])
  90. nest.Connect(multimeter, neurons[pop][neu])
  91. else:
  92. # create multimeter to record compartment voltages and various state variables
  93. rec_list = ['v_comp0', 'v_comp1', 'w_5','m_Ca_1','h_Ca_1','i_AMPA_9']
  94. pop = 0
  95. neu = 0
  96. multimeter = nest.Create('multimeter', 1, {'record_from': rec_list, 'interval': .1,
  97. 'start': recording_pms['start_ms'], 'stop': recording_pms['stop_ms']})
  98. # nest.Connect(multimeter, neurons[pop])
  99. nest.Connect(multimeter, neurons[pop][neu])
  100. else:
  101. # create multimeter to record compartment voltages and various state variables
  102. rec_list = ['v_comp0', f'syn_2exp{ri.ALPHAexc_soma}']
  103. if not use_single_compartment_environment:
  104. rec_list.append('v_comp1')
  105. pop = 0
  106. neu = 0
  107. multimeter = nest.Create('multimeter', 1, {'record_from': rec_list, 'interval': .1,
  108. 'start': recording_pms['start_ms'], 'stop': recording_pms['stop_ms']})
  109. # nest.Connect(multimeter, neurons[pop])
  110. nest.Connect(multimeter, neurons[pop][neu])
  111. # Connection specifications
  112. exc_t_ref_ms=nest_pms["exc_t_ref_ms"]
  113. min_syn_delay_ms=nest_pms["network"]["min_syn_delay_ms"]
  114. use_recurrency=nest_pms["network"]["use_exc_recurrency"]
  115. recurrent_weight = nest_pms["network"]["weights"]["exc_to_exc"]
  116. inh_to_exc_weight = nest_pms["network"]["weights"]["inh_to_exc_weight"]
  117. exc_to_inh_weight = nest_pms["network"]["weights"]["exc_to_inh_weight"]
  118. inh_to_inh_weight = nest_pms["network"]["weights"]["inh_to_inh_weight"]
  119. exc_to_exc_delay_ms = min_syn_delay_ms + 1.
  120. inh_to_inh_delay_ms = min_syn_delay_ms + exc_t_ref_ms + 1.0
  121. assert(conn_rule == 'pairwise_bernoulli')
  122. conn_spec_dict_exc = {"rule": conn_rule, "p": p_conn_exc}
  123. conn_spec_dict_inh = {"rule": conn_rule, "p": p_conn_inh}
  124. conn_spec_dict_exc = {"rule": 'all_to_all', "allow_autapses":False}
  125. conn_spec_dict_inh = {"rule": 'all_to_all', "allow_autapses":False}
  126. #set to false the book-keeping of intra-pop and inter pop syn types
  127. present_exc_conn={}
  128. for i in range(num_exc_pop):
  129. present_exc_conn[i]={}
  130. for j in range(num_exc_pop):
  131. present_exc_conn[i][j] = {'synapse_model': False}
  132. #set initial intra-pop connections
  133. for i in range(num_exc_pop):
  134. static_synapse_i_i='static_synapse_'+str(i)+'_'+str(i)
  135. nest.CopyModel('static_synapse',static_synapse_i_i)
  136. syn_spec={"synapse_model": static_synapse_i_i, "weight": recurrent_weight, "delay": exc_to_exc_delay_ms}
  137. if not use_nestml:
  138. if(not use_single_compartment_environment):
  139. syn_spec.update({'receptor_type': ALPHAexc_soma})
  140. else:
  141. syn_spec.update({'receptor_type': ri.ALPHAexc_soma})
  142. nest.Connect(neurons[i], neurons[i], conn_spec=conn_spec_dict_exc, syn_spec=syn_spec)
  143. present_exc_conn[i][i] = {'synapse_model': static_synapse_i_i}
  144. #inter assemblies connections: initial set-up
  145. if nest_pms["network"]["inter_pop_conn"] == True:
  146. inter_pop_weight = nest_pms["network"]["weights"]["inter_pop_weight"]
  147. for i in range(num_exc_pop):
  148. for j in range(num_exc_pop):
  149. if i != j:
  150. static_synapse_i_j='static_synapse_'+str(i)+'_'+str(j)
  151. nest.CopyModel('static_synapse',static_synapse_i_j)
  152. syn_spec={"synapse_model":static_synapse_i_j,"weight": inter_pop_weight * cf_mc, "delay": exc_to_exc_delay_ms}
  153. if not use_nestml:
  154. if(not use_single_compartment_environment):
  155. syn_spec.update({'receptor_type': ALPHAexc_soma})
  156. else:
  157. syn_spec_dict.update({'receptor_type': ri.ALPHAexc_soma})
  158. nest.Connect(neurons[i], neurons[j], conn_spec=conn_spec_dict_exc, syn_spec=syn_spec)
  159. present_exc_conn[i][j]['synapse_model'] = static_synapse_i_j
  160. #inh to inh connections: initial setup
  161. nest.CopyModel('static_synapse','static_synapse_inh_inh')
  162. nest.Connect(inh_neurons, inh_neurons, conn_spec=conn_spec_dict_inh,\
  163. syn_spec={"synapse_model": 'static_synapse_inh_inh', "weight": inh_to_inh_weight, "delay": inh_to_inh_delay_ms})
  164. # Connect inhibitory neurons to all excitatory neurons and vice versa
  165. #before 2024-1006 (QUESTA NON ROMPE IL KERNEL)
  166. inh_to_exc_delay_ms = min_syn_delay_ms + exc_t_ref_ms + 0.55
  167. exc_to_inh_delay_ms = min_syn_delay_ms + 0.5
  168. #IN PROVA QUESTA DOPO FUNZIONA ANCORA
  169. #inh_to_exc_delay_ms = min_syn_delay_ms + 0.55
  170. #exc_to_inh_delay_ms = min_syn_delay_ms + 0.5
  171. #IN PROVA
  172. #inh_to_exc_delay_ms = min_syn_delay_ms + 0.1
  173. #exc_to_inh_delay_ms = min_syn_delay_ms + 0.1
  174. #QUESTA CONFIGURAZIONE FA CRASHARE IL KERNEL
  175. #inh_to_exc_delay_ms = min_syn_delay_ms
  176. #exc_to_inh_delay_ms = min_syn_delay_ms
  177. for i in range(num_exc_pop):
  178. # inh to exc(i)
  179. new_syn_model_inh_exc_n = 'static_synapse_inh_exc_'+str(i)
  180. nest.CopyModel('static_synapse', new_syn_model_inh_exc_n)
  181. syn_spec={"synapse_model": new_syn_model_inh_exc_n, "weight": inh_to_exc_weight, "delay": inh_to_exc_delay_ms}
  182. if not use_nestml:
  183. if(not use_single_compartment_environment):
  184. syn_spec.update({"weight": -inh_to_exc_weight, 'receptor_type': ALPHAinh_soma})
  185. else:
  186. syn_spec.update({
  187. "weight": -inh_to_exc_weight,
  188. "receptor_type": ri.ALPHAinh_soma,
  189. })
  190. nest.Connect(inh_neurons, neurons[i], conn_spec=conn_spec_dict_inh, syn_spec=syn_spec)
  191. # exc(i) to inh
  192. new_syn_model_exc_n_inh = 'static_synapse_exc_' + str(i) + '_inh'
  193. nest.CopyModel('static_synapse', new_syn_model_exc_n_inh)
  194. syn_spec={"synapse_model": new_syn_model_exc_n_inh, "weight": exc_to_inh_weight, "delay": exc_to_inh_delay_ms}
  195. nest.Connect(neurons[i], inh_neurons, conn_spec=conn_spec_dict_exc, syn_spec=syn_spec)
  196. # Create and connect Poisson generators if enabled
  197. use_poisson_generators=nest_pms["network"]["use_poisson_generators"]
  198. if use_poisson_generators:
  199. num_poisson_generators=nest_pms["network"]["num_poisson_generators"]
  200. poisson_rate=nest_pms["poisson"]["poisson_rate"]
  201. pgs = nest.Create("poisson_generator", num_poisson_generators, params={"rate": poisson_rate, 'start': 200.})
  202. poisson_weight=nest_pms["poisson"]["poisson_weight"]
  203. syn_spec={"weight": poisson_weight, "delay": 1.0}
  204. for i in range(num_exc_pop):
  205. if not use_nestml:
  206. if not use_single_compartment_environment:
  207. syn_spec.update({'receptor_type': ALPHAexc_soma})
  208. else:
  209. syn_spec.update({'receptor_type': ri.ALPHAexc_soma})
  210. nest.Connect(pgs, neurons[i], syn_spec=syn_spec)
  211. # Add contextual poisson signal if configured
  212. if 'contextual_poisson' in nest_pms and \
  213. nest_pms['brain_state'] in nest_pms['contextual_poisson']:
  214. # Extract the upper-level configuration parameters
  215. contextual_poisson_config = nest_pms['contextual_poisson'][nest_pms['brain_state']]
  216. # Ensure all required keys are present in the configuration
  217. if all(key in contextual_poisson_config for key in ['events', 'spreading_factor', 'basic_rate', 'poisson_weight']):
  218. events = contextual_poisson_config['events']
  219. spreading_factor = contextual_poisson_config['spreading_factor']
  220. basic_rate = contextual_poisson_config['basic_rate']
  221. poisson_weight = contextual_poisson_config['poisson_weight']
  222. # Iterate through each event in the events list
  223. for event in events:
  224. target_pop = event['target_population']
  225. start_time = event['start_time_ms']
  226. stop_time = event['stop_time_ms']
  227. # Create a Poisson generator for the event
  228. contextual_poisson_gen = nest.Create('poisson_generator', 1, {'rate': basic_rate})
  229. # Set the start and stop times for the generator
  230. nest.SetStatus(contextual_poisson_gen, {'start': start_time, 'stop': stop_time})
  231. # Define the synapse specifications
  232. syn_spec = {'weight': poisson_weight * spreading_factor, "delay": 1.0}
  233. # Connect the generator to the target population
  234. if not use_nestml:
  235. if not use_single_compartment_environment:
  236. syn_spec.update({'receptor_type': AMPA_NMDA_dist})
  237. else:
  238. # if use_single_compartment_environment:
  239. # syn_spec.update({'receptor_type': ri.AMPA_NMDA_soma})
  240. # else:
  241. # syn_spec.update({'receptor_type': ri.AMPA_NMDA_dist})
  242. syn_spec.update({'receptor_type': ri.PSC_context})
  243. nest.Connect(contextual_poisson_gen, neurons[target_pop], syn_spec=syn_spec)
  244. # Add contextual inhibiton signal if configured
  245. if 'contextual_inhibition' in nest_pms and \
  246. nest_pms['brain_state'] in nest_pms['contextual_inhibition']:
  247. # Extract the upper-level configuration parameters
  248. contextual_poisson_config = nest_pms['contextual_inhibition'][nest_pms['brain_state']]
  249. # Ensure all required keys are present in the configuration
  250. if all(key in contextual_poisson_config for key in ['events', 'spreading_factor', 'basic_rate', 'poisson_weight']):
  251. events = contextual_poisson_config['events']
  252. spreading_factor = contextual_poisson_config['spreading_factor']
  253. basic_rate = contextual_poisson_config['basic_rate']
  254. poisson_weight = contextual_poisson_config['poisson_weight']
  255. # Iterate through each event in the events list
  256. for event in events:
  257. target_pop = event['target_population']
  258. start_time = event['start_time_ms']
  259. stop_time = event['stop_time_ms']
  260. # Create a Poisson generator for the event
  261. contextual_poisson_gen = nest.Create('poisson_generator', 1, {'rate': basic_rate})
  262. # Set the start and stop times for the generator
  263. nest.SetStatus(contextual_poisson_gen, {'start': start_time, 'stop': stop_time})
  264. # Define the synapse specifications
  265. syn_spec = {'weight': poisson_weight * spreading_factor, "delay": 1.0}
  266. # Connect the generator to the target population
  267. if not use_nestml:
  268. if not use_single_compartment_environment:
  269. syn_spec.update({'receptor_type': AMPA_NMDA_dist})
  270. else:
  271. # @Willem, please modify the code in the comment towards your nestml specifics
  272. # assert False, "use_nestml option not yet supported: under construction"
  273. if use_single_compartment_environment:
  274. syn_spec.update({'receptor_type': ri.ALPHAinh_soma})
  275. else:
  276. syn_spec.update({'receptor_type': ri.ALPHAinh_dist})
  277. nest.Connect(contextual_poisson_gen, neurons[target_pop], syn_spec=syn_spec)
  278. # DC current injection for all neurons if enabled
  279. use_dc_exc_injectors=nest_pms["use_dc_exc_injectors"]
  280. if use_dc_exc_injectors:
  281. dc_exc_start_ms=nest_pms["dc_exc"]["start_ms"]
  282. dc_exc_stop_ms=nest_pms["dc_exc"]["stop_ms"]
  283. dc_exc_amplitudes=nest_pms["dc_exc"]["dc_exc_amplitudes"]
  284. dc_exc_weight=nest_pms["dc_exc"]["dc_exc_weight"]
  285. dc_exc_delay_ms=nest_pms["dc_exc"]["dc_exc_delay_ms"]
  286. dcgs = [nest.Create("dc_generator", 1,\
  287. {"start": dc_exc_start_ms, "stop": dc_exc_stop_ms, "amplitude": amp})\
  288. for amp in dc_exc_amplitudes]
  289. for i in range(num_exc_pop):
  290. if use_single_compartment_environment:
  291. nest.Connect(dcgs[i], neurons[i],\
  292. syn_spec={'weight': dc_exc_weight, 'delay': dc_exc_delay_ms})
  293. else:
  294. #assert("MC neuron not yet implemented")
  295. nest.Connect(dcgs[i], neurons[i], syn_spec={'weight': dc_exc_weight, 'delay': dc_exc_delay, 'receptor_type': 0})
  296. # Specific DC current injection for inhibitory neurons
  297. use_dc_inh_injector=nest_pms["use_dc_inh_injector"]
  298. if use_dc_inh_injector:
  299. dc_inh_start_ms = nest_pms["dc_inh"]["start_ms"]
  300. dc_inh_stop_ms = nest_pms["dc_inh"]["stop_ms"]
  301. dc_inh_amplitude = nest_pms["dc_inh"]["dc_inh_amplitude"]
  302. dc_inh_weight = nest_pms["dc_inh"]["weight"]
  303. dc_inh_delay_ms = nest_pms["dc_inh"]["delay_ms"]
  304. dc_inh_generator = nest.Create("dc_generator", 1,\
  305. {"start": dc_inh_start_ms, "stop": dc_inh_stop_ms,
  306. "amplitude": dc_inh_amplitude})
  307. nest.Connect(dc_inh_generator, inh_neurons,\
  308. syn_spec={'weight': dc_inh_weight, 'delay': dc_inh_delay_ms})
  309. def make_plastic_conn(source_exc_pop, target_exc_pop, Wmax, verbose):
  310. if verbose:
  311. print("in make_plastic_conn: source and target pops", source_exc_pop, target_exc_pop)
  312. assert(source_exc_pop >= 0 and source_exc_pop < num_exc_pop)
  313. assert(target_exc_pop >= 0 and target_exc_pop < num_exc_pop)
  314. new_syn_model = default_plasticity['synapse_model']+'_'+str(source_exc_pop)+'_'+str(target_exc_pop)
  315. if verbose:
  316. print("in make_plastic_conn: new_syn_model = ", new_syn_model)
  317. if new_syn_model not in nest.Models(mtype='synapses'):
  318. if verbose:
  319. print("in make_plastic_conn: new_syn_model not already among Models")
  320. if present_exc_conn[source_exc_pop][target_exc_pop]['synapse_model'] != False:
  321. if verbose:
  322. print("in make_plastic_conn: present_exc_conn =",present_exc_conn[source_exc_pop][target_exc_pop]['synapse_model'])
  323. print("in make_plastic_conn: before GetConnections (old set)")
  324. existing_conns = nest.GetConnections(neurons[source_exc_pop],
  325. neurons[target_exc_pop],
  326. synapse_model=present_exc_conn[source_exc_pop][target_exc_pop]['synapse_model'])
  327. if verbose:
  328. print("in make_plastic_conn: before Disconnect (old set)")
  329. nest.Disconnect(existing_conns)
  330. if verbose:
  331. print("in make_plastic_conn: after Disconnect (old set)")
  332. present_exc_conn[source_exc_pop][target_exc_pop] = {'synapse_model': False}
  333. conn_spec_dict = conn_spec_dict_exc
  334. nest.CopyModel(default_plasticity['synapse_model'],new_syn_model)
  335. syn_spec_dict = {"synapse_model": new_syn_model,
  336. "Wmax": Wmax,
  337. "tau_plus": default_plasticity['tau_plus'],
  338. "lambda": default_plasticity['lambda'],
  339. "alpha": default_plasticity['alpha'],
  340. "mu_plus": default_plasticity['mu_plus'],
  341. "mu_minus": default_plasticity['mu_minus'],
  342. "weight": default_plasticity['weight'],
  343. "delay": exc_to_exc_delay_ms}
  344. if not use_nestml:
  345. if not use_single_compartment_environment:
  346. syn_spec_dict.update({'receptor_type': ALPHAexc_soma})
  347. else:
  348. syn_spec_dict.update({'receptor_type': ri.ALPHAexc_soma})
  349. if verbose:
  350. print("in make_plastic_conn: before connecting ",new_syn_model)
  351. nest.Connect(neurons[source_exc_pop], neurons[target_exc_pop],
  352. conn_spec=conn_spec_dict, syn_spec=syn_spec_dict)
  353. if verbose:
  354. print("in make_plastic_conn: after connecting ",new_syn_model)
  355. present_exc_conn[source_exc_pop][target_exc_pop] = {'synapse_model': new_syn_model}
  356. if verbose:
  357. print("Wmax =", Wmax, "initial_weight", default_plasticity['weight'])
  358. return
  359. def disconnect_conn(source_exc_pop, target_exc_pop, verbose):
  360. if verbose:
  361. print("in disconnect_conn: source_exc_pop -> target_exc_pop",source_exc_pop, target_exc_pop)
  362. assert(source_exc_pop >= 0 and source_exc_pop < num_exc_pop)
  363. assert(target_exc_pop >= 0 and target_exc_pop < num_exc_pop)
  364. if present_exc_conn[source_exc_pop][target_exc_pop]['synapse_model'] != False:
  365. synapse_model = present_exc_conn[source_exc_pop][target_exc_pop]['synapse_model']
  366. existing_conns = nest.GetConnections(neurons[source_exc_pop],
  367. neurons[target_exc_pop], synapse_model=synapse_model)
  368. nest.Disconnect(existing_conns)
  369. present_exc_conn[source_exc_pop][target_exc_pop] = {'synapse_model': False}
  370. # Next lines reconnect with zero values
  371. conn_spec_dict = conn_spec_dict_exc
  372. new_disconnected_static_syn_model = \
  373. 'static_synapse_weight_zero_'+str(source_exc_pop)+'_'+str(target_exc_pop)
  374. nest.CopyModel('static_synapse',new_disconnected_static_syn_model)
  375. syn_spec_dict = {"synapse_model":new_disconnected_static_syn_model,"weight": 0.0, "delay": exc_to_exc_delay_ms}
  376. if not use_nestml:
  377. if not use_single_compartment_environment:
  378. syn_spec_dict.update({'receptor_type': ALPHAexc_soma})
  379. else:
  380. syn_spec_dict.update({'receptor_type': ri.ALPHAexc_soma})
  381. nest.Connect(neurons[source_exc_pop], neurons[target_exc_pop],
  382. conn_spec=conn_spec_dict, syn_spec=syn_spec_dict)
  383. present_exc_conn[source_exc_pop][target_exc_pop] = {'synapse_model': new_disconnected_static_syn_model, 'weight': 0.0}
  384. return
  385. def perform_event_action(requested_action, tot_simulated_time_ms, verbose):
  386. if verbose:
  387. print("in perform_event_action: requested action:", requested_action, "at time (ms)", tot_simulated_time_ms)
  388. if requested_action['kind']=='store_syn':
  389. #STORE SYN MATRIX
  390. store_syn(requested_action['syn_file_name'], tot_simulated_time_ms, verbose)
  391. elif requested_action['kind']=='disconnect_exc_pop_syn':
  392. #DISCONNECT (several options to select target intra and inter pops)
  393. #can be an integer, a list of integers, or a string
  394. target_exc_pop = requested_action['target_exc_pop']
  395. if isinstance(target_exc_pop, int):
  396. # Perform actions for integer value
  397. disconnect_conn(target_exc_pop, target_exc_pop, verbose)
  398. elif isinstance(target_exc_pop, list):
  399. # The value is a list
  400. # Check that all elements in the list are integers
  401. if all(isinstance(item, int) for item in target_exc_pop):
  402. # Perform actions for list of integers
  403. for item in target_exc_pop:
  404. disconnect_conn(item, item, verbose)
  405. else:
  406. raise TypeError("All items in 'target_exc_pop' list must be integers.")
  407. elif isinstance(target_exc_pop, str):
  408. # The value is a string
  409. # Perform actions for string value
  410. if target_exc_pop == 'all_intra_exc':
  411. for index_target_pop in range(0,num_exc_pop):
  412. disconnect_conn(index_target_pop, index_target_pop, verbose)
  413. elif target_exc_pop == 'all_inter_exc':
  414. for index_source_pop in range(0,num_exc_pop):
  415. for index_target_pop in range(0,num_exc_pop):
  416. if index_source_pop!=index_target_pop:
  417. disconnect_conn(index_source_pop, index_target_pop, verbose)
  418. elif target_exc_pop == 'all_intra_inter_exc':
  419. for index_source_pop in range(0,num_exc_pop):
  420. for index_target_pop in range(0,num_exc_pop):
  421. disconnect_conn(index_source_pop, index_target_pop, verbose)
  422. else:
  423. print("unrecognized command in set plastic synapses")
  424. assert(False)
  425. else:
  426. # Handle unexpected types
  427. raise TypeError(f"Invalid type for 'target_exc_pop': {type(target_exc_pop)}")
  428. elif requested_action['kind']=='exc_plasticity_ON':
  429. #make PLASTIC exc synapses (several options to select target intra and inter pops)
  430. Wmax = recurrent_weight * requested_action['W_max_factor']
  431. #can be an integer, a list of integers, or a string
  432. target_exc_pop = requested_action['target_exc_pop']
  433. if isinstance(target_exc_pop, int):
  434. # Perform actions for integer value
  435. make_plastic_conn(target_exc_pop, target_exc_pop, Wmax, verbose)
  436. elif isinstance(target_exc_pop, list):
  437. # The value is a list
  438. # Check that all elements in the list are integers
  439. if all(isinstance(item, int) for item in target_exc_pop):
  440. # Perform actions for list of integers
  441. for item in target_exc_pop:
  442. make_plastic_conn(item, item, Wmax, verbose)
  443. else:
  444. raise TypeError("All items in 'target_exc_pop' list must be integers.")
  445. elif isinstance(target_exc_pop, str):
  446. # The value is a string
  447. # Perform actions for string value
  448. if target_exc_pop == 'all_intra_exc':
  449. for index_target_pop in range(0,num_exc_pop):
  450. make_plastic_conn(index_target_pop, index_target_pop, Wmax, verbose)
  451. elif target_exc_pop == 'all_inter_exc':
  452. for index_source_pop in range(0,num_exc_pop):
  453. for index_target_pop in range(0,num_exc_pop):
  454. if index_source_pop!=index_target_pop:
  455. make_plastic_conn(index_source_pop, index_target_pop, Wmax, verbose)
  456. elif target_exc_pop == 'all_intra_inter_exc':
  457. for index_source_pop in range(0,num_exc_pop):
  458. for index_target_pop in range(0,num_exc_pop):
  459. make_plastic_conn(index_source_pop, index_target_pop, Wmax, verbose)
  460. else:
  461. print("unrecognized command in set plastic synapses")
  462. assert(False)
  463. else:
  464. # Handle unexpected types
  465. raise TypeError(f"Invalid type for 'target_exc_pop': {type(target_exc_pop)}")
  466. elif requested_action['kind']=='set_learning':
  467. # Set learning rate
  468. learning_rate = default_plasticity['lambda']
  469. alpha = default_plasticity['alpha']
  470. if 'lambda' in requested_action:
  471. learning_rate = requested_action['lambda']
  472. if 'alpha' in requested_action:
  473. alpha = requested_action['alpha']
  474. target_exc_pop = requested_action['target_exc_pop']
  475. assert(target_exc_pop >= 0 and target_exc_pop < num_exc_pop)
  476. # add check if target_exc_pop is in the list of plastic populations (issue #34)
  477. existing_conns_plastic = nest.GetConnections(neurons[target_exc_pop],
  478. neurons[target_exc_pop], synapse_model='stdp_synapse')
  479. nest.SetStatus(existing_conns_plastic, {'lambda': learning_rate, 'alpha': alpha})
  480. print('Set lambda =', learning_rate, 'alpha =', alpha, 'in population', target_exc_pop)
  481. else:
  482. #UNRECOGNIZED
  483. print("in perform_event_action: requested action:",requested_action['kind'],"NOT SUPPORTED")
  484. assert False
  485. return
  486. list_of_syn_matrix_file_names=[]
  487. def store_syn(file_name, tot_simulated_time_ms, verbose):
  488. if(verbose):
  489. print("in store_syn:")
  490. print("will save to file:", file_name)
  491. print("at time (ms):", tot_simulated_time_ms)
  492. array_of_dicts = []
  493. for i in range(num_exc_pop):
  494. synapse_model = present_exc_conn[i][i]['synapse_model']
  495. array_of_dicts.append(\
  496. {"time (ms)": tot_simulated_time_ms,\
  497. "conn_index": i,\
  498. "synapse_model":present_exc_conn[i][i]['synapse_model'],\
  499. "connections": nest.GetConnections(source=neurons[i],target=neurons[i],
  500. synapse_model=synapse_model).get(("source", "target", "weight"), output="pandas")})
  501. with open(file_name, "wb") as f:
  502. pickle.dump(array_of_dicts, f, pickle.HIGHEST_PROTOCOL)
  503. list_of_syn_matrix_file_names.append(file_name)
  504. return
  505. def simulate(verbose):
  506. # Run the simulation
  507. if verbose:
  508. print("in nest_..._simulate: LIST OF PLANNED ACTIONS")
  509. for item in nest_pms['events_pms']:
  510. if 'action' in item:
  511. print("ACTION",item['action'])
  512. if 'sim_period_ms' in item:
  513. if verbose:
  514. print("expected NEXT SIM PERIOD ms",item['sim_period_ms'])
  515. print("in nest_..._simulate: JUST BEFORE ACTUAL EXECUTION")
  516. tot_simulated_time_ms=0.0
  517. if 'events_pms' in nest_pms:
  518. for item in nest_pms['events_pms']:
  519. if 'action' in item:
  520. if verbose:
  521. print("ACTION",item['action'])
  522. #performing the action
  523. perform_event_action(item['action'], tot_simulated_time_ms, verbose)
  524. if 'sim_period_ms' in item:
  525. if verbose:
  526. print("expected NEXT SIM PERIOD ms",item['sim_period_ms'])
  527. next_sim_period_ms = item['sim_period_ms']
  528. else:
  529. next_sim_period_ms = 0.0
  530. if next_sim_period_ms + tot_simulated_time_ms > sim_pms["stop_ms"]:
  531. next_sim_period_ms = sim_pms["stop_ms"] - tot_simulated_time_ms
  532. store_syn('syn_matrix-end_of_sim',sim_pms["stop_ms"],verbose)
  533. if verbose:
  534. print("reduced last sim time ms to", next_sim_period_ms)
  535. print("launching next period of ", next_sim_period_ms, "ms of simulation")
  536. #launching simulation period
  537. if next_sim_period_ms > 0:
  538. nest.Simulate(next_sim_period_ms)
  539. tot_simulated_time_ms += next_sim_period_ms
  540. if verbose:
  541. print("performed until now:",tot_simulated_time_ms, "TOTAL ms of simulation")
  542. if tot_simulated_time_ms < sim_pms["stop_ms"]:
  543. next_sim_period_ms = sim_pms["stop_ms"] - tot_simulated_time_ms
  544. if verbose:
  545. print("ADDING ", next_sim_period_ms, "ms sim to complete expected" ,sim_pms["stop_ms"], "TOTAL ms of simulation")
  546. #possible last simulation period
  547. assert(next_sim_period_ms>0)
  548. nest.Simulate(next_sim_period_ms)
  549. tot_simulated_time_ms += next_sim_period_ms
  550. store_syn('syn_matrix-end_of_sim', tot_simulated_time_ms, verbose)
  551. if verbose:
  552. print("performed until now:",tot_simulated_time_ms, "TOTAL ms of simulation")
  553. assert(tot_simulated_time_ms==sim_pms["stop_ms"])
  554. return
  555. #HERE IS THE SIMULATION
  556. verbose=True
  557. simulate(verbose)
  558. sim_completed=True
  559. return sim_completed, spike_recorders, inh_spike_recorder, multimeter, list_of_syn_matrix_file_names

nest_reset_create_connect_simulate.py at commit 3331128, no license · at the source

Overview

Authors: Willem A M Wybo1, Leander Ewert2, Charl Linssen2,3,4, Pooja Babu3,4, Elena Pastorelli5, Pier Stanislao Paolucci5, Abigail Morrison2,4
  1. Peter Grünberg Institute 15 – Neuromorphic Software Ecosystems (PGI-15), Forschungszentrum Jülich, Aachen, Germany
  2. Institute for Advanced Simulation (IAS-6), Computational and Systems Neuroscience, Forschungszentrum Jülich, Jülich, Germany
  3. Simulation and Data Lab Neuroscience, Jülich Supercomputer Centre, Institute for Advanced Simulation, Jülich-Aachen Research Alliance, Forschungszentrum Jülich, Jülich, Germany
  4. Software Engineering, Faculty of Computer Science, RWTH Aachen University, Aachen, Germany
  5. Istituto Nazionale di Fisica Nucleare, Sezione di Roma, Rome, Italy
Journal: Communications biology, volume 9, issue 1, article 1411
Dates: received 11 September 2025; accepted 30 September 2026; published online 27 October 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s42003-026-11157-0 · PMID 42946780 · PMCID PMC13714284 · OpenAlex W7223976105
Open access: gold, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: computational modeling (no new data) (modality), human (organism), computational (subfield)
Methods: Graphs, Single-unit activity, calcium imaging
Keywords: Biophysical models, Network models
MeSH: Computer Simulation*, Models, Neurological*, Nerve Net*, Neurons*, Software*, Animals, Dendrites, Humans (* major topic)
Topic: Neural dynamics and brain function (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Ministero dell'Istruzione, dell'Università e della Ricerca (Ministry of Education, University and Research) (CUP B51E22000150006, CUP I53C22001400006)
Citations: not cited yet (Europe PMC); 106 references in the paper

Abstract

While subcellular mechanisms in the dendrites of neurons govern the implementation of learning and memory in the brain, large-scale network simulations featuring such processes remain challenging to achieve. This can be attributed to a lack of appropriate software tools, as neuroscientific simulators focus on the one hand on highly detailed models, and on the other hand on massive networks featuring point neurons. Here, we fill this gap by implementing a framework for the massively parallel simulation of simplified dendrite models with customizable subcellular dynamics. We leverage the NEural Simulation Tool (NEST), the neuroscientific reference with respect to efficient massively parallel simulations of point-neuron networks. By co-opting the model description language NESTML, we generate C++ code implementing user-configurable subcellular dynamics. We show that the generated models run efficiently, leading to scalable NEST network simulations. To showcase relevant functionalities, we provide a proof-of-concept demonstration that a key sensory computation – the association of top-down context arriving at distal dendrites in layer 1 and feedforward sensory input arriving perisomatically – can be achieved in a single-shot fashion through apical calcium dynamics. Our work thus unlocks the study of how dendritic processes shape network function and learning at scale.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 5 matches between paragraphs and lines of code.

Zenodo 22878144

License: CC-BY-4.0
State: the link answers, verified on 30 October 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Data availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 October 2026: the link answers (HTTP 200)
  • 30 October 2026: the link answers (HTTP 200)
At the source:

willemwybo/wta-states

License: none: the authors keep all their rights
State: the link answers, verified on 30 October 2026
Evidence: files inventoried
Commit: 33311287c43fb73cddacb163c4b66064c961787e, 30 June 2025
Languages: Python (14), Jupyter (1)
Size: 136 files, 15 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 1 notebook
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (10 files), Matplotlib (8 files), NEST Simulator (6 files), SciPy (3 files)
Availability: 1 check, the latest on 30 October 2026: the link answers
  • 30 October 2026: the link answers
16 files

jugit.fz-juelich.de/w.wybo/ca-adex

License: none: the authors keep all their rights
State: the link answers, verified on 30 October 2026
Evidence: the link answers
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 October 2026: the link answers (HTTP 200)
  • 30 October 2026: the link answers (HTTP 200)

Zenodo 10125416

License: GPL-2.0
State: the link answers, verified on 1 October 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 1 October 2026: the link answers (HTTP 200)
  • 1 October 2026: the link answers (HTTP 200)
At the source:

Zenodo 20757797

License: GPL-2.0
State: the link answers, verified on 30 October 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 October 2026: the link answers (HTTP 200)
  • 30 October 2026: the link answers (HTTP 200)
At the source:

Code availability

Code to reproduce the simulations in this paper is available at https://github.com/WillemWybo/WTA-states/releases/tag/v1.0 for the winner-take-all network and at https://jugit.fz-juelich.de/w.wybo/ca-adex/-/tree/paper-revision for all other simulations. A Zenodo archive is available at https://doi.org/10.5281/zenodo.22878144.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 5 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 15 scripts, each with its path and the digest of its content;
  • 5 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

Benchmarking results are available at https://jugit.fz-juelich.de/w.wybo/ca-adex/-/tree/paper-revision/data or in the Zenodo archive https://doi.org/10.5281/zenodo.22878144.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 October 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 2 keywords, 8 MeSH terms, 1 funder, 78 references.

Cite

This paper

Wybo, W. A. M., Ewert, L., Linssen, C., Babu, P., Pastorelli, E., Paolucci, P. S., & Morrison, A. (2026). A NEST-based framework unlocks massively parallel simulation of networks of multi-compartment neurons with customizable subcellular dynamics. Communications biology, 9(1), 1411. https://doi.org/10.1038/s42003-026-11157-0

BibTeX

@article{wybo2026nest,
author = {Wybo, Willem A M and Ewert, Leander and Linssen, Charl and Babu, Pooja and Pastorelli, Elena and Paolucci, Pier Stanislao and Morrison, Abigail},
title = {{A NEST-based framework unlocks massively parallel simulation of networks of multi-compartment neurons with customizable subcellular dynamics}},
journal = {Communications biology},
year = {2026},
month = oct,
volume = {9},
number = {1},
pages = {1411},
publisher = {Nature Publishing Group},
issn = {2399-3642},
doi = {10.1038/s42003-026-11157-0},
url = {https://doi.org/10.1038/s42003-026-11157-0},
pmid = {42946780},
pmcid = {PMC13714284}
}

RIS

TY - JOUR
AU - Wybo, Willem A M
AU - Ewert, Leander
AU - Linssen, Charl
AU - Babu, Pooja
AU - Pastorelli, Elena
AU - Paolucci, Pier Stanislao
AU - Morrison, Abigail
TI - A NEST-based framework unlocks massively parallel simulation of networks of multi-compartment neurons with customizable subcellular dynamics
T2 - Communications biology
J2 - Commun Biol
PY - 2026
DA - 2026/10/27
VL - 9
IS - 1
SP - 1411
SN - 2399-3642
PB - Nature Publishing Group
DO - 10.1038/s42003-026-11157-0
UR - https://doi.org/10.1038/s42003-026-11157-0
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s42003-026-11157-0",
"type": "article-journal",
"title": "A NEST-based framework unlocks massively parallel simulation of networks of multi-compartment neurons with customizable subcellular dynamics",
"container-title": "Communications biology",
"author": [
{
"family": "Wybo",
"given": "Willem A M"
},
{
"family": "Ewert",
"given": "Leander"
},
{
"family": "Linssen",
"given": "Charl"
},
{
"family": "Babu",
"given": "Pooja"
},
{
"family": "Pastorelli",
"given": "Elena"
},
{
"family": "Paolucci",
"given": "Pier Stanislao"
},
{
"family": "Morrison",
"given": "Abigail"
}
],
"container-title-short": "Commun Biol",
"volume": "9",
"issue": "1",
"page": "1411",
"DOI": "10.1038/s42003-026-11157-0",
"PMID": "42946780",
"PMCID": "PMC13714284",
"ISSN": "2399-3642",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s42003-026-11157-0",
"language": "en",
"issued": {
"date-parts": [
[
2026,
10,
27
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.3389/fncom.2025.1566196 [code]
Simplified two-compartment neuron with calcium dynamics capturing brain-state specific apical-amplification, -isolation and -drive.
Journal: Frontiers in computational neuroscience
In common: computational, 20 references, author Pier Stanislao Paolucci
[2] doi:10.3389/fninf.2022.883333 [code]
Fast Simulation of a Multi-Area Spiking Network Model of Macaque Cortex on an MPI-GPU Cluster.
Journal: Frontiers in neuroinformatics
In common: NEST Simulator, SciPy, Matplotlib, 1 other tool, computational, computational modeling (no new data), 10 references, author Pier Stanislao Paolucci
[3] doi:10.1007/s12021-025-09766-x [code]
The Neural Analysis Toolkit Unifies Semi-Analytical Techniques to Simplify, Understand, and Simulate Dendrites.
Journal: Neuroinformatics
In common: computational modeling (no new data), 14 references
[4] doi:10.3389/fninf.2023.941696 [code]
Efficient parameter calibration and real-time simulation of large-scale spiking neural networks with GeNN and NEST.
Journal: Frontiers in neuroinformatics
In common: NEST Simulator, SciPy, Matplotlib, 1 other tool, computational, computational modeling (no new data), 9 references
[5] doi:10.1038/s41467-023-41553-7 [code]
A GPU-based computational framework that bridges neuron simulation and artificial intelligence.
Journal: Nature communications
In common: SciPy, Matplotlib, NumPy, computational modeling (no new data), 12 references
[6] doi:10.7554/elife.79535 [code]
Ultrafast simulation of large-scale neocortical microcircuitry with biophysically realistic neurons.
Journal: eLife
In common: SciPy, Matplotlib, NumPy, computational, computational modeling (no new data), 11 references
[7] doi:10.1371/journal.pcbi.1013926 [code]
Plastic Arbor: A modern simulation framework for synaptic plasticity-From single synapses to networks of morphological neurons.
Journal: PLoS computational biology
In common: NEST Simulator, SciPy, Matplotlib, 1 other tool, computational modeling (no new data), 9 references
[8] doi:10.7554/elife.103324 [code]
DendroTweaks, an interactive approach for unraveling dendritic dynamics.
Journal: eLife
In common: SciPy, Matplotlib, NumPy, computational modeling (no new data), 11 references
[9] doi:10.1038/s41467-025-56297-9 [code]
Dendrites endow artificial neural networks with accurate, robust and parameter-efficient learning.
Journal: Nature communications
In common: SciPy, Matplotlib, NumPy, computational modeling (no new data), 10 references
[10] doi:10.1371/journal.pcbi.1010353 [code]
Brain signal predictions from multi-scale networks using a linearized framework.
Journal: PLoS computational biology
In common: NEST Simulator, SciPy, Matplotlib, 1 other tool, computational, computational modeling (no new data), 4 references, author Pooja Babu

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0.svg)](https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0.svg
   :target: https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0"><img src="https://openscicode.org/badge/doi/10.1038/s42003-026-11157-0.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.