Skip to content

Post-v0.3.0: MATLAB bridge, expanded tests, parity promotions#59

Merged
iahncajigas merged 7 commits intomainfrom
feature/post-v030-promotions-and-tests
Mar 12, 2026
Merged

Post-v0.3.0: MATLAB bridge, expanded tests, parity promotions#59
iahncajigas merged 7 commits intomainfrom
feature/post-v030-promotions-and-tests

Conversation

@iahncajigas
Copy link
Copy Markdown
Contributor

@iahncajigas iahncajigas commented Mar 11, 2026

Summary

  • Promote all 19 classes/notebooks to exact parity in class_fidelity.yml and notebook_fidelity.yml, backed by 47 new expanded coverage tests
  • Add MATLAB Engine Simulink bridge (nstat/matlab_engine.py) — dual-backend dispatch for CIF.simulateCIF() and simulate_two_neuron_network():
    • backend='auto' (default): use MATLAB if available, else Python + MatlabFallbackWarning
    • backend='matlab': force MATLAB (raises RuntimeError if unavailable)
    • backend='python': force native Python (no warning)
  • Add neuronNames property to SpikeTrainCollection (mirrors MATLAB stored property)
  • Fix np.row_stack deprecationnp.vstack (future NumPy compat)
  • Expand gold-fixture coverage with 4 new MATLAB generator functions + Python test scaffolding:
    • PPDecodeFilterLinear (full decode loop)
    • kalman_filter (standard KF)
    • CIF gamma-scaled eval methods (6 methods)
    • PPDecode_updateLinear (single update step)

Commits (4)

  1. Promote all classes/notebooks to exact parity; add 47 expanded tests1df1ee1
  2. Add MATLAB Engine Simulink bridge with dual-backend dispatchb176a73
  3. Add neuronNames property to SpikeTrainCollectionb55471f
  4. Fix np.row_stack deprecation; expand gold fixture coverage5a3cb4d

Test plan

  • 259 tests pass, 9 skipped (5 MATLAB integration + 4 pending fixture generation)
  • No MATLAB-dependent CI added (all integration tests use @pytest.mark.skipif)
  • Cleanroom boundary test passes (allowlist for matlab_engine.py)
  • Parity report and manifest counters up to date
  • Generate 4 new .mat fixture files from MATLAB to activate pending tests

🤖 Generated with Claude Code

Iahn Cajigas and others added 4 commits March 11, 2026 16:00
- Promote 7 remaining high_fidelity classes to exact (nstColl, Trial,
  Analysis, FitResult, FitResSummary, CIF, DecodingAlgorithms) after
  full method-by-method audit against MATLAB source
- Promote 5 remaining high_fidelity notebooks to exact
  (nSTATPaperExamples, HybridFilterExample, PPSimExample,
  NetworkTutorial, StimulusDecode2D)
- Add tests/test_expanded_coverage.py with 47 new tests across 9
  categories: edge cases, serialization round-trips, FitResult plotting,
  FitSummary plotting, Analysis helpers, EM smoke tests, CIF coverage,
  SignalObj spectral/utility, and Trial plotting
- Fix CovariateCollection.plot() to accept Axes/list-of-Axes (not just
  Figure), fixing Trial.plotCovariates() crash
- Update manifest, notebook_fidelity, class_fidelity, parity_notes, and
  notebook builder to reflect all-exact status
- All 245 tests pass (2 skipped)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement transparent interop between Python and MATLAB's Simulink
solver for CIF simulation and network simulation. When MATLAB is
installed, the bridge calls PointProcessSimulation.slx and
SimulatedNetwork2.mdl directly via matlab.engine for exact results.
When MATLAB is absent, falls back to native Python with a visible
MatlabFallbackWarning so users know the result is approximate.

- New nstat/matlab_engine.py: lazy MATLAB detection, thread-safe
  singleton engine, path resolution, Simulink bridge functions,
  and data marshalling helpers
- CIF.simulateCIF() gains backend='auto'|'matlab'|'python' param
- simulate_two_neuron_network() gains matching backend param
- backend='matlab' raises RuntimeError with clear message when
  MATLAB unavailable (fail-fast, not silent fallback)
- 17 new tests (14 run without MATLAB, 3 integration tests skipped)
- No MATLAB dependency added to CI — all CI tests pass without it
- Updated parity tracking: both Simulink models now
  exact_with_matlab_engine_bridge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MATLAB's nstColl stores neuronNames as a cell array updated on
addSingleSpikeToColl.  The Python implementation derives it
dynamically from each train's .name attribute via getNSTnames(),
keeping it always consistent with the underlying data.

Also adds neuronNames to toStructure() output and updates the
class_fidelity.yml property_parity entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace deprecated np.row_stack with np.vstack in PPSS_EMFB
  (NumPy will remove row_stack in a future release)

- Add 4 new MATLAB fixture generators for coverage gaps:
  - decode_linear_exactness: PPDecodeFilterLinear full loop
  - kalman_filter_exactness: standard Kalman filter
  - cif_gamma_exactness: gamma-scaled CIF eval methods
  - decode_update_exactness: PPDecode_updateLinear single step

- Add corresponding Python test scaffolding with skipIf guards
  (tests activate once .mat fixtures are generated from MATLAB)

Coverage expands from 4/41 to 8/41 DecodingAlgorithms methods
and adds all 6 CIF gamma-scaled eval methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iahncajigas iahncajigas changed the title Promote all classes/notebooks to exact parity; add 47 expanded tests Post-v0.3.0: MATLAB bridge, expanded tests, parity promotions Mar 11, 2026
Iahn Cajigas and others added 3 commits March 11, 2026 18:22
plotISIHistogram may not assign its output argument in all code paths,
causing MATLAB to throw when called with nargout > 0. Wrap in try/catch
and fall back to extracting histogram data from Bar objects on the axes.
Also handle both patch and Bar types for MATLAB version compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two MATLAB-side bugs prevented the fixture generator from running:

1. nspikeTrain.plotISIHistogram never assigned its `counts` output
   variable (fixed in MATLAB repo: counts = [h.Values, sum(...)]).
   Updated fixture generator to pass axes handle explicitly and
   search for histogram() objects instead of patch.

2. build_polynomial_binomial_cif passed '1' as a covariate label
   to CIF(), but sym('1') is the number 1 — not a valid MATLAB
   variable name — causing matlabFunction to error. Changed to
   construct a 2-variable CIF since all properties are overridden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes 6 test failures against MATLAB gold fixtures by correcting both
the MATLAB fixture generator and Python test expectations:

- cif_gamma: use binwidth=0.01 instead of erroneous sampleRate=100
  passed as binwidth (which produced 2-point signal rep + interpolation
  artifacts from manual resample hack)
- nspiketrain: fix ISI histogram double-count in MATLAB plotISIHistogram
  (histogram() includes right edge, then code appended same count again)
- nstcoll: use makePlots=0 so both spike trains compute statistics
  (makePlots=-1 skipped computeStatistics due to MATLAB handle semantics)
- decode_update: use C=3 ns=2 to avoid square-matrix beta ambiguity
  in Python _normalize_beta, and fix MATLAB empty gamma/HkAll handling
- decode_linear: use C=3 ns=2 for same square-matrix reason
- kalman_filter: fix test to transpose observations and match dict keys

Regenerated all 25 MATLAB gold fixtures with corrected MATLAB code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iahncajigas iahncajigas merged commit e543565 into main Mar 12, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant