Skip to content

Commit 22cb3e1

Browse files
committed
fix: ww crbl demo updates
1 parent 3a9a9c9 commit 22cb3e1

9 files changed

Lines changed: 980 additions & 383 deletions

File tree

tvb_documentation/demos/ww-crbl/run_ww_crbl_hybrid.py

Lines changed: 325 additions & 94 deletions
Large diffs are not rendered by default.
-2.73 KB
Loading

tvb_documentation/demos/ww-crbl/ww_crbl_hybrid_demo.ipynb

Lines changed: 608 additions & 263 deletions
Large diffs are not rendered by default.
8.93 KB
Loading
37.4 KB
Loading
-13.7 KB
Loading

tvb_library/tvb/simulator/backend/nb_hybrid.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ def _get_supported_models_classes() -> tuple:
209209
ReducedSetFitzHughNagumo,
210210
ReducedSetHindmarshRose,
211211
)
212+
from tvb.simulator.models.cerebellar_mf import CerebellarMF
212213
from tvb.simulator.models.linear import Linear
213214
_SUPPORTED_MODELS_CACHE = (
214215
MontbrioPazoRoxin,
@@ -236,6 +237,7 @@ def _get_supported_models_classes() -> tuple:
236237
ZetterbergJansen,
237238
ReducedSetFitzHughNagumo,
238239
ReducedSetHindmarshRose,
240+
CerebellarMF,
239241
Linear,
240242
)
241243
return _SUPPORTED_MODELS_CACHE
@@ -1486,8 +1488,14 @@ def _run_compiled(
14861488
args.append(stim_arr)
14871489

14881490
# Per-subnetwork spatial parameter arrays (heterogeneous per-node parameters)
1491+
# Custom-template models bake all params into generated code, so skip
1492+
# spatial_parameter_names auto-detection (which may pick up non-spatial
1493+
# arrays like P_grc[5] that can't broadcast to n_nodes).
14891494
for sn_info in analysis.subnetworks:
1490-
sp_names = list(getattr(sn_info.model, 'spatial_parameter_names', []))
1495+
if hasattr(sn_info.model, '_nb_hybrid_custom_template'):
1496+
sp_names = []
1497+
else:
1498+
sp_names = list(getattr(sn_info.model, 'spatial_parameter_names', []))
14911499
if sp_names:
14921500
sp_arr = np.array(
14931501
[np.broadcast_to(getattr(sn_info.model, n), (sn_info.n_nodes,)).ravel()

tvb_library/tvb/simulator/backend/templates/nb-hybrid-sim.py.mako

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,15 @@ def compute_coupling_${p.name}(
295295
"heun" if isinstance(sn.integrator, HeunDeterministic) else "euler"
296296
svars = list(sn.model.state_variables)
297297
298-
# Zerlaut models use a custom template for dfun generation;
299-
# they don't have coupling_terms / state_variable_dfuns / global_parameter_names.
298+
# Models with custom Mako templates (ZerlautAdaptation*, CerebellarMF)
299+
# don't have state_variable_dfuns / global_parameter_names, but they do
300+
# have coupling_terms.
300301
_has_custom_template = hasattr(sn.model, '_nb_hybrid_custom_template')
301302
if _has_custom_template:
302-
cterms = ['Coupling_Term'] # Zerlaut: single cvar=[0]
303+
cterms = list(sn.model.coupling_terms)
303304
dfuns = None
304305
gparams = {}
306+
sparams_list = [] # custom template bakes all params — no spatial params needed
305307
else:
306308
cterms = list(sn.model.coupling_terms)
307309
dfuns = sn.model.state_variable_dfuns
@@ -312,16 +314,16 @@ def compute_coupling_${p.name}(
312314
n_nodes = sn.n_nodes
313315
n_modes = sn.n_modes
314316
svb = sn.model.state_variable_boundaries
315-
lo_map = {k: float(v[0]) if v[0] != float('-inf') and not (v[0] != v[0]) else None for k, v in svb.items()} if svb else {}
316-
hi_map = {k: float(v[1]) if v[1] != float('inf') and not (v[1] != v[1]) else None for k, v in svb.items()} if svb else {}
317+
lo_map = {}
318+
hi_map = {}
317319
import math as _math, numpy as _np
318320
lo_map = {}
319321
hi_map = {}
320322
if svb:
321323
import numpy as _np
322324
for k, v in svb.items():
323-
lo_map[k] = float(v[0]) if _np.isfinite(v[0]) else None
324-
hi_map[k] = float(v[1]) if _np.isfinite(v[1]) else None
325+
lo_map[k] = float(v[0]) if v[0] is not None and _np.isfinite(v[0]) else None
326+
hi_map[k] = float(v[1]) if v[1] is not None and _np.isfinite(v[1]) else None
325327
svars_str = ', '.join(svars)
326328
cterms_str = ', '.join(cterms)
327329
i1svars_str = ', '.join(['i1' + s for s in svars])

tvb_library/tvb/simulator/models/cerebellar_mf.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,11 @@ class CerebellarMF(ModelNumbaDfun):
428428

429429
external_input_ex_ex = NArray(
430430
label=":math:`\\nu_e^{drive}`",
431-
default=numpy.array([0.315e-3]),
432-
domain=Range(lo=0.0, hi=0.1, step=0.001),
433-
doc="External excitatory drive to excitatory population (GrC/GoC)")
431+
default=numpy.array([0.05]),
432+
domain=Range(lo=0.0, hi=0.5, step=0.001),
433+
doc="External excitatory drive to excitatory population (GrC/GoC). "
434+
"The default 0.05 produces oscillatory dynamics with peak/mean > 3x "
435+
"in theta-alpha range across connected CRBL nodes.")
434436

435437
external_input_ex_in = NArray(
436438
label=":math:`\\nu_i^{drive}`",
@@ -464,33 +466,39 @@ class CerebellarMF(ModelNumbaDfun):
464466

465467
mf_to_grc = NArray(
466468
label="Mossy→GrC split",
467-
default=numpy.array([0.97]),
469+
default=numpy.array([1.0]),
468470
domain=Range(lo=0.0, hi=1.0, step=0.01),
469-
doc="Fraction of mossy fiber input received by GrC")
471+
doc="Fraction of mossy fiber input received by GrC. "
472+
"Set to 1.0 to match the multimf_ww monolithic model where "
473+
"c_mossy is the full coupling signal without anatomical sub-fractions.")
470474

471475
mf_to_goc = NArray(
472476
label="Mossy→GoC split",
473-
default=numpy.array([0.03]),
477+
default=numpy.array([1.0]),
474478
domain=Range(lo=0.0, hi=1.0, step=0.01),
475-
doc="Fraction of mossy fiber input received by GoC")
479+
doc="Fraction of mossy fiber input received by GoC. "
480+
"Set to 1.0 to match the multimf_ww monolithic model.")
476481

477482
pf_to_goc = NArray(
478483
label="Parallel→GoC split",
479-
default=numpy.array([0.14]),
484+
default=numpy.array([1.0]),
480485
domain=Range(lo=0.0, hi=1.0, step=0.01),
481-
doc="Fraction of parallel fiber input received by GoC")
486+
doc="Fraction of parallel fiber input received by GoC. "
487+
"Set to 1.0 to match the multimf_ww monolithic model.")
482488

483489
pf_to_mli = NArray(
484490
label="Parallel→MLI split",
485-
default=numpy.array([0.55]),
491+
default=numpy.array([1.0]),
486492
domain=Range(lo=0.0, hi=1.0, step=0.01),
487-
doc="Fraction of parallel fiber input received by MLI")
493+
doc="Fraction of parallel fiber input received by MLI. "
494+
"Set to 1.0 to match the multimf_ww monolithic model.")
488495

489496
pf_to_pc = NArray(
490497
label="Parallel→PC split",
491-
default=numpy.array([0.31]),
498+
default=numpy.array([1.0]),
492499
domain=Range(lo=0.0, hi=1.0, step=0.01),
493-
doc="Fraction of parallel fiber input received by PC")
500+
doc="Fraction of parallel fiber input received by PC. "
501+
"Set to 1.0 to match the multimf_ww monolithic model.")
494502

