OSCR

Multiple mechanisms of rhythm switching in recurrent neural networks with adaptive time constants.

Code ↔ Paper

30 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 30 matches
  1. [1] § Methods › Analysis methods › Causal silencing analysis ↔ analysis_ablation.py, lines 1 to 36 · score 0.95 · silenced subpopulations, random subsets, recurrent dynamics, firing rate, trained network, band power · Report a mismatch
  2. [2] § Results › Structural and dynamical basis: recurrent connectivity and gain modulation ↔ analysis_connectivity.py, lines 1 to 33 · score 0.93 · leak rates held, unstable eigenfrequency, Slowest relaxation, dynamical basis, Gain modulation, neuronal gain · Report a mismatch
  3. [3] § Methods › Analysis methods › Connectivity structure and linearized dynamics ↔ analysis_connectivity.py, lines 1 to 33 · score 0.90 · leak rates held, Connectivity structure, slowest relaxation, Gain modulation, timescale, intrinsic · Report a mismatch
  4. [4] § Results › Phase interference controls band power ↔ analysis_phase_coherence.py, lines 1 to 20 · score 0.80 · coherence ratio, amplitude suppression, phase interference, amplitude ratio, band amplitude, band power · Report a mismatch
  5. [5] § Appendix C Inter-mode population sharing and the learned time-constant distribution ↔ analysis_outlier_tau.py, lines 1 to 29 · score 0.80 · inter mode population, inter mode amplitude, median learned, pattern correlations, outliers, active · Report a mismatch
  6. [6] § Results › Robustness to time-constant initialization ↔ analysis_reinit_compare.py, lines 1 to 31 · score 0.78 · 5–300 ms, log uniform, matched mode amplitude, Spearman correlation, 5 ms, skewness · Report a mismatch
  7. [7] § Results › Inter-mode population similarity and run-to-run variability ↔ make_fig4_intermode.py, lines 1 to 16 · score 0.76 · Jaccard coefficient matrix, Spearman correlation matrix, Inter mode population, sync degree, mode amplitudes, variability · Report a mismatch
  8. [8] § Results › Baseline shifts drive rhythm switching ↔ analysis_baseline_fp.py, lines 435 to 556 · score 0.76 · eigenvalue magnitude, median amplitude, Baseline shift, oscillation amplitude, Power spectrum, peaks · Report a mismatch
  9. [9] § Appendix A Distribution of across training runs ↔ analysis_phase_coherence.py, lines 197 to 322 · score 0.74 · band coherence ratio, amplitude suppression, amplitude ratio, phase interference, classification · Report a mismatch
  10. [10] § Results › Phase interference controls band power ↔ analysis_phase_coherence.py, lines 1 to 20 · score 0.72 · coherence ratio, amplitude suppression, phase interference, amplitude ratio, band amplitude, classification · Report a mismatch
  11. [11] § Methods › Task ↔ train_once.py, lines 37 to 60 · score 0.71 · 8–13 Hz, 14–29 Hz, 30–50 Hz, 4–7 Hz, pulses, 30 Hz · Report a mismatch
  12. [12] § Methods › Task ↔ train_reinit.py, lines 43 to 61 · score 0.71 · 8–13 Hz, 14–29 Hz, 30–50 Hz, 4–7 Hz, pulses, 30 Hz · Report a mismatch
  13. [13] § Results › Fast neurons are the causal substrate of high-frequency rhythms ↔ analysis_ablation.py, lines 1 to 36 · score 0.71 · baseline contribution, firing rate, band power, fastest, shortest, clamped · Report a mismatch
  14. [14] § Appendix D Robustness to time-constant initialization ↔ analysis_reinit_compare.py, lines 1 to 31 · score 0.70 · 5–300 ms, log uniform, 5 ms, Gini, recurrent, baseline · Report a mismatch
  15. [15] § Results › Structural and dynamical basis: recurrent connectivity and gain modulation ↔ analysis_connectivity.py, lines 146 to 161 · score 0.70 · frequency retuning, dominant unstable, gain profile, gain modulation, connectivity, band · Report a mismatch
  16. [16] § Results › Structural and dynamical basis: recurrent connectivity and gain modulation ↔ analysis_connectivity.py, lines 60 to 91 · score 0.69 · slowest decaying, free dynamics, eigenmode, origin, connectivity, Linearizing · Report a mismatch
  17. [17] § Results › Phase interference controls band power ↔ analysis_phase_supfig.py, lines 59 to 80 · score 0.64 · log spaced bins, amplitude suppression, phase interference, Histogram, threshold · Report a mismatch
  18. [18] § Results › Frequency-dependent synchronization structure ↔ make_fig3_sync.py, lines 1 to 22 · score 0.63 · Absolute sync strength, synchronization structure, sync degree, ascending, matrix, Figure 3 · Report a mismatch
  19. [19] § Results › Inter-mode population similarity and run-to-run variability ↔ analysis_outlier_tau.py, lines 1 to 29 · score 0.60 · amplitude pattern correlation, Inter mode population, inter mode sharing, outliers, active, Jaccard · Report a mismatch
  20. [20] § Methods › Analysis methods › Baseline analysis: fixed-point search and stability analysis ↔ analysis_baseline_fp.py, lines 276 to 413 · score 0.58 · pre activation, power spectrum, simulation, baseline, oscillations, population · Report a mismatch
  21. [21] § Results › Frequency-dependent synchronization structure ↔ make_fig3_sync.py, lines 1 to 22 · score 0.58 · absolute sync strength, neurons sorted, ascending, synchronized, matrix · Report a mismatch
  22. [22] § Results › Phase interference controls band power ↔ analysis_phase_fig6.py, lines 1 to 27 · score 0.57 · phase interference mechanism, representative neuron, single neuron, transition, Figure 6, oscillation · Report a mismatch
  23. [23] § Methods › Analysis methods › Bandpass filtering and amplitude extraction ↔ analysis_phase_coherence.py, lines 29 to 67 · score 0.55 · Hilbert transform, bandpass filter · Report a mismatch
  24. [24] § Results › Fast neurons are the causal substrate of high-frequency rhythms ↔ analysis_ablation.py, lines 294 to 341 · score 0.55 · neuron silencing, oscillatory contribution, isolates, freeze, fast, causal · Report a mismatch
  25. [25] § Results › Baseline shifts drive rhythm switching ↔ analysis_baseline_fp.py, lines 435 to 556 · score 0.54 · low amplitude neurons, baseline shift, eigenvalue, scatter, activity, oscillation · Report a mismatch
  26. [26] § Results › Inter-mode population similarity and run-to-run variability ↔ make_fig4_intermode.py, lines 33 to 55 · score 0.53 · matched mode amplitude, correlation matrix, vectors, Spearman, Inter · Report a mismatch
  27. [27] § Methods › Analysis methods › Baseline analysis: fixed-point search and stability analysis ↔ analysis_baseline_fp.py, lines 276 to 413 · score 0.53 · pre activation, cluster, perturbations, baseline · Report a mismatch
  28. [28] § Methods › Analysis methods › Inter-mode population similarity ↔ make_fig4_intermode.py, lines 1 to 16 · score 0.53 · Jaccard coefficient, sync degree, Inter, population · Report a mismatch
  29. [29] § Methods › Analysis methods › Bandpass filtering and amplitude extraction ↔ analysis_phase_coherence.py, lines 70 to 97 · score 0.52 · Hilbert envelope, band amplitude, Bandpass, filtering, rhythm · Report a mismatch
  30. [30] § Methods › Analysis methods › Amplitude distribution statistics ↔ analysis_multiple.py, lines 93 to 138 · score 0.52 · Gini coefficient, matched mode amplitudes, skewness · 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 · 326 lines · 12 KB · MIT · 5 matches

  1. """
  2. Analysis for Sect. 3.6: phase-interference control of band power.
  3. For each of the 20 trained networks, the following quantities are computed:
  4. 1. Coherence ratio eta^(m,k) over all (mode, band) pairs (4 x 4 matrix).
  5. 2. Alpha-band amplitude ratio kappa_i = A_i^(alpha, beta mode) / A_i^(alpha, alpha mode).
  6. 3. Per-run classification: amplitude-suppression vs phase-interference type.
  7. """
  8. import os
  9. import sys
  10. import json
  11. import argparse
  12. import numpy as np
  13. from scipy import signal as sp_signal
  14. from function import *
  15. import matplotlib
  16. matplotlib.use('Agg')
  17. import matplotlib.pyplot as plt
  18. # GPU memory configuration
  19. gpus = tf.config.list_physical_devices('GPU')
  20. if gpus:
  21. for gpu in gpus:
  22. tf.config.experimental.set_memory_growth(gpu, True)
  23. def compute_coherence_ratio(r_split, rhythms, labels, Fs, cut_s=500):
  24. """
  25. Compute the coherence ratio eta^(m,k) over all (mode, band) pairs.
  26. eta = <R^(k)(t)>_t / <(1/N) sum_i A_i^(k)(t)>_t
  27. R^(k)(t) = |(1/N) sum_i A_i^(k)(t) exp(i phi_i^(k)(t))|
  28. Returns: (n_modes, n_bands) array.
  29. """
  30. n_modes = len(labels)
  31. units = r_split.shape[1]
  32. eta = np.zeros((n_modes, n_modes)) # eta[mode, band]
  33. band_names = list(rhythms.keys())
  34. for k_idx, band_name in enumerate(band_names):
  35. low, high = rhythms[band_name]
  36. # Band-pass filter
  37. filtered = bandpass_filter(r_split, low, high, Fs) # (n_modes, units, T)
  38. # Hilbert transform
  39. _, envelopes, phases = hilbert(filtered) # (n_modes, units, T)
  40. for m_idx in range(n_modes):
  41. env = envelopes[m_idx, :, cut_s:] # (units, T)
  42. pha = phases[m_idx, :, cut_s:] # (units, T)
  43. # R^(k)(t) = |(1/N) Σ_i A_i exp(i φ_i)|
  44. vector_sum_t = np.mean(env * np.exp(1j * pha), axis=0) # (T,)
  45. R_t = np.abs(vector_sum_t) # (T,)
  46. # (1/N) Σ_i A_i(t)
  47. scalar_mean_t = np.mean(env, axis=0) # (T,)
  48. # η = <R(t)> / <scalar_mean(t)>
  49. mean_R = np.mean(R_t)
  50. mean_scalar = np.mean(scalar_mean_t)
  51. eta[m_idx, k_idx] = mean_R / (mean_scalar + 1e-20)
  52. return eta
  53. def compute_kappa(r_split, rhythms, labels, Fs, cut_s=500):
  54. """
  55. Compute the alpha-band amplitude ratio kappa_i = A_i^(alpha, beta_mode) / A_i^(alpha, alpha_mode).
  56. Returns: dict with kappa array and summary statistics.
  57. """
  58. alpha_idx = list(labels).index('alpha')
  59. beta_idx = list(labels).index('beta')
  60. low, high = rhythms['alpha']
  61. filtered = bandpass_filter(r_split, low, high, Fs)
  62. # Time-averaged Hilbert envelope
  63. _, envelopes, _ = hilbert(filtered)
  64. amp_alpha_mode = np.mean(envelopes[alpha_idx, :, cut_s:], axis=-1) # (units,)
  65. amp_beta_mode = np.mean(envelopes[beta_idx, :, cut_s:], axis=-1) # (units,)
  66. kappa = amp_beta_mode / (amp_alpha_mode + 1e-20)
  67. return {
  68. 'kappa': kappa,
  69. 'mean_kappa': float(np.mean(kappa)),
  70. 'median_kappa': float(np.median(kappa)),
  71. 'n_above_0.5': int(np.sum(kappa > 0.5)),
  72. 'n_above_1.0': int(np.sum(kappa > 1.0)),
  73. 'amp_alpha_mode': amp_alpha_mode,
  74. 'amp_beta_mode': amp_beta_mode,
  75. }
  76. def compute_cancel_ratio_alpha(r_split, rhythms, labels, Fs, cut_s=500):
  77. """
  78. For both the alpha mode and the beta mode, compute the alpha-band cancel_ratio
  79. cancel_ratio = |sum_i A_i exp(i phi_i)| / sum_i A_i
  80. (equivalent to computing eta with a different time-averaging convention).
  81. """
  82. alpha_idx = list(labels).index('alpha')
  83. beta_idx = list(labels).index('beta')
  84. low, high = rhythms['alpha']
  85. filtered = bandpass_filter(r_split, low, high, Fs)
  86. _, envelopes, phases = hilbert(filtered)
  87. results = {}
  88. for mode_idx, mode_name in [(alpha_idx, 'alpha'), (beta_idx, 'beta')]:
  89. env = envelopes[mode_idx, :, cut_s:]
  90. pha = phases[mode_idx, :, cut_s:]
  91. # Time-averaged amplitude and representative phase
  92. mean_amp = np.mean(env, axis=-1)
  93. mean_phase = np.angle(np.mean(np.exp(1j * pha), axis=-1))
  94. vector_sum = np.abs(np.sum(mean_amp * np.exp(1j * mean_phase)))
  95. scalar_sum = np.sum(mean_amp)
  96. cancel_ratio = vector_sum / (scalar_sum + 1e-20)
  97. results[mode_name] = {
  98. 'vector_sum': float(vector_sum),
  99. 'scalar_sum': float(scalar_sum),
  100. 'cancel_ratio': float(cancel_ratio),
  101. }
  102. return results
  103. def analyze_run(run_id):
  104. """Run the analysis pipeline for a single training run."""
  105. run_path = f"multiple_runs/{run_id}/results"
  106. if not os.path.exists(run_path):
  107. print(f" Run {run_id}: path not found, skipping")
  108. return None
  109. # Load the trained model
  110. model, dsg, history = load_from_json(run_path)
  111. checkpoint_path = f"{run_path}/checkpoints/best_model.weights.h5"
  112. model.load_weights(checkpoint_path)
  113. try:
  114. model.sort_by_tau()
  115. except:
  116. pass
  117. # Generate the evaluation dataset
  118. dsg.update_task_config(period_length=8000, switch_num=dsg.task.n_rhythm)
  119. dsg.update_noise_config(strength=0)
  120. inputs, noise, mask, onehots, labels = dsg.make_datasets(
  121. batch_size=1, specified_rhythm=dsg.task.rhythm_names
  122. )
  123. labels = labels[0]
  124. init_state = model.get_initial_state(batch_size=1)
  125. y, z = model(inputs, noise, init_state)
  126. r = model.r[0].numpy().T # (units, time)
  127. Fs = dsg.Fs
  128. wait_length = dsg.task.wait_length
  129. switch_num = dsg.task.switch_num
  130. rhythms = dsg.task.rhythms
  131. # Split into per-interval segments
  132. r_split = split_signal(r, wait_length, switch_num)
  133. # 1. Coherence ratio
  134. eta = compute_coherence_ratio(r_split, rhythms, labels, Fs)
  135. # 2. kappa (alpha-band amplitude ratio)
  136. kappa_result = compute_kappa(r_split, rhythms, labels, Fs)
  137. # 3. cancel ratio
  138. cancel = compute_cancel_ratio_alpha(r_split, rhythms, labels, Fs)
  139. return {
  140. 'run_id': run_id,
  141. 'labels': list(labels),
  142. 'eta': eta,
  143. 'kappa_mean': kappa_result['mean_kappa'],
  144. 'kappa_median': kappa_result['median_kappa'],
  145. 'kappa_n_above_0.5': kappa_result['n_above_0.5'],
  146. 'kappa_n_above_1.0': kappa_result['n_above_1.0'],
  147. 'cancel_alpha_in_alpha': cancel['alpha']['cancel_ratio'],
  148. 'cancel_alpha_in_beta': cancel['beta']['cancel_ratio'],
  149. 'kappa_all': kappa_result['kappa'],
  150. }
  151. def main():
  152. parser = argparse.ArgumentParser()
  153. parser.add_argument('--runs', type=str, default='all',
  154. help='Comma-separated run IDs or "all"')
  155. args = parser.parse_args()
  156. if args.runs == 'all':
  157. run_ids = list(range(1, 21))
  158. else:
  159. run_ids = [int(x) for x in args.runs.split(',')]
  160. all_results = []
  161. for run_id in run_ids:
  162. print(f"\n{'='*50}")
  163. print(f"Run {run_id}")
  164. print(f"{'='*50}")
  165. result = analyze_run(run_id)
  166. if result is not None:
  167. all_results.append(result)
  168. if not all_results:
  169. print("No results.")
  170. return
  171. # ===== Summary output =====
  172. print("\n" + "="*70)
  173. print("SUMMARY: Phase coherence screening")
  174. print("="*70)
  175. band_names = ['theta', 'alpha', 'beta', 'gamma']
  176. # --- Statistics of the diagonal of eta (matched mode) ---
  177. print("\n--- Coherence ratio η^(m,m) (matched mode, diagonal) ---")
  178. print(f"{'Run':>4s} {'θ':>6s} {'α':>6s} {'β':>6s} {'γ':>6s}")
  179. diag_eta = []
  180. for res in all_results:
  181. eta = res['eta']
  182. diag = np.diag(eta)
  183. diag_eta.append(diag)
  184. print(f" {res['run_id']:>2d} {diag[0]:.4f} {diag[1]:.4f} {diag[2]:.4f} {diag[3]:.4f}")
  185. diag_eta = np.array(diag_eta)
  186. print(f"{'mean':>6s} {diag_eta[:,0].mean():.4f} {diag_eta[:,1].mean():.4f} "
  187. f"{diag_eta[:,2].mean():.4f} {diag_eta[:,3].mean():.4f}")
  188. print(f"{'std':>6s} {diag_eta[:,0].std():.4f} {diag_eta[:,1].std():.4f} "
  189. f"{diag_eta[:,2].std():.4f} {diag_eta[:,3].std():.4f}")
  190. # --- Statistics of eta^(beta, alpha): alpha-band coherence in the beta mode ---
  191. print("\n--- η^(β,α): alpha coherence in beta mode ---")
  192. eta_beta_alpha = []
  193. for res in all_results:
  194. beta_idx = res['labels'].index('beta')
  195. alpha_band_idx = list(band_names).index('alpha')
  196. val = res['eta'][beta_idx, alpha_band_idx]
  197. eta_beta_alpha.append(val)
  198. print(f" Run {res['run_id']:>2d}: η^(β,α) = {val:.6f}")
  199. eta_beta_alpha = np.array(eta_beta_alpha)
  200. print(f" mean: {eta_beta_alpha.mean():.6f} ± {eta_beta_alpha.std():.6f}")
  201. # --- κ (alpha amplitude ratio) ---
  202. print("\n--- κ: alpha amplitude ratio (beta mode / alpha mode) ---")
  203. print(f"{'Run':>4s} {'mean_κ':>8s} {'median_κ':>9s} {'n>0.5':>6s} {'n>1.0':>6s} {'Type':>12s}")
  204. for res in all_results:
  205. # Classification rule: median(kappa) > 0.3 AND at least 20 neurons with kappa > 0.5 -> phase-interference type
  206. is_phase_type = res['kappa_median'] > 0.3 and res['kappa_n_above_0.5'] >= 20
  207. type_label = "PHASE-INTERF" if is_phase_type else "AMP-SUPPRESS"
  208. print(f" {res['run_id']:>2d} {res['kappa_mean']:>8.4f} {res['kappa_median']:>9.4f} "
  209. f"{res['kappa_n_above_0.5']:>6d} {res['kappa_n_above_1.0']:>6d} {type_label:>12s}")
  210. # --- Per-run classification ---
  211. phase_runs = [res['run_id'] for res in all_results
  212. if res['kappa_median'] > 0.3 and res['kappa_n_above_0.5'] >= 20]
  213. amp_runs = [res['run_id'] for res in all_results
  214. if not (res['kappa_median'] > 0.3 and res['kappa_n_above_0.5'] >= 20)]
  215. print(f"\n--- Classification ---")
  216. print(f" Phase-interference type ({len(phase_runs)} runs): {phase_runs}")
  217. print(f" Amplitude-suppression type ({len(amp_runs)} runs): {amp_runs}")
  218. # --- Mean eta matrix across all runs ---
  219. all_eta = np.array([res['eta'] for res in all_results])
  220. mean_eta = np.mean(all_eta, axis=0)
  221. std_eta = np.std(all_eta, axis=0)
  222. print(f"\n--- Mean η matrix (mode × band) ---")
  223. print(f"{'':>8s} {'θ-band':>8s} {'α-band':>8s} {'β-band':>8s} {'γ-band':>8s}")
  224. mode_names = all_results[0]['labels']
  225. for i, m in enumerate(mode_names):
  226. print(f" {m:>6s} {mean_eta[i,0]:.4f}±{std_eta[i,0]:.3f} "
  227. f"{mean_eta[i,1]:.4f}±{std_eta[i,1]:.3f} "
  228. f"{mean_eta[i,2]:.4f}±{std_eta[i,2]:.3f} "
  229. f"{mean_eta[i,3]:.4f}±{std_eta[i,3]:.3f}")
  230. # --- Save results to JSON ---
  231. save_path = "multiple_runs/summary"
  232. os.makedirs(save_path, exist_ok=True)
  233. save_data = {
  234. 'n_runs': len(all_results),
  235. 'run_ids': [res['run_id'] for res in all_results],
  236. 'phase_interference_runs': phase_runs,
  237. 'amplitude_suppression_runs': amp_runs,
  238. 'mean_eta_diagonal': {
  239. 'theta': f"{diag_eta[:,0].mean():.4f}±{diag_eta[:,0].std():.4f}",
  240. 'alpha': f"{diag_eta[:,1].mean():.4f}±{diag_eta[:,1].std():.4f}",
  241. 'beta': f"{diag_eta[:,2].mean():.4f}±{diag_eta[:,2].std():.4f}",
  242. 'gamma': f"{diag_eta[:,3].mean():.4f}±{diag_eta[:,3].std():.4f}",
  243. },
  244. 'mean_eta_matrix': mean_eta.tolist(),
  245. 'std_eta_matrix': std_eta.tolist(),
  246. 'per_run': [{
  247. 'run_id': res['run_id'],
  248. 'eta_diagonal': np.diag(res['eta']).tolist(),
  249. 'eta_beta_alpha': float(res['eta'][res['labels'].index('beta'),
  250. list(band_names).index('alpha')]),
  251. 'kappa_mean': res['kappa_mean'],
  252. 'kappa_median': res['kappa_median'],
  253. 'kappa_n_above_0.5': res['kappa_n_above_0.5'],
  254. } for res in all_results],
  255. }
  256. with open(f"{save_path}/phase_coherence_results.json", 'w') as f:
  257. json.dump(save_data, f, indent=2)
  258. print(f"\nResults saved to {save_path}/phase_coherence_results.json")
  259. if __name__ == '__main__':
  260. main()

