Suite No. 2 Upgrade: Izhikevich to V1-V4 Spectrolaminar Proxy Readouts¶
Pipeline: Emitter -> Source -> Field -> Probe -> Objective -> Optimizer.
Learning objectives¶
- Configure one reduced Izhikevich emitter through
jaxfne. - Compare E/PV/SST/VIP reduced-emitter presets through package-level arrays.
- Build
net1, a 100-emitter uniformly sampled 3D column. - Generate raster, LFP-proxy, CSD-proxy, EEG-proxy, MEG-proxy, and EMM-proxy figures without tutorial-local plotting functions.
- Configure a V1-V4 six-layer scaffold with feedforward and feedback metadata.
- Tune solver-tuned noise amplitude toward a firing-rate target with the Suite No. 2 AGSDR-Adam utility.
Question¶
How far can a compact jaxfne grammar carry the workflow from one reduced emitter to a two-area laminar scaffold while preserving reusable source/field/probe readouts?
Mathematical glossary flow¶
Reduced Izhikevich emitter¶
Formal equation:
Reset rule:
Terms: \(v_i\) is the reduced voltage-proxy state, \(u_i\) is recovery, \(a,b,c,d\) set class-specific dynamics, and \(I_i(t)\) combines base drive, recurrent input, and stochastic drive.
Worded equation: voltage changes according to intrinsic recovery, a nonlinear voltage term, and input current; threshold events reset the emitter state.
Implementation: jaxfne.emitters.IzhikevichEmitter, jaxfne.emitters.simulate_eig_izhikevich, and Suite No. 2 config builders.
Source/readout projection¶
Formal equation:
Terms: \(S_n(t)\) is a source proxy from emitter \(n\), \(W_{cn}\) is a declared projection weight, and \(Y_c(t)\) is a channel/contact readout.
Worded equation: each readout channel is a weighted sum of source activity.
Implementation: jaxfne.fields.LinearReadout, jaxfne.fields.project_laminar_sources, and jaxfne.vis.* figure functions.
Package-level workflow¶
The notebook uses only package-level helpers:
import jaxfne as jtfne
cfg_net1 = jtfne.suite2_net1_config(seed=7, n=100, duration_ms=1000.0, dt_ms=0.1)
model_net1 = jtfne.construct(cfg_net1)
bundle_net1 = jtfne.suite2_run_bundle(model_net1, seed=7, duration_ms=1000.0, dt_ms=0.1)
fig_panel = jtfne.vis.spectrolaminar_suite(bundle_net1["signals"], max_freq_hz=80.0)
V1-V4 scaffold:
cfg_v1v4 = jtfne.suite2_v1_v4_config(seed=7, n_per_area=400, duration_ms=1000.0, dt_ms=0.1)
model_v1v4 = jtfne.construct(cfg_v1v4)
Figures¶
Core figures are generated by reusable visualization functions:
jtfne.vis.raster(..., sort_by="z")jtfne.vis.lfp_traces(...)jtfne.vis.csd_traces(...)jtfne.vis.eeg(...)jtfne.vis.meg(...)jtfne.vis.emm(...)jtfne.vis.spectrolaminar_suite(...)jtfne.vis.circuit3d(...)
Configuration Reference¶
All Suite No. 2 workflows are specified through the chainable Configuration API.
Every field listed here stores in cfg.metadata; none are physical statuss.
Smoke config vs full config¶
import jaxfne as jtfne
# ── Smoke config (fast, 10 neurons, 100 ms) ─────────────────────────────────
cfg_smoke = jtfne.suite2_net1_config(seed=7, n=10, duration_ms=100.0, dt_ms=0.1)
# ── Full config (100 neurons, 1000 ms) ───────────────────────────────────────
cfg_full = jtfne.suite2_net1_config(seed=7, n=100, duration_ms=1000.0, dt_ms=0.1)
# ── V1-V4 multi-area scaffold ────────────────────────────────────────────────
cfg_v1v4 = jtfne.suite2_v1_v4_config(seed=7, n_per_area=400, duration_ms=1000.0, dt_ms=0.1)
The same 10-domain grammar applies to both:
cfg = (
jtfne.Configuration()
.runtime(seed=7, duration_ms=1000.0, dt_ms=0.1, dtype="float32")
.column("V1", layers=["L1", "L2/3", "L4", "L5", "L6"], n=100)
.cell_types({"E": 0.75, "PV": 0.10, "SST": 0.08, "VIP": 0.07})
.connectivity(within_area="all_to_all_uniform_random", within_gain=0.45)
.set_emitter("izhikevich", "cortical_eig")
.probes(["spikes", "V_m", "source", "LFP", "CSD"], n_contacts=16)
.field(domain="laminar_column", conductivity="proxy", boundary="mean_zero_neumann")
)
Runtime domain (cfg.runtime)¶
| Parameter | Default | Unit / status | Description |
|---|---|---|---|
seed |
42 |
integer | PRNG seed for all random operations |
duration_ms |
1000.0 |
ms | Total simulation duration |
dt_ms |
0.1 |
ms | Fixed timestep (forward Euler) |
dtype |
"float32" |
string | JAX array dtype ("float32" or "float64") |
backend |
"cpu" |
string | JAX backend ("cpu", "gpu") |
jit |
True |
bool | Enable jax.jit compilation for main kernels |
vmap |
True |
bool | Enable jax.vmap over trial batches |
n_trials |
1 |
integer | Number of stochastic trials |
Column domain (cfg.column)¶
| Parameter | Default | Unit / status | Description |
|---|---|---|---|
column_name |
"single_column" |
string | Column/area identifier |
layers |
["L1","L2/3","L4","L5","L6"] |
list | Layer labels (declarative) |
n |
100 |
integer | Total neuron count per column |
x_size_mm |
0.5 |
mm | Lateral x extent (proxy geometry) |
y_size_mm |
0.5 |
mm | Lateral y extent (proxy geometry) |
z_size_mm |
1.6 |
mm | Laminar depth extent (proxy geometry) |
geometry_status |
"declared_metadata" |
string | Always declared_metadata; no 3D PDE grid |
Cell-type domain (cfg.cell_types)¶
| Cell type | Global fraction | Sign | Izhikevich preset | Drive default (a.u.) |
|---|---|---|---|---|
E (excitatory) |
0.75 |
+1 |
cortical_eig |
5.0 |
PV (fast-spiking) |
0.10 |
−1 |
cortical_eig |
3.0 |
SST (Martinotti) |
0.08 |
−1 |
cortical_eig |
3.5 |
VIP (disinhibitory) |
0.07 |
−1 |
cortical_eig |
3.0 |
Izhikevich parameters by cell type (cortical_eig preset)¶
| Parameter | E | PV | SST | VIP | Unit |
|---|---|---|---|---|---|
| a | 0.02 | 0.10 | 0.02 | 0.02 | 1/ms |
| b | 0.20 | 0.20 | 0.25 | −0.10 | dimensionless |
| c | −65.0 | −65.0 | −65.0 | −55.0 | mV |
| d | 8.0 | 2.0 | 2.0 | 6.0 | mV/ms |
| Spike threshold | 30 | 30 | 30 | 30 | mV |
| Reset V | −65 | −65 | −65 | −55 | mV |
PV has high a (fast recovery) and low d (weak AHP) → fast-spiking.
VIP has negative b (bistable subthreshold) and higher reset c → irregular firing.
Connectivity domain (cfg.connectivity)¶
| Parameter | Default | Unit / status | Description |
|---|---|---|---|
within_area |
"all_to_all_uniform_random" |
string | Recurrent topology mode |
within_gain |
0.45 |
dimensionless | Global weight scale (net1); 0.35 for V1-V4 |
E_weight_range |
(0.5, 2.0) |
a.u. | Excitatory weight range |
I_weight_range |
(-1.5, -0.5) |
a.u. | Inhibitory weight range |
synaptic_tau_ms |
5.0 |
ms | Exponential synapse decay constant |
sign_policy |
"intrinsic" |
string | Sign from emitter type, not overridden |
seed |
None |
integer | Edge-weight PRNG seed |
Drive domain (cfg.drive)¶
| Parameter | Default | Unit / status | Description |
|---|---|---|---|
baseline_drive_by_cell_type |
{"E": 5.0, "PV": 3.0, "SST": 3.5, "VIP": 3.0} |
a.u. | Constant external drive per cell type |
noise_policy |
"additive_poisson" |
string | Stochastic drive mode |
noise_amplitude |
0.5 |
a.u. | Noise scale (tuned by suite2_tune_noise_agsdr_adam) |
time_schedule |
"constant" |
string | Drive profile ("constant", "pulse", "ramp") |
trial_variability |
False |
bool | Vary seed across trials |
Inter-column connectivity domain (cfg.inter_column_connectivity)¶
For V1-V4 only. Declarative metadata; connectivity is stored as parameter dicts, resolved into sparse matrices only at simulate() time.
| Parameter | Default | Unit / status | Description |
|---|---|---|---|
source_area |
"V1" |
string | Feedforward origin |
target_area |
"V4" |
string | Feedforward target |
mode |
"sparse" |
string | Topology ("sparse", "all_to_all") |
p_feedforward |
0.3 |
probability | V1→V4 connection probability |
p_feedback |
0.2 |
probability | V4→V1 connection probability |
feedforward_weight_range |
(0.5, 2.0) |
a.u. | V1→V4 weight range |
feedback_weight_range |
(0.3, 1.5) |
a.u. | V4→V1 weight range |
layer_to_layer_map |
{"L2/3": "L4", "L5": "L1"} |
dict | Declared source→target layer routing |
Field domain (cfg.field)¶
| Parameter | Value | Status |
|---|---|---|
domain |
"laminar_column" |
Proxy geometry |
conductivity |
"proxy" |
Not calibrated |
boundary |
"mean_zero_neumann" |
Boundary convention |
field_solver_status |
"linear_solver" |
Immutable |
amplitude_status |
False |
Immutable |
source_projection_mode |
"proxy_no_field_solve" |
Proxy only |
Probe domain (cfg.probes)¶
| Probe mode | Default contacts | Returns | Scope |
|---|---|---|---|
"spikes" |
N neurons | bool [N, T] |
Spike indicator |
"V_m" |
N neurons | float32 [N, T] |
Voltage-proxy |
"source" |
N neurons | float32 [N, T] |
Source current proxy |
"LFP" |
16 | float32 [Z, T] |
LFP-proxy |
"CSD" |
16 | float32 [Z, T] |
CSD-proxy (2nd spatial derivative) |
"EEG" |
4 | float32 [4, T] |
EEG proxy (declared leadfield) |
"MEG" |
4 | float32 [4, T] |
MEG proxy (declared leadfield) |
"EMM" |
1 | float32 [1, T] |
Signaling-energy proxy |
All probes carry units_or_status: "proxy_relative_units" and
amplitude_status: false.
Objective domain (cfg.objective)¶
| Parameter | Default | Description |
|---|---|---|
firing_rate_target |
{"E": 8.0, "PV": 15.0, "SST": 4.0, "VIP": 2.0} |
Target Hz per cell type |
band_definitions |
{"alpha_beta": (8.0, 25.0), "gamma": (40.0, 150.0)} |
Hz ranges |
rejection_gates |
{"max_firing_rate": (0.0, 200.0)} |
Hard acceptance bounds |
Optimizer domain (cfg.optimizer)¶
| Parameter | Default | Description |
|---|---|---|
optimizer_family |
"AGSDR" |
Optimizer type ("AGSDR", "random_search") |
surrogate_status |
"soft_rate_surrogate" |
Inner-loop approximation; not for statements |
budget |
50 |
Optimization iterations |
hard_gates |
{"model_status": "computational_scaffold"} |
Cannot be overridden |
Simulation Execution¶
Core pipeline¶
import jaxfne as jtfne
cfg = jtfne.suite2_net1_config(seed=7, n=100, duration_ms=1000.0, dt_ms=0.1)
model = jtfne.construct(cfg)
# Run bundle: returns signals, report, and config
bundle = jtfne.suite2_run_bundle(model, seed=7, duration_ms=1000.0, dt_ms=0.1)
signals = bundle["signals"] # Signals namedtuple
report = bundle["report"] # JSON-safe metadata dict
Solver semantics (per timestep)¶
The integration uses forward Euler with fixed dt_ms:
- Evaluate recurrent input:
I_rec = W @ S_prev(dense or sparse edge-list) - Evaluate external drive:
I_ext = baseline_drive + I_noise(noise_amplitude, key) - Update
vanduvia Izhikevich equations - Detect threshold: if
v >= 30, record spike, resetv = c,u = u + d - Update synaptic traces: exponential decay
tau = synaptic_tau_ms - Record all probe outputs for this timestep
Numerical bounds¶
| Quantity | Clamp / reset | Value |
|---|---|---|
Membrane potential v |
Hard clip | [-100, +50] mV |
| Spike threshold | Hard | 30 mV |
| Reset value | Cell-type specific | c parameter |
| Synaptic trace | Decay only | Never negative |
Output structure¶
suite2_run_bundle() returns:
{
"signals": Signals(
spikes = jnp.array([N_neurons, N_steps]), # bool
V_m = jnp.array([N_neurons, N_steps]), # float32
source = jnp.array([N_neurons, N_steps]), # float32
LFP = jnp.array([N_contacts, N_steps]), # float32 proxy
CSD = jnp.array([N_contacts, N_steps]), # float32 proxy
# ...EEG, MEG, EMM if requested
),
"report": {
"seed": 7,
"duration_ms": 1000.0,
"dt_ms": 0.1,
"n_steps": 10000,
"firing_rate_per_cell_type": {"E": ..., "PV": ..., "SST": ..., "VIP": ...},
"status_fields": {
"run_status": "tutorial_scaffold",
"model_status": "computational_scaffold",
"field_solver_status": "linear_solver",
"amplitude_status": False,
},
},
}
Noise tuning¶
Use suite2_tune_noise_agsdr_adam to tune noise_amplitude toward the
firing-rate target:
tuned_model, tune_report = jtfne.suite2_tune_noise_agsdr_adam(
model,
seed=7,
duration_ms=500.0, # shorter for tuning runs
dt_ms=0.1,
n_steps=30,
)
# Re-run with tuned model:
bundle_tuned = jtfne.suite2_run_bundle(tuned_model, seed=7, duration_ms=1000.0, dt_ms=0.1)
The surrogate optimizer minimizes the squared deviation from the firing-rate target. The surrogate path is for inner-loop optimization only; it does not produce physical amplitude statuss.
Manifest & Reproducibility¶
Every simulation run should be accompanied by a manifest capturing all inputs and outputs for auditability.
Manifest structure¶
import jaxfne as jtfne
manifest = jtfne.manifest(
config=cfg,
signals=bundle["signals"],
report=bundle["report"],
seed=7,
)
# Validate manifest is JSON-safe (no NaN/Inf)
import json
json.dumps(manifest, allow_nan=False) # must not raise
The manifest includes:
{
"version": "0.3.14",
"seed": 7,
"duration_ms": 1000.0,
"dt_ms": 0.1,
"n_steps": 10000,
"configuration": { "...": "..." },
"outputs": {
"spikes": {"shape": [100, 10000], "dtype": "bool"},
"V_m": {"shape": [100, 10000], "dtype": "float32"},
"LFP": {"shape": [16, 10000], "dtype": "float32"}
},
"statistics": {
"firing_rate_mean_per_cell_type": {"E": 8.3, "PV": 14.7, "SST": 3.8, "VIP": 1.9}
},
"status_fields": {
"run_status": "tutorial_scaffold",
"model_status": "computational_scaffold",
"field_solver_status": "linear_solver",
"amplitude_status": false
}
}
Reproducibility¶
To reproduce a run exactly:
cfg2 = jtfne.suite2_net1_config(seed=7, n=100, duration_ms=1000.0, dt_ms=0.1)
model2 = jtfne.construct(cfg2)
bundle2 = jtfne.suite2_run_bundle(model2, seed=7, duration_ms=1000.0, dt_ms=0.1)
# Outputs are bit-identical to bundle["signals"] within float32 rounding
import jax.numpy as jnp
assert jnp.allclose(bundle["signals"].V_m, bundle2["signals"].V_m)
Validation gates¶
Before accepting any output:
| Gate | Check | Remediation |
|---|---|---|
| Finiteness | jnp.all(jnp.isfinite(signals.V_m)) |
Reduce drive or dt_ms |
| Firing rate | Per-cell-type rate in [0.1, 150] Hz |
Adjust within_gain or drive |
| Spectral positivity | All band powers ≥ 0 | Check CSD/LFP output |
| JSON-safety | json.dumps(manifest, allow_nan=False) |
Never export NaN/Inf |
| Status fields | amplitude_status == False |
Never override |
Simulation-only outputs: The manifest records configuration and output statistics. PDE residuals, convergence diagnostics, and calibration certificates are outside scope — the proxy field operator requires none.
Interpretation of Results¶
Expected firing rates¶
| Cell type | Expected range | Target (tuned) |
|---|---|---|
| E (pyramidal) | 5–15 Hz | 8 Hz |
| PV (fast-spiking) | 10–30 Hz | 15 Hz |
| SST (Martinotti) | 2–10 Hz | 4 Hz |
| VIP (disinhibitory) | 1–5 Hz | 2 Hz |
If observed rates are >2× outside these ranges, the network is unstable or frozen.
Expected spectrolaminar proxy power¶
LFP power is in proxy relative units (not µV²):
- Alpha/beta (8–25 Hz): Typically highest in layers 4 and 5/6. Range
[0.1, 1.0]proxy units. - Gamma (40–150 Hz): Often highest in superficial layers (L2/3, L4). Range
[0.02, 0.3]proxy units.
Cell-type roles¶
| Cell type | Role | Ablation effect |
|---|---|---|
| E | Primary driver; recurrent excitation | Network goes silent (too little) or unstable (too much) |
| PV | Fast feedback inhibition | Loss causes runaway firing and loss of gamma |
| SST | Dendritic inhibition | Loss reduces layer-specific selectivity |
| VIP | Disinhibition of E via PV suppression | Loss reduces gain modulation |
Null comparison¶
To confirm spectrolaminar features are not artifactual: 1. Shuffle spike times within each trial (preserves firing rate) 2. Recompute LFP/CSD proxy from shuffled spikes 3. Real band power should exceed shuffled by >2× for meaningful signal
When to discard a run¶
Discard if any of the following:
- Any signal contains NaN or Inf
- Any cell-type firing rate is outside [0.1, 150] Hz
- amplitude_status was overridden (not possible via public API)
- Manifest JSON serialization fails
Failure Modes¶
| Symptom | Likely cause | Remediation |
|---|---|---|
| All neurons silent (rate ≈ 0 Hz) | Drive too low or inhibition too strong | Increase baseline_drive_by_cell_type["E"]; decrease within_gain |
| Runaway firing (>100 Hz sustained) | Drive too high or E dominance | Decrease drive; increase PV/SST drive |
| NaN or Inf in output | Numerical overflow; dt_ms too large |
Reduce dt_ms to 0.05; reduce drive amplitude |
| Flat LFP (no oscillations) | Insufficient recurrent feedback | Increase within_gain; check synaptic tau |
| VIP neurons always silent | VIP drive below threshold | Increase baseline_drive_by_cell_type["VIP"] |
| CSD all zeros | Source projection degenerate | Check n_contacts >= 3; verify column height > 0 |
| Slow JIT compile (>60 s) | Shape instability / recompilation loop | Fix n, n_steps, n_contacts before first run |
| Suite runs differ across machines | x64 not enabled consistently | Call jtfne.enable_x64() before array construction |
Dense recurrent matrix on small CPUs¶
For n > 500, the dense W @ S matrix multiply becomes expensive on CPU.
Use the recurrent_backend="edge_list" option in RuntimeConfig to switch to
a sparse edge-list kernel:
from jaxfne.core import RuntimeConfig
rt = RuntimeConfig(recurrent_backend="edge_list")
sim = jtfne.simulation(duration_ms=1000.0, dt_ms=0.1, seed=7, runtime=rt)
Exercises¶
-
Smoke first: Run
suite2_net1_config(n=10, duration_ms=100.0)before attemptingn=100to confirm the full pipeline executes. -
PV ablation: Set
baseline_drive_by_cell_type["PV"] = 0.0and rerun. Observe how gamma-band power changes when fast inhibition is removed. -
SST ablation: Repeat with
SST = 0.0. Compare to PV ablation — SST loss tends to broaden layer selectivity rather than collapse gamma. -
Noise tuning convergence: Run
suite2_tune_noise_agsdr_adamfor 10, 20, and 50 steps. Plot the objective value versus iteration count. -
V1-V4 feedforward dominance: In
suite2_v1_v4_config, setp_feedback = 0.0(feedforward only). Does V4 gamma power decrease? -
Contact density sweep: Vary
n_contactsfrom 4 to 32 and plot the spatial resolution of the CSD-proxy profile. -
Null check: Shuffle spike times in
bundle["signals"].spikesand recompute LFP/CSD. Confirm real band power > 2× shuffled power.
Coverage boundary¶
This tutorial covers reduced emitters, declared source projection, relative proxy readouts, and package-level figure generation. Solver-tuned amplitudes, subject-specific head geometry, and empirical parameter fitting belong to later workflows.
Extended Mathematical Glossary¶
Source tensor construction¶
Formal equation:
Terms: - \(S[t, n]\): source proxy from emitter \(n\) at timestep \(t\) - \(R[t]\): population spike rate (relative units) - \(I_{\text{decomposed}}\): capacitive + ionic current - \(I_{\text{synap}}\): synaptic input current - \(I_{\text{total}}\): membrane current (total of all sources)
Worded equation: source proxy is selected from available current decompositions or spike rate, validated for finite values and single-source consistency.
Implementation location: jaxfne.fields.construct_source_tensor
Scope boundary: Proxy relative units. Physical amplitude calibration is outside scope.
Geometric projection tensor (laminar approximation)¶
Formal equation:
Terms: - \(\mathbf{M}_{cn}\): entry of the row-normalized geometric projection tensor (mapping contact \(c\) to emitter \(n\)) - \(z_c\): relative laminar depth coordinate of contact \(c\) - \(z_n\): relative laminar depth coordinate of emitter \(n\) - \(\sigma\): declared standard deviation (width parameter) of the Gaussian profile
Worded equation: the geometric projection operator is a row-normalized Gaussian weight matrix representing a homogeneous, isotropic infinite-medium proxy operator design note, not current calibrated field-solver evidence.
Implementation location: jaxfne.fields._row_normalize and jaxfne.fields.project_laminar_sources
Scope boundary: Homogeneous isotropic infinite-medium proxy operator. Calibrated field-solver evidence is outside scope; this is a proxy operator design only.
LFP-proxy linear projection¶
Formal equation:
Terms: - \(\text{LFP}[t, c]\): LFP-proxy at contact \(c\) - \(K_{cn}\): row-normalized Gaussian kernel (contact \(c\) to emitter \(n\)) - \(S[t, n]\): source proxy from emitter \(n\)
Worded equation: LFP-proxy is a weighted sum of source-proxy traces, with weights from a row-stochastic contact kernel.
Implementation location: jaxfne.fields.project_laminar_sources
Scope boundary: Laminar proxy only. PDE solution and physical calibration are outside scope.
CSD-proxy (second spatial derivative)¶
Formal equation:
Terms: - \(\text{CSD}[t, c]\): current-source-density proxy at contact \(c\) - \(\Phi_e\): extracellular potential-proxy (LFP-proxy) - \(z_c\): laminar depth coordinate
Worded equation: CSD-proxy is the negative second spatial derivative of the potential-proxy along the contact axis, computed via finite differences.
Implementation location: jaxfne.fields.project_laminar_sources, lines ~130–133
Scope boundary: Proxy approximation only. Resistive-field PDE computation is outside scope.
EEG/MEG linear proxy readout¶
Formal equation:
Terms: - \(Y_{\text{EEG/MEG}}\): EEG or MEG proxy trace - \(L_c\): declared EEG/MEG leadfield for channel \(c\) (toy deterministic basis) - \(S[t, n]\): source proxy
Worded equation: EEG and MEG proxies are linear projections of source activity through declared (not empirically measured) leadfields.
Implementation location: jaxfne.fields.eeg_proxy_transform, jaxfne.fields.meg_proxy_transform, jaxfne.vis.eeg, jaxfne.vis.meg
Scope boundary: Declared geometry only. Relative proxy units; head geometry and real sensor placement are outside scope.
EMM-proxy (signaling-energy summary)¶
Formal equation:
Terms: - \(E_{\text{proxy}}\): relative signaling-energy proxy (normalized) - \(R[t]\): spike rate proxy - \(S[t]\): source-proxy vector - \(\Phi_e[t]\): potential-proxy vector - \(\lambda_1, \lambda_2, \lambda_3\): weighting factors
Worded equation: EMM-proxy is a normalized weighted combination of spike rate, source L1-norm, and field L2-norm.
Implementation location: jaxfne.fields.emm_proxy_transform, jaxfne.vis.emm
Scope boundary: Relative proxy units only. Biophysical metabolism is outside scope.
Spectrolaminar band power summary¶
Formal equation:
where \(B \in \{\text{alpha/beta} = [8, 25]\text{ Hz}, \text{gamma} = [40, 150]\text{ Hz}\}\)
Terms: - \(P_{\text{band}}[c]\): mean power in frequency band for contact \(c\) - \(\text{PSD}[f, c]\): power spectral density (Welch estimate) - \(B\): frequency band (alpha/beta or gamma)
Worded equation: Spectrolaminar profile is the mean PSD in each named frequency band, computed per contact.
Implementation location: jaxfne.fields.spectrolaminar_bandpower
Scope boundary: Relative power, proxy signal. Amplitude calibration is outside scope.
V1/V4 feedforward-feedback routing metadata¶
Formal equation:
Terms: - \(W_{\text{ff/fb}}\): connectivity matrix mask (declarative) - source/target: area (V1 or V4) and layer assignment
Worded equation: V1-to-V4 feedforward and V4-to-V1 feedback connectivity are declared as separate sparse weight matrices.
Implementation location: jaxfne.core.suite2_v1_v4_config, connectiv ity metadata section
Scope boundary: Declared metadata only. Fitted weights and anatomical validation are outside scope.
Figure Placeholders¶
The following figures are referenced in the notebook but not yet committed as PNG files. They will be generated by running the notebook:
-
Figure placeholder: spectrolaminar_suite_panel — Six-panel figure (raster, LFP-proxy, CSD-proxy, PSD, EEG-proxy, EMM-proxy). Generated by
jtfne.vis.spectrolaminar_suite(). Available until generated by tutorials/jaxfne_suite_no_2_spectrolaminar_motif.ipynb. -
Figure placeholder: circuit3d_layout_scatter — 3D scatter plot of V1-V4 emitter positions. Generated by
jtfne.vis.circuit3d(). Available until generated by tutorials/jaxfne_suite_no_2_spectrolaminar_motif.ipynb.
These placeholders mark where final PNG or PDF figures should be placed once the notebook is executed and validated.