495503
# -----------------------------------------------------------------------
496504
# Model metadata
@@ -499,6 +507,9 @@ class CerebellarMF(ModelNumbaDfun):
499507
label="Coupling terms",
500508
default=["mossy", "parallel"])
501509

510+
# nb-hybrid: use custom CerebellarMF Mako template — do NOT add state_variable_dfuns
511+
_nb_hybrid_custom_template = "nb-cerebellar-dfun.py.mako"
512+
502513
parameter_names = List(
503514
of=str,
504515
label="List of parameters for this model",
@@ -527,10 +538,10 @@ class CerebellarMF(ModelNumbaDfun):
527538
state_variable_range = Final(
528539
label="State Variable ranges [lo, hi]",
529540
default={
530-
"GrC": numpy.array([0.5e3, 0.5e3]),
531-
"GoC": numpy.array([5.0e3, 5.0e3]),
532-
"MLI": numpy.array([15.0e3, 15.0e3]),
533-
"PC": numpy.array([38.0e3, 38.0e3]),
541+
"GrC": numpy.array([0.1, 0.1]),
542+
"GoC": numpy.array([0.02, 0.02]),
543+
"MLI": numpy.array([0.2, 0.2]),
544+
"PC": numpy.array([0.1, 0.1]),
534545
"noise": numpy.array([0.0, 0.0]),
535546
},
536547
doc="""Expected dynamic range for each state variable.
@@ -666,7 +677,7 @@ def TF_inhibitory_goc(self, fe, fi, fe_ext, fi_ext, W=0):
666677
return self._TF_goc(fe, fi, fe_ext, fi_ext, W,
667678
self.P_goc, self.Q_grc_goc, self.Q_goc_goc,
668679
self.tau_grc_goc, self.tau_goc_goc,
669-
self.E_i, self.E_i,
680+
self.E_e, self.E_i,
670681
self.g_L_goc, self.C_m_goc, self.E_L_goc,
671682
self.K_grc_goc, self.K_goc_goc,
672683
self.Q_mf_goc, self.tau_mf_goc,

0 commit comments

Comments
 (0)