analysis_phase_coherence.py at commit 7122c45, under MIT · at the source

Overview

Authors: Yutaka Yamaguti1, Shota Nakamura2
ORCID iDs: Yutaka Yamaguti
  1. Faculty of Information Engineering, Fukuoka Institute of Technology, 3-30-1 Wajiro-Higashi, Higashi-ku, Fukuoka, Fukuoka 811-0295 Japan
  2. Graduate School of Engineering, Fukuoka Institute of Technology, 3-30-1 Wajiro-Higashi, Higashi-ku, Fukuoka, Fukuoka 811-0295 Japan
Institutions: Fukuoka Institute of Technology (Japan)
Journal: Biological cybernetics, volume 120, issue 5-6, article 41
Dates: received 14 May 2026; accepted 20 October 2026; published online 6 November 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1007/s00422-026-01074-0 · PMID 42993300 · PMCID PMC13743668 · OpenAlex W7161251093
Open access: hybrid, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: computational (subfield)
Methods: Spectral & time-frequency, Statistics, Connectivity, Single-unit activity, calcium imaging, Physiology & signal measures
Keywords: Rhythm generation, Functional differentiation, Recurrent neural networks, Time constant diversity
MeSH: Models, Neurological*, Nerve Net*, Neural Networks, Computer*, Neurons*, Periodicity*, Animals, Recurrent Neural Networks, Time Factors (* major topic)
Topic: Neural dynamics and brain function (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Japan Society for the Promotion of Science (26K15000)
Citations: not cited yet (Europe PMC); 25 references in the paper

Abstract

Although recurrent neural networks (RNNs) trained on cognitive tasks have become a widely used framework for studying neural computation, the internal mechanisms by which RNNs switch between rhythms across multiple frequency bands, and how these mechanisms relate to neuronal time constants, have not been systematically analyzed. We trained leaky integrator RNNs with neuron-specific learnable time constants on a four-band (theta, alpha, beta, gamma) rhythm-switching task and analyzed 20 independently trained networks. Whereas low-frequency rhythms were produced by distributed participation of many neurons, high-frequency rhythms were dominated by a small subpopulation of short-time-constant neurons, and the negative correlation between time constant and matched-mode amplitude strengthened monotonically with frequency. Rhythm switching was supported by multiple coexisting mechanisms: turnover of the active subpopulation, network-wide baseline shifts that reposition the operating point near distinct unstable fixed points, and inter-neuronal phase reorganization that selectively cancels or supports band components in the population output. Analysis of the learned recurrent connectivity linked these mechanisms to network structure: the short-time-constant neurons formed a more strongly interconnected module, and the baseline shift retuned the oscillation frequency through gain modulation of the recurrent interactions. The mechanism deployed for each mode pair varied across training runs, exposing a degeneracy of learned solutions. These findings parallel the coexistence of rhythm-specific and multi-rhythm interneurons reported in biological circuits and provide a candidate framework for interpreting frequency-band-specific functional differentiation in neural systems.

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 30 matches between paragraphs and lines of code.

cncs-fit/rnn-rhythm

License: MIT
State: the link answers, verified on 9 November 2026
Evidence: files inventoried
Commit: 7122c45d0846bab9e1e3036d728d3ada5f5560f4, 12 August 2026
Languages: Python (23), Shell (2)
Size: 29 files, 25 scripts
Software Heritage: not archived
Found in: “Code Availability”
Holds: README, license file, environment (requirements.txt)
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (22 files), Matplotlib (17 files), SciPy (12 files), TensorFlow (10 files), Keras (5 files), h5py (2 files), pandas (2 files), seaborn (2 files), scikit-learn (1 file)
Availability: 1 check, the latest on 9 November 2026: the link answers
  • 9 November 2026: the link answers
27 files

Zenodo 21900320

License: MIT
State: the link answers, verified on 9 November 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code Availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (22 files), Matplotlib (17 files), SciPy (12 files), TensorFlow (10 files), Keras (5 files), h5py (2 files), pandas (2 files), seaborn (2 files), scikit-learn (1 file)
Availability: 1 check, the latest on 9 November 2026: the link answers (HTTP 200)
  • 9 November 2026: the link answers (HTTP 200)
27 files

Code Availability

The code used to train the networks and to perform all analyses is publicly available at https://github.com/cncs-fit/rnn-rhythm and permanently archived at Zenodo (DOI: https://doi.org/10.5281/zenodo.21900320).

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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 50 scripts, each with its path and the digest of its content;
  • 30 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 Statement

All data analyzed in this study were generated by the simulation and analysis code described in Sect. 2. The code, together with scripts to reproduce the analyses and figures, is publicly available at https://github.com/cncs-fit/rnn-rhythm and archived at Zenodo (https://doi.org/10.5281/zenodo.21900320).

The code used to train the networks and to perform all analyses is publicly available at https://github.com/cncs-fit/rnn-rhythm and permanently archived at Zenodo (DOI: https://doi.org/10.5281/zenodo.21900320).

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, 9 November 2026: the first record

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

Cite

This paper

Yamaguti, Y., & Nakamura, S. (2026). Multiple mechanisms of rhythm switching in recurrent neural networks with adaptive time constants. Biological cybernetics, 120(5-6), 41. https://doi.org/10.1007/s00422-026-01074-0

BibTeX

@article{yamaguti2026multiple,
author = {Yamaguti, Yutaka and Nakamura, Shota},
title = {{Multiple mechanisms of rhythm switching in recurrent neural networks with adaptive time constants}},
journal = {Biological cybernetics},
year = {2026},
month = nov,
volume = {120},
number = {5-6},
pages = {41},
publisher = {Springer Science+Business Media},
issn = {0340-1200},
doi = {10.1007/s00422-026-01074-0},
url = {https://doi.org/10.1007/s00422-026-01074-0},
pmid = {42993300},
pmcid = {PMC13743668}
}

RIS

TY - JOUR
AU - Yamaguti, Yutaka
AU - Nakamura, Shota
TI - Multiple mechanisms of rhythm switching in recurrent neural networks with adaptive time constants
T2 - Biological cybernetics
J2 - Biol Cybern
PY - 2026
DA - 2026/11/06
VL - 120
IS - 5-6
SP - 41
SN - 0340-1200
PB - Springer Science+Business Media
DO - 10.1007/s00422-026-01074-0
UR - https://doi.org/10.1007/s00422-026-01074-0
LA - en
ER -

CSL-JSON

{
"id": "10.1007/s00422-026-01074-0",
"type": "article-journal",
"title": "Multiple mechanisms of rhythm switching in recurrent neural networks with adaptive time constants",
"container-title": "Biological cybernetics",
"author": [
{
"family": "Yamaguti",
"given": "Yutaka"
},
{
"family": "Nakamura",
"given": "Shota"
}
],
"container-title-short": "Biol Cybern",
"volume": "120",
"issue": "5-6",
"page": "41",
"DOI": "10.1007/s00422-026-01074-0",
"PMID": "42993300",
"PMCID": "PMC13743668",
"ISSN": "0340-1200",
"publisher": "Springer Science+Business Media",
"URL": "https://doi.org/10.1007/s00422-026-01074-0",
"language": "en",
"issued": {
"date-parts": [
[
2026,
11,
6
]
]
}
}

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.1007/s11571-025-10377-0 [code]
Emergence of functionally differentiated structures via mutual information minimization in recurrent neural networks.
Journal: Cognitive neurodynamics
In common: Keras, TensorFlow, seaborn, 5 other tools, computational, 4 references, author Yutaka Yamaguti
[2] doi:10.3389/fnsys.2024.1269190 [code]
Exploring Flip Flop memories and beyond: training Recurrent Neural Networks with key insights.
Journal: Frontiers in systems neuroscience
In common: Keras, TensorFlow, scikit-learn, 3 other tools, computational, 4 references
[3] doi:10.1371/journal.pbio.3003831 [code]
Disinhibitory signaling enables flexible coding of top-down information in cortical networks.
Journal: PLoS biology
In common: TensorFlow, h5py, scikit-learn, 4 other tools, 4 references
[4] doi:10.1038/s41467-022-33581-6 [code]
Recurrent neural networks with explicit representation of dynamic latent variables can mimic behavioral patterns in a physical inference task.
Journal: Nature communications
In common: TensorFlow, h5py, seaborn, 5 other tools, computational, 2 references
[5] doi:10.1007/s11571-023-10038-0 [code]
Coincidence detection and integration behavior in spiking neural networks.
Journal: Cognitive neurodynamics
In common: Keras, TensorFlow, scikit-learn, 4 other tools, computational, 2 references
[6] doi:10.1016/j.celrep.2024.114580 [code]
Adaptive robustness through incoherent signaling mechanisms in a regenerative brain.
Journal: Cell reports
In common: Keras, TensorFlow, h5py, 5 other tools, 2 references
[7] doi:10.1038/s41467-023-35824-6 [code]
Distributed context-dependent choice information in mouse posterior cortex.
Journal: Nature communications
In common: Keras, TensorFlow, h5py, 5 other tools, 2 references
[8] doi:10.1038/s41540-026-00727-x [code]
Association-sensory spatiotemporal hierarchy and functional gradient-regularised recurrent neural network with implications for schizophrenia.
Journal: NPJ systems biology and applications
In common: h5py, seaborn, pandas, 3 other tools, computational, 3 references
[9] doi:10.1371/journal.pcbi.1014162 [code]
Exploring neural manifolds across a wide range of intrinsic dimensions.
Journal: PLoS computational biology
In common: TensorFlow, h5py, scikit-learn, 4 other tools, computational, 2 references
[10] doi:10.1038/s41467-025-63771-x [code]
Efficient and robust temporal processing with neural oscillations modulated spiking neural networks.
Journal: Nature communications
In common: TensorFlow, h5py, scikit-learn, 4 other tools, computational, 2 references

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.1007/s00422-026-01074-0.svg)](https://openscicode.org/badge/doi/10.1007/s00422-026-01074-0)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.1007/s00422-026-01074-0.svg
   :target: https://openscicode.org/badge/doi/10.1007/s00422-026-01074-0
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1007/s00422-026-01074-0"><img src="https://openscicode.org/badge/doi/10.1007/s00422-026-01074-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.