diff --git a/nstat/notebook_fidelity_audit.py b/nstat/notebook_fidelity_audit.py index 427c9172..b6f40fe3 100644 --- a/nstat/notebook_fidelity_audit.py +++ b/nstat/notebook_fidelity_audit.py @@ -18,6 +18,7 @@ IMG_SRC_RE = re.compile(r']+src="([^"]+)"', re.IGNORECASE) SECTION_RE = re.compile(r"^%%", re.MULTILINE) PYTHON_SECTION_RE = re.compile(r"^# SECTION\b", re.MULTILINE) +CI_GROUP_ORDER = ("helpfile_full", "parity_core", "ci_smoke", "core", "smoke") def _repo_root() -> Path: @@ -45,6 +46,12 @@ def _count_python_sections(notebook_path: Path) -> int: return len(PYTHON_SECTION_RE.findall(text)) +def _load_notebook_groups(base: Path) -> dict[str, set[str]]: + payload = yaml.safe_load((base / "tools" / "notebooks" / "topic_groups.yml").read_text(encoding="utf-8")) or {} + groups = payload.get("groups", {}) + return {str(name): {str(topic) for topic in values or []} for name, values in groups.items()} + + def build_notebook_fidelity_audit( repo_root: Path | None = None, *, @@ -54,6 +61,7 @@ def build_notebook_fidelity_audit( matlab_root = default_matlab_repo_root(base) if matlab_repo_root is None else matlab_repo_root.resolve() help_root = matlab_root / "helpfiles" notes = load_notebook_parity_notes(base) + topic_groups = _load_notebook_groups(base) items: list[dict[str, Any]] = [] for row in notes: @@ -66,12 +74,17 @@ def build_notebook_fidelity_audit( matlab_m_path = help_root / f"{matlab_stem}.m" matlab_html_path = help_root / f"{matlab_stem}.html" matlab_available = matlab_m_path.exists() and matlab_html_path.exists() + current_run_group = next((group for group in CI_GROUP_ORDER if topic in topic_groups.get(group, set())), None) item: dict[str, Any] = { "topic": topic, "source_matlab": str(row["source_matlab"]), "python_notebook": str(row["file"]), + "status": str(row["fidelity_status"]), "fidelity_status": str(row["fidelity_status"]), + "executable_in_ci": current_run_group is not None, + "current_run_group": current_run_group, + "fixture_backed": False, "remaining_differences": str(row["remaining_differences"]), "python_sections": python_sections, "python_expected_figures": int(figure_contract.expected_count) if figure_contract else 0, @@ -113,6 +126,7 @@ def build_notebook_fidelity_audit( "matlab": "https://github.com/cajigaslab/nSTAT", "python": "https://github.com/cajigaslab/nSTAT-python", }, + "status_legend": ["exact", "high_fidelity", "partial", "missing"], "matlab_repo_root": str(matlab_root), "items": items, } diff --git a/nstat/parity_report.py b/nstat/parity_report.py index fa51512e..09ebb417 100644 --- a/nstat/parity_report.py +++ b/nstat/parity_report.py @@ -18,6 +18,8 @@ from nstat.simulink_fidelity import ( iter_outstanding_simulink_items, load_simulink_fidelity_audit, + normalize_simulink_status, + summarize_simulink_statuses, summarize_simulink_strategies, ) @@ -90,12 +92,12 @@ def render_parity_report(repo_root: Path | None = None) -> str: notebook_counts = summarize_notebook_fidelity(notebook_fidelity) notebook_partial = iter_outstanding_notebook_fidelity(notebook_fidelity) simulink_counts = summarize_simulink_strategies(simulink_fidelity) + simulink_status_counts = summarize_simulink_statuses(simulink_fidelity) simulink_outstanding = iter_outstanding_simulink_items(simulink_fidelity) simulink_reference_only = [ row for row in simulink_fidelity.get("items", []) - if str(row.get("current_python_status", "")).strip() == "reference_only" - or str(row.get("python_strategy", "")).strip() == "reference_only" + if normalize_simulink_status(row) == "reference_only" ] lines = [ "# nSTAT Python Parity Report", @@ -161,6 +163,18 @@ def render_parity_report(repo_root: Path | None = None) -> str: "", "## Simulink Fidelity Summary", "", + "| Status | Count |", + "|---|---:|", + ] + ) + for status in simulink_fidelity.get("status_legend", ()): + lines.append(f"| `{status}` | {simulink_status_counts.get(status, 0)} |") + + lines.extend( + [ + "", + "## Simulink Strategy Summary", + "", "| Strategy | Count |", "|---|---:|", ] @@ -277,11 +291,11 @@ def render_parity_report(repo_root: Path | None = None) -> str: else: for row in simulink_outstanding: lines.append( - f"- `{row['model_name']}` -> `{row['model_path']}` [{row['python_strategy']}/{row['current_python_status']}]: {row['chosen_interoperability_strategy']}" + f"- `{row['model_name']}` -> `{row['model_path']}` [{normalize_simulink_status(row)}]: {row['chosen_interoperability_strategy']}" ) for row in simulink_reference_only: lines.append( - f"- `{row['model_name']}` -> `{row['model_path']}` [{row['python_strategy']}/{row['current_python_status']}]: {row['chosen_interoperability_strategy']}" + f"- `{row['model_name']}` -> `{row['model_path']}` [{normalize_simulink_status(row)}]: {row['chosen_interoperability_strategy']}" ) lines.extend(["", "## Justified Non-Applicable Items", ""]) diff --git a/nstat/simulink_fidelity.py b/nstat/simulink_fidelity.py index 63647341..ab180dc1 100644 --- a/nstat/simulink_fidelity.py +++ b/nstat/simulink_fidelity.py @@ -6,6 +6,17 @@ import yaml +STATUS_LEGEND = ( + "exact_native_python", + "high_fidelity_native_python", + "generated_code_wrapped", + "packaged_runtime", + "matlab_engine_reference", + "reference_only", + "unsupported", +) + + def _repo_root() -> Path: return Path(__file__).resolve().parents[1] @@ -16,6 +27,30 @@ def load_simulink_fidelity_audit(repo_root: Path | None = None) -> dict[str, Any return yaml.safe_load(path.read_text(encoding="utf-8")) +def normalize_simulink_status(row: dict[str, Any]) -> str: + explicit = str(row.get("status", "")).strip() + if explicit: + return explicit + + strategy = str(row.get("python_strategy", "")).strip() + current = str(row.get("current_python_status", "")).strip() + if strategy == "reference_only" or current == "reference_only": + return "reference_only" + if strategy == "generated_code_wrapped": + return "generated_code_wrapped" + if strategy == "packaged_runtime": + return "packaged_runtime" + if strategy == "matlab_engine_fallback": + return "matlab_engine_reference" + if strategy == "unsupported" or current == "unsupported": + return "unsupported" + if strategy == "native_python" and current == "exact": + return "exact_native_python" + if strategy == "native_python" and current == "high_fidelity": + return "high_fidelity_native_python" + return current or strategy or "unsupported" + + def summarize_simulink_strategies(payload: dict[str, Any]) -> dict[str, int]: counts = {status: 0 for status in payload.get("strategy_legend", [])} for row in payload.get("items", []): @@ -26,16 +61,29 @@ def summarize_simulink_strategies(payload: dict[str, Any]) -> dict[str, int]: return counts +def summarize_simulink_statuses(payload: dict[str, Any]) -> dict[str, int]: + counts = {status: 0 for status in payload.get("status_legend", STATUS_LEGEND)} + for row in payload.get("items", []): + status = normalize_simulink_status(row) + if status not in counts: + counts[status] = 0 + counts[status] += 1 + return counts + + def iter_outstanding_simulink_items(payload: dict[str, Any]) -> list[dict[str, Any]]: return [ row for row in payload.get("items", []) - if row.get("current_python_status") in {"missing", "partial", "unsupported"} + if normalize_simulink_status(row) in {"unsupported"} ] __all__ = [ "iter_outstanding_simulink_items", "load_simulink_fidelity_audit", + "normalize_simulink_status", + "STATUS_LEGEND", + "summarize_simulink_statuses", "summarize_simulink_strategies", ] diff --git a/parity/manifest.yml b/parity/manifest.yml index fc5f3619..d87b1885 100644 --- a/parity/manifest.yml +++ b/parity/manifest.yml @@ -1,13 +1,13 @@ version: 1 -generated_on: 2026-03-07 +generated_on: '2026-03-08' source_repositories: matlab: https://github.com/cajigaslab/nSTAT python: https://github.com/cajigaslab/nSTAT-python status_legend: - - mapped - - partial - - missing - - not_applicable +- mapped +- partial +- missing +- not_applicable summary: public_api: mapped: 18 @@ -40,418 +40,446 @@ summary: missing: 0 not_applicable: 0 public_api: - - matlab: Analysis - matlab_path: Analysis.m - python_target: nstat.Analysis - python_path: nstat/analysis.py - status: mapped - notes: Exported from the package root. - - matlab: CIF - matlab_path: CIF.m - python_target: nstat.CIF - python_path: nstat/cif.py - status: mapped - notes: Canonical CIF class is exported from the package root. - - matlab: ConfidenceInterval - matlab_path: ConfidenceInterval.m - python_target: nstat.ConfidenceInterval - python_path: nstat/ConfidenceInterval.py - status: mapped - notes: Compatibility adapter is exported from the package root. - - matlab: ConfigColl - matlab_path: ConfigColl.m - python_target: nstat.ConfigColl - python_path: nstat/ConfigColl.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: CovColl - matlab_path: CovColl.m - python_target: nstat.CovColl - python_path: nstat/CovColl.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: Covariate - matlab_path: Covariate.m - python_target: nstat.Covariate - python_path: nstat/signal.py - status: mapped - notes: Canonical signal object is exported from the package root. - - matlab: DecodingAlgorithms - matlab_path: DecodingAlgorithms.m - python_target: nstat.DecodingAlgorithms - python_path: nstat/decoding_algorithms.py - status: mapped - notes: Exported from the package root. - - matlab: Events - matlab_path: Events.m - python_target: nstat.Events - python_path: nstat/events.py - status: mapped - notes: Exported from the package root. - - matlab: FitResSummary - matlab_path: FitResSummary.m - python_target: nstat.FitResSummary - python_path: nstat/FitResSummary.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: FitResult - matlab_path: FitResult.m - python_target: nstat.FitResult - python_path: nstat/FitResult.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: History - matlab_path: History.m - python_target: nstat.History - python_path: nstat/history.py - status: mapped - notes: Exported from the package root. - - matlab: SignalObj - matlab_path: SignalObj.m - python_target: nstat.SignalObj - python_path: nstat/SignalObj.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: Trial - matlab_path: Trial.m - python_target: nstat.Trial - python_path: nstat/trial.py - status: mapped - notes: Exported from the package root. - - matlab: TrialConfig - matlab_path: TrialConfig.m - python_target: nstat.TrialConfig - python_path: nstat/trial.py - status: mapped - notes: Exported from the package root. - - matlab: nspikeTrain - matlab_path: nspikeTrain.m - python_target: nstat.nspikeTrain - python_path: nstat/nspikeTrain.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: nstColl - matlab_path: nstColl.m - python_target: nstat.nstColl - python_path: nstat/nstColl.py - status: mapped - notes: MATLAB-style adapter is exported from the package root. - - matlab: getPaperDataDirs - matlab_path: getPaperDataDirs.m - python_target: nstat.getPaperDataDirs - python_path: nstat/data_manager.py - status: mapped - notes: Package root exports both MATLAB-style and snake-case helpers. - - matlab: nSTAT_Install - matlab_path: nSTAT_Install.m - python_target: nstat.nSTAT_Install - python_path: nstat/nstat_install.py - status: mapped - notes: MATLAB-style alias is exported from the package root. - - matlab: nstatOpenHelpPage - matlab_path: nstatOpenHelpPage.m - python_target: null - python_path: null - status: not_applicable - notes: MATLAB help-browser integration does not have a direct Python equivalent. +- matlab: Analysis + matlab_path: Analysis.m + python_target: nstat.Analysis + python_path: nstat/analysis.py + status: mapped + notes: Exported from the package root. +- matlab: CIF + matlab_path: CIF.m + python_target: nstat.CIF + python_path: nstat/cif.py + status: mapped + notes: Canonical CIF class is exported from the package root. +- matlab: ConfidenceInterval + matlab_path: ConfidenceInterval.m + python_target: nstat.ConfidenceInterval + python_path: nstat/ConfidenceInterval.py + status: mapped + notes: Compatibility adapter is exported from the package root. +- matlab: ConfigColl + matlab_path: ConfigColl.m + python_target: nstat.ConfigColl + python_path: nstat/ConfigColl.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: CovColl + matlab_path: CovColl.m + python_target: nstat.CovColl + python_path: nstat/CovColl.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: Covariate + matlab_path: Covariate.m + python_target: nstat.Covariate + python_path: nstat/signal.py + status: mapped + notes: Canonical signal object is exported from the package root. +- matlab: DecodingAlgorithms + matlab_path: DecodingAlgorithms.m + python_target: nstat.DecodingAlgorithms + python_path: nstat/decoding_algorithms.py + status: mapped + notes: Exported from the package root. +- matlab: Events + matlab_path: Events.m + python_target: nstat.Events + python_path: nstat/events.py + status: mapped + notes: Exported from the package root. +- matlab: FitResSummary + matlab_path: FitResSummary.m + python_target: nstat.FitResSummary + python_path: nstat/FitResSummary.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: FitResult + matlab_path: FitResult.m + python_target: nstat.FitResult + python_path: nstat/FitResult.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: History + matlab_path: History.m + python_target: nstat.History + python_path: nstat/history.py + status: mapped + notes: Exported from the package root. +- matlab: SignalObj + matlab_path: SignalObj.m + python_target: nstat.SignalObj + python_path: nstat/SignalObj.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: Trial + matlab_path: Trial.m + python_target: nstat.Trial + python_path: nstat/trial.py + status: mapped + notes: Exported from the package root. +- matlab: TrialConfig + matlab_path: TrialConfig.m + python_target: nstat.TrialConfig + python_path: nstat/trial.py + status: mapped + notes: Exported from the package root. +- matlab: nspikeTrain + matlab_path: nspikeTrain.m + python_target: nstat.nspikeTrain + python_path: nstat/nspikeTrain.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: nstColl + matlab_path: nstColl.m + python_target: nstat.nstColl + python_path: nstat/nstColl.py + status: mapped + notes: MATLAB-style adapter is exported from the package root. +- matlab: getPaperDataDirs + matlab_path: getPaperDataDirs.m + python_target: nstat.getPaperDataDirs + python_path: nstat/data_manager.py + status: mapped + notes: Package root exports both MATLAB-style and snake-case helpers. +- matlab: nSTAT_Install + matlab_path: nSTAT_Install.m + python_target: nstat.nSTAT_Install + python_path: nstat/nstat_install.py + status: mapped + notes: MATLAB-style alias is exported from the package root. +- matlab: nstatOpenHelpPage + matlab_path: nstatOpenHelpPage.m + python_target: null + python_path: null + status: not_applicable + notes: MATLAB help-browser integration does not have a direct Python equivalent. help_workflows: - - matlab: NeuralSpikeAnalysis_top - matlab_path: helpfiles/NeuralSpikeAnalysis_top.m - python_target: docs/NeuralSpikeAnalysis_top.md - status: mapped - notes: Python docs expose a top-level navigation page that mirrors the MATLAB help home. - - matlab: PaperOverview - matlab_path: helpfiles/PaperOverview.m - python_target: docs/PaperOverview.md - status: mapped - notes: Python docs expose a paper-aligned toolbox map page with the same workflow categories. - - matlab: ClassDefinitions - matlab_path: helpfiles/ClassDefinitions.m - python_target: docs/ClassDefinitions.md - status: mapped - notes: Python docs expose a class-definition index for the MATLAB-facing public API names. - - matlab: Examples - matlab_path: helpfiles/Examples.m - python_target: docs/Examples.md - status: mapped - notes: Python docs expose an example index mirroring the MATLAB helpfile categories and names. - - matlab: DocumentationSetup2025b - matlab_path: helpfiles/DocumentationSetup2025b.m - python_target: docs/DocumentationSetup.md - status: mapped - notes: Python replaces MATLAB help-browser integration with a Sphinx documentation setup and rebuild guide. - - matlab: AnalysisExamples - matlab_path: helpfiles/AnalysisExamples.mlx - python_target: notebooks/AnalysisExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: AnalysisExamples2 - matlab_path: helpfiles/AnalysisExamples2.mlx - python_target: notebooks/AnalysisExamples2.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: ConfidenceIntervalOverview - matlab_path: helpfiles/ConfidenceIntervalOverview.m - python_target: notebooks/ConfidenceIntervalOverview.ipynb - status: mapped - notes: Tutorial notebook exists with matching name. - - matlab: ConfigCollExamples - matlab_path: helpfiles/ConfigCollExamples.mlx - python_target: notebooks/ConfigCollExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: CovCollExamples - matlab_path: helpfiles/CovCollExamples.mlx - python_target: notebooks/CovCollExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: CovariateExamples - matlab_path: helpfiles/CovariateExamples.mlx - python_target: notebooks/CovariateExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: DecodingExample - matlab_path: helpfiles/DecodingExample.mlx - python_target: notebooks/DecodingExample.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: DecodingExampleWithHist - matlab_path: helpfiles/DecodingExampleWithHist.mlx - python_target: notebooks/DecodingExampleWithHist.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: EventsExamples - matlab_path: helpfiles/EventsExamples.mlx - python_target: notebooks/EventsExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: ExplicitStimulusWhiskerData - matlab_path: helpfiles/ExplicitStimulusWhiskerData.mlx - python_target: notebooks/ExplicitStimulusWhiskerData.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: FitResSummaryExamples - matlab_path: helpfiles/FitResSummaryExamples.mlx - python_target: notebooks/FitResSummaryExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: FitResultExamples - matlab_path: helpfiles/FitResultExamples.mlx - python_target: notebooks/FitResultExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: FitResultReference - matlab_path: helpfiles/FitResultReference.m - python_target: notebooks/FitResultReference.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: HippocampalPlaceCellExample - matlab_path: helpfiles/HippocampalPlaceCellExample.mlx - python_target: notebooks/HippocampalPlaceCellExample.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: HistoryExamples - matlab_path: helpfiles/HistoryExamples.mlx - python_target: notebooks/HistoryExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: HybridFilterExample - matlab_path: helpfiles/HybridFilterExample.mlx - python_target: notebooks/HybridFilterExample.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: NetworkTutorial - matlab_path: helpfiles/NetworkTutorial.mlx - python_target: notebooks/NetworkTutorial.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: PPSimExample - matlab_path: helpfiles/PPSimExample.mlx - python_target: notebooks/PPSimExample.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: PPThinning - matlab_path: helpfiles/PPThinning.mlx - python_target: notebooks/PPThinning.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: PSTHEstimation - matlab_path: helpfiles/PSTHEstimation.mlx - python_target: notebooks/PSTHEstimation.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: SignalObjExamples - matlab_path: helpfiles/SignalObjExamples.mlx - python_target: notebooks/SignalObjExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: StimulusDecode2D - matlab_path: helpfiles/StimulusDecode2D.mlx - python_target: notebooks/StimulusDecode2D.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: TrialConfigExamples - matlab_path: helpfiles/TrialConfigExamples.mlx - python_target: notebooks/TrialConfigExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: TrialExamples - matlab_path: helpfiles/TrialExamples.mlx - python_target: notebooks/TrialExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: ValidationDataSet - matlab_path: helpfiles/ValidationDataSet.mlx - python_target: notebooks/ValidationDataSet.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: mEPSCAnalysis - matlab_path: helpfiles/mEPSCAnalysis.mlx - python_target: notebooks/mEPSCAnalysis.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: nSTATPaperExamples - matlab_path: helpfiles/nSTATPaperExamples.mlx - python_target: notebooks/nSTATPaperExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: nSpikeTrainExamples - matlab_path: helpfiles/nSpikeTrainExamples.mlx - python_target: notebooks/nSpikeTrainExamples.ipynb - status: mapped - notes: Notebook exists with matching name. - - matlab: nstCollExamples - matlab_path: helpfiles/nstCollExamples.mlx - python_target: notebooks/nstCollExamples.ipynb - status: mapped - notes: Notebook exists with matching name. +- matlab: NeuralSpikeAnalysis_top + matlab_path: helpfiles/NeuralSpikeAnalysis_top.m + python_target: docs/NeuralSpikeAnalysis_top.md + status: mapped + notes: Python docs expose a top-level navigation page that mirrors the MATLAB help + home. +- matlab: PaperOverview + matlab_path: helpfiles/PaperOverview.m + python_target: docs/PaperOverview.md + status: mapped + notes: Python docs expose a paper-aligned toolbox map page with the same workflow + categories. +- matlab: ClassDefinitions + matlab_path: helpfiles/ClassDefinitions.m + python_target: docs/ClassDefinitions.md + status: mapped + notes: Python docs expose a class-definition index for the MATLAB-facing public + API names. +- matlab: Examples + matlab_path: helpfiles/Examples.m + python_target: docs/Examples.md + status: mapped + notes: Python docs expose an example index mirroring the MATLAB helpfile categories + and names. +- matlab: DocumentationSetup2025b + matlab_path: helpfiles/DocumentationSetup2025b.m + python_target: docs/DocumentationSetup.md + status: mapped + notes: Python replaces MATLAB help-browser integration with a Sphinx documentation + setup and rebuild guide. +- matlab: AnalysisExamples + matlab_path: helpfiles/AnalysisExamples.mlx + python_target: notebooks/AnalysisExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: AnalysisExamples2 + matlab_path: helpfiles/AnalysisExamples2.mlx + python_target: notebooks/AnalysisExamples2.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: ConfidenceIntervalOverview + matlab_path: helpfiles/ConfidenceIntervalOverview.m + python_target: notebooks/ConfidenceIntervalOverview.ipynb + status: mapped + notes: Tutorial notebook exists with matching name. +- matlab: ConfigCollExamples + matlab_path: helpfiles/ConfigCollExamples.mlx + python_target: notebooks/ConfigCollExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: CovCollExamples + matlab_path: helpfiles/CovCollExamples.mlx + python_target: notebooks/CovCollExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: CovariateExamples + matlab_path: helpfiles/CovariateExamples.mlx + python_target: notebooks/CovariateExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: DecodingExample + matlab_path: helpfiles/DecodingExample.mlx + python_target: notebooks/DecodingExample.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: DecodingExampleWithHist + matlab_path: helpfiles/DecodingExampleWithHist.mlx + python_target: notebooks/DecodingExampleWithHist.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: EventsExamples + matlab_path: helpfiles/EventsExamples.mlx + python_target: notebooks/EventsExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: ExplicitStimulusWhiskerData + matlab_path: helpfiles/ExplicitStimulusWhiskerData.mlx + python_target: notebooks/ExplicitStimulusWhiskerData.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: FitResSummaryExamples + matlab_path: helpfiles/FitResSummaryExamples.mlx + python_target: notebooks/FitResSummaryExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: FitResultExamples + matlab_path: helpfiles/FitResultExamples.mlx + python_target: notebooks/FitResultExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: FitResultReference + matlab_path: helpfiles/FitResultReference.m + python_target: notebooks/FitResultReference.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: HippocampalPlaceCellExample + matlab_path: helpfiles/HippocampalPlaceCellExample.mlx + python_target: notebooks/HippocampalPlaceCellExample.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: HistoryExamples + matlab_path: helpfiles/HistoryExamples.mlx + python_target: notebooks/HistoryExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: HybridFilterExample + matlab_path: helpfiles/HybridFilterExample.mlx + python_target: notebooks/HybridFilterExample.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: NetworkTutorial + matlab_path: helpfiles/NetworkTutorial.mlx + python_target: notebooks/NetworkTutorial.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: PPSimExample + matlab_path: helpfiles/PPSimExample.mlx + python_target: notebooks/PPSimExample.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: PPThinning + matlab_path: helpfiles/PPThinning.mlx + python_target: notebooks/PPThinning.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: PSTHEstimation + matlab_path: helpfiles/PSTHEstimation.mlx + python_target: notebooks/PSTHEstimation.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: SignalObjExamples + matlab_path: helpfiles/SignalObjExamples.mlx + python_target: notebooks/SignalObjExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: StimulusDecode2D + matlab_path: helpfiles/StimulusDecode2D.mlx + python_target: notebooks/StimulusDecode2D.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: TrialConfigExamples + matlab_path: helpfiles/TrialConfigExamples.mlx + python_target: notebooks/TrialConfigExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: TrialExamples + matlab_path: helpfiles/TrialExamples.mlx + python_target: notebooks/TrialExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: ValidationDataSet + matlab_path: helpfiles/ValidationDataSet.mlx + python_target: notebooks/ValidationDataSet.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: mEPSCAnalysis + matlab_path: helpfiles/mEPSCAnalysis.mlx + python_target: notebooks/mEPSCAnalysis.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: nSTATPaperExamples + matlab_path: helpfiles/nSTATPaperExamples.mlx + python_target: notebooks/nSTATPaperExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: nSpikeTrainExamples + matlab_path: helpfiles/nSpikeTrainExamples.mlx + python_target: notebooks/nSpikeTrainExamples.ipynb + status: mapped + notes: Notebook exists with matching name. +- matlab: nstCollExamples + matlab_path: helpfiles/nstCollExamples.mlx + python_target: notebooks/nstCollExamples.ipynb + status: mapped + notes: Notebook exists with matching name. paper_examples: - - matlab: example01_mepsc_poisson - matlab_path: examples/paper/example01_mepsc_poisson.m - python_target: nstat.paper_examples_full.run_experiment1 - python_script: examples/paper/example01_mepsc_poisson.py - status: mapped - notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example01/. - - matlab: example02_whisker_stimulus_thalamus - matlab_path: examples/paper/example02_whisker_stimulus_thalamus.m - python_target: nstat.paper_examples_full.run_experiment2 - python_script: examples/paper/example02_whisker_stimulus_thalamus.py - status: mapped - notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example02/. - - matlab: example03_psth_and_ssglm - matlab_path: examples/paper/example03_psth_and_ssglm.m - python_target: nstat.paper_examples_full.run_experiment3 - python_script: examples/paper/example03_psth_and_ssglm.py - status: mapped - notes: Canonical Python script exports the MATLAB-named figure set for experiment3 and experiment3b into docs/figures/example03/. - - matlab: example04_place_cells_continuous_stimulus - matlab_path: examples/paper/example04_place_cells_continuous_stimulus.m - python_target: nstat.paper_examples_full.run_experiment4 - python_script: examples/paper/example04_place_cells_continuous_stimulus.py - status: mapped - notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example04/. - - matlab: example05_decoding_ppaf_pphf - matlab_path: examples/paper/example05_decoding_ppaf_pphf.m - python_target: nstat.paper_examples_full.run_experiment5 - python_script: examples/paper/example05_decoding_ppaf_pphf.py - status: mapped - notes: Canonical Python script exports the MATLAB-named figure set for experiment5, experiment5b, and experiment6 into docs/figures/example05/. - - matlab: nSTATPaperExamples section 3b - matlab_path: helpfiles/nSTATPaperExamples.m#example-3b - python_target: nstat.paper_examples_full.run_experiment3b - python_script: examples/paper/example03_psth_and_ssglm.py - status: mapped - notes: Section 3b is exported through the canonical example03 Python script and gallery. - - matlab: nSTATPaperExamples section 5b - matlab_path: helpfiles/nSTATPaperExamples.m#example-5b - python_target: nstat.paper_examples_full.run_experiment5b - python_script: examples/paper/example05_decoding_ppaf_pphf.py - status: mapped - notes: Section 5b is exported through the canonical example05 Python script and gallery. - - matlab: nSTATPaperExamples section 6 - matlab_path: helpfiles/nSTATPaperExamples.m#experiment-6 - python_target: nstat.paper_examples_full.run_experiment6 - python_script: examples/paper/example05_decoding_ppaf_pphf.py - status: mapped - notes: Section 6 is exported through the canonical example05 Python script and gallery. +- matlab: example01_mepsc_poisson + matlab_path: examples/paper/example01_mepsc_poisson.m + python_target: nstat.paper_examples_full.run_experiment1 + python_script: examples/paper/example01_mepsc_poisson.py + status: mapped + notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example01/. +- matlab: example02_whisker_stimulus_thalamus + matlab_path: examples/paper/example02_whisker_stimulus_thalamus.m + python_target: nstat.paper_examples_full.run_experiment2 + python_script: examples/paper/example02_whisker_stimulus_thalamus.py + status: mapped + notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example02/. +- matlab: example03_psth_and_ssglm + matlab_path: examples/paper/example03_psth_and_ssglm.m + python_target: nstat.paper_examples_full.run_experiment3 + python_script: examples/paper/example03_psth_and_ssglm.py + status: mapped + notes: Canonical Python script exports the MATLAB-named figure set for experiment3 + and experiment3b into docs/figures/example03/. +- matlab: example04_place_cells_continuous_stimulus + matlab_path: examples/paper/example04_place_cells_continuous_stimulus.m + python_target: nstat.paper_examples_full.run_experiment4 + python_script: examples/paper/example04_place_cells_continuous_stimulus.py + status: mapped + notes: Canonical Python script exports the MATLAB-named figure set into docs/figures/example04/. +- matlab: example05_decoding_ppaf_pphf + matlab_path: examples/paper/example05_decoding_ppaf_pphf.m + python_target: nstat.paper_examples_full.run_experiment5 + python_script: examples/paper/example05_decoding_ppaf_pphf.py + status: mapped + notes: Canonical Python script exports the MATLAB-named figure set for experiment5, + experiment5b, and experiment6 into docs/figures/example05/. +- matlab: nSTATPaperExamples section 3b + matlab_path: helpfiles/nSTATPaperExamples.m#example-3b + python_target: nstat.paper_examples_full.run_experiment3b + python_script: examples/paper/example03_psth_and_ssglm.py + status: mapped + notes: Section 3b is exported through the canonical example03 Python script and + gallery. +- matlab: nSTATPaperExamples section 5b + matlab_path: helpfiles/nSTATPaperExamples.m#example-5b + python_target: nstat.paper_examples_full.run_experiment5b + python_script: examples/paper/example05_decoding_ppaf_pphf.py + status: mapped + notes: Section 5b is exported through the canonical example05 Python script and + gallery. +- matlab: nSTATPaperExamples section 6 + matlab_path: helpfiles/nSTATPaperExamples.m#experiment-6 + python_target: nstat.paper_examples_full.run_experiment6 + python_script: examples/paper/example05_decoding_ppaf_pphf.py + status: mapped + notes: Section 6 is exported through the canonical example05 Python script and gallery. docs_gallery: - - matlab: docs/paper_examples.md - python_target: docs/paper_examples.md - status: mapped - notes: Generated from the canonical Python paper-example manifest. - - matlab: docs/figures/manifest.json - python_target: docs/figures/manifest.json - status: mapped - notes: Generated from the canonical Python paper-example manifest. - - matlab: docs/figures/example01/ - python_target: docs/figures/example01/ - status: mapped - notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical Python script. - - matlab: docs/figures/example02/ - python_target: docs/figures/example02/ - status: mapped - notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical Python script. - - matlab: docs/figures/example03/ - python_target: docs/figures/example03/ - status: mapped - notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical Python script. - - matlab: docs/figures/example04/ - python_target: docs/figures/example04/ - status: mapped - notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical Python script. - - matlab: docs/figures/example05/ - python_target: docs/figures/example05/ - status: mapped - notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical Python script. - - matlab: README five-example gallery - python_target: README.md - status: mapped - notes: README mirrors the MATLAB five-example gallery pattern and links the Python paper-example docs page. +- matlab: docs/paper_examples.md + python_target: docs/paper_examples.md + status: mapped + notes: Generated from the canonical Python paper-example manifest. +- matlab: docs/figures/manifest.json + python_target: docs/figures/manifest.json + status: mapped + notes: Generated from the canonical Python paper-example manifest. +- matlab: docs/figures/example01/ + python_target: docs/figures/example01/ + status: mapped + notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical + Python script. +- matlab: docs/figures/example02/ + python_target: docs/figures/example02/ + status: mapped + notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical + Python script. +- matlab: docs/figures/example03/ + python_target: docs/figures/example03/ + status: mapped + notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical + Python script. +- matlab: docs/figures/example04/ + python_target: docs/figures/example04/ + status: mapped + notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical + Python script. +- matlab: docs/figures/example05/ + python_target: docs/figures/example05/ + status: mapped + notes: Gallery directory contains the MATLAB-named PNG set generated by the canonical + Python script. +- matlab: README five-example gallery + python_target: README.md + status: mapped + notes: README mirrors the MATLAB five-example gallery pattern and links the Python + paper-example docs page. installer_setup: - - matlab: nSTAT_Install console entrypoint - matlab_path: nSTAT_Install.m - python_target: nstat-install - python_path: pyproject.toml - status: mapped - notes: Console script is defined in pyproject.toml. - - matlab: nSTAT_Install programmatic entrypoint - matlab_path: nSTAT_Install.m - python_target: nstat.install.nstat_install - python_path: nstat/install.py - status: mapped - notes: Programmatic installer exists and is documented. - - matlab: DownloadExampleData option - matlab_path: nSTAT_Install.m - python_target: nstat.install.nstat_install(download_example_data=...) - python_path: nstat/install.py - status: mapped - notes: Prompt/always/never modes exist in Python. - - matlab: RebuildDocSearch option - matlab_path: nSTAT_Install.m - python_target: nstat.install.nstat_install(rebuild_doc_search=...) - python_path: nstat/install.py - status: mapped - notes: The installer can rebuild the local Sphinx HTML search index and reports whether searchindex.js was created. - - matlab: CleanUserPathPrefs option - matlab_path: nSTAT_Install.m - python_target: nstat.install.nstat_install(clean_user_path_prefs=...) - python_path: nstat/install.py - status: not_applicable - notes: Accepted as a compatibility no-op because Python does not use MATLAB-style saved user path preferences. - - matlab: MATLAB runtime path pruning - matlab_path: nSTAT_Install.m - python_target: null - python_path: null - status: not_applicable - notes: Python packaging/import resolution replaces MATLAB path management. - - matlab: MATLAB toolbox cache refresh and savepath - matlab_path: nSTAT_Install.m - python_target: null - python_path: null - status: not_applicable - notes: There is no Python equivalent to MATLAB toolbox cache refresh or savepath persistence. +- matlab: nSTAT_Install console entrypoint + matlab_path: nSTAT_Install.m + python_target: nstat-install + python_path: pyproject.toml + status: mapped + notes: Console script is defined in pyproject.toml. +- matlab: nSTAT_Install programmatic entrypoint + matlab_path: nSTAT_Install.m + python_target: nstat.install.nstat_install + python_path: nstat/install.py + status: mapped + notes: Programmatic installer exists and is documented. +- matlab: DownloadExampleData option + matlab_path: nSTAT_Install.m + python_target: nstat.install.nstat_install(download_example_data=...) + python_path: nstat/install.py + status: mapped + notes: Prompt/always/never modes exist in Python. +- matlab: RebuildDocSearch option + matlab_path: nSTAT_Install.m + python_target: nstat.install.nstat_install(rebuild_doc_search=...) + python_path: nstat/install.py + status: mapped + notes: The installer can rebuild the local Sphinx HTML search index and reports + whether searchindex.js was created. +- matlab: CleanUserPathPrefs option + matlab_path: nSTAT_Install.m + python_target: nstat.install.nstat_install(clean_user_path_prefs=...) + python_path: nstat/install.py + status: not_applicable + notes: Accepted as a compatibility no-op because Python does not use MATLAB-style + saved user path preferences. +- matlab: MATLAB runtime path pruning + matlab_path: nSTAT_Install.m + python_target: null + python_path: null + status: not_applicable + notes: Python packaging/import resolution replaces MATLAB path management. +- matlab: MATLAB toolbox cache refresh and savepath + matlab_path: nSTAT_Install.m + python_target: null + python_path: null + status: not_applicable + notes: There is no Python equivalent to MATLAB toolbox cache refresh or savepath + persistence. repo_structure: - - item: canonical_package_layout - python_target: nstat/ - status: mapped - notes: The repo now uses a single root-level nstat/ package with no src/nstat mirror or repo-root package stub. +- item: canonical_package_layout + python_target: nstat/ + status: mapped + notes: The repo now uses a single root-level nstat/ package with no src/nstat mirror + or repo-root package stub. +fidelity_summary: + class_fidelity: + high_fidelity: 18 + not_applicable: 1 + notebook_fidelity: + high_fidelity: 13 + simulink_fidelity: + high_fidelity_native_python: 2 + reference_only: 10 diff --git a/parity/notebook_fidelity.yml b/parity/notebook_fidelity.yml index 02ed69b5..6678e39d 100644 --- a/parity/notebook_fidelity.yml +++ b/parity/notebook_fidelity.yml @@ -3,12 +3,21 @@ generated_on: '2026-03-08' source_repositories: matlab: https://github.com/cajigaslab/nSTAT python: https://github.com/cajigaslab/nSTAT-python +status_legend: +- exact +- high_fidelity +- partial +- missing matlab_repo_root: /Users/iahncajigas/Library/CloudStorage/Dropbox/Codex/nSTAT items: - topic: nSTATPaperExamples source_matlab: nSTATPaperExamples.mlx python_notebook: notebooks/nSTATPaperExamples.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now executes the canonical paper-example workflows through the standalone Python implementations and real figshare-backed datasets; exact numerical traces and figure styling still vary modestly because the Python @@ -29,7 +38,11 @@ items: - topic: TrialExamples source_matlab: TrialExamples.mlx python_notebook: notebooks/TrialExamples.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now mirrors the MATLAB Trial workflow with executable object construction, masking, history extraction, and plotting; only minor Python plotting defaults differ from the published MATLAB help output. @@ -49,7 +62,11 @@ items: - topic: AnalysisExamples source_matlab: AnalysisExamples.mlx python_notebook: notebooks/AnalysisExamples.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now follows the MATLAB standard-GLM workflow with the canonical `glm_data.mat` dataset and real KS/model-visualization figures; coefficient values and styling still vary modestly because the Python GLM backend @@ -70,7 +87,11 @@ items: - topic: AnalysisExamples2 source_matlab: AnalysisExamples2.mlx python_notebook: notebooks/AnalysisExamples2.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now follows the MATLAB toolbox workflow on the canonical `glm_data.mat` dataset with executable `Trial`, `ConfigColl`, and `Analysis` calls; exact coefficients and plot styling still vary modestly because the Python @@ -91,7 +112,11 @@ items: - topic: DecodingExample source_matlab: DecodingExample.mlx python_notebook: notebooks/DecodingExample.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: Workflow, model fitting, and decoded-stimulus figures now follow the MATLAB helpfile closely; exact traces still depend on stochastic simulation draws and Python plotting defaults. @@ -111,7 +136,11 @@ items: - topic: DecodingExampleWithHist source_matlab: DecodingExampleWithHist.mlx python_notebook: notebooks/DecodingExampleWithHist.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now mirrors the MATLAB history-aware decoding workflow closely; exact stochastic trajectories and figure styling still vary slightly under Python execution. @@ -131,7 +160,11 @@ items: - topic: ExplicitStimulusWhiskerData source_matlab: ExplicitStimulusWhiskerData.mlx python_notebook: notebooks/ExplicitStimulusWhiskerData.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now reproduces the dataset-backed lag search, stimulus-effect, and history-effect workflow with real figures; exact KS traces and coefficient values still vary modestly from MATLAB because the Python GLM @@ -152,7 +185,11 @@ items: - topic: HippocampalPlaceCellExample source_matlab: HippocampalPlaceCellExample.mlx python_notebook: notebooks/HippocampalPlaceCellExample.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now reproduces the dataset-backed place-cell model-comparison and field-visualization workflow with the same normalized 10-term Zernike basis used by MATLAB; exact AIC/BIC values and surface styling still vary @@ -174,7 +211,11 @@ items: - topic: HybridFilterExample source_matlab: HybridFilterExample.mlx python_notebook: notebooks/HybridFilterExample.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now reproduces the hybrid-filter simulation, single-run decoding, and averaged summary figures with real outputs; the Python port still uses the current hybrid-filter implementation instead of every MATLAB-specific @@ -195,7 +236,11 @@ items: - topic: PPSimExample source_matlab: PPSimExample.mlx python_notebook: notebooks/PPSimExample.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now follows the MATLAB recursive-CIF workflow with the native Python `CIF.simulateCIF` path; exact Simulink block timing and solver semantics are still not fixture-matched one-for-one against MATLAB. @@ -215,7 +260,11 @@ items: - topic: NetworkTutorial source_matlab: NetworkTutorial.mlx python_notebook: notebooks/NetworkTutorial.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now mirrors the MATLAB helpfile section order and published figure inventory with a native Python network simulator and MATLAB-style `Analysis` workflow; exact spike realizations still vary modestly because NumPy @@ -236,7 +285,11 @@ items: - topic: ValidationDataSet source_matlab: ValidationDataSet.mlx python_notebook: notebooks/ValidationDataSet.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now reproduces the constant-rate and piecewise-rate validation workflows with real `Trial`/`Analysis` objects and figure outputs; local execution uses the MATLAB-scale simulation sizes, while CI switches to a @@ -257,7 +310,11 @@ items: - topic: StimulusDecode2D source_matlab: StimulusDecode2D.mlx python_notebook: notebooks/StimulusDecode2D.ipynb + status: high_fidelity fidelity_status: high_fidelity + executable_in_ci: true + current_run_group: helpfile_full + fixture_backed: false remaining_differences: The notebook now follows the MATLAB nonlinear-CIF decoding workflow and uses `DecodingAlgorithms.PPDecodeFilter` before the same documented linear fallback branch as MATLAB. Exact decoded traces and figure styling can diff --git a/parity/report.md b/parity/report.md index dfb68f22..27c3077f 100644 --- a/parity/report.md +++ b/parity/report.md @@ -5,7 +5,7 @@ Generated from `parity/manifest.yml`, `parity/class_fidelity.yml`, `tools/notebo - MATLAB reference: https://github.com/cajigaslab/nSTAT - Python target: https://github.com/cajigaslab/nSTAT-python - Inventory version: 1 -- Generated on: 2026-03-07 +- Generated on: 2026-03-08 ## Summary @@ -47,6 +47,18 @@ Generated from `parity/manifest.yml`, `parity/class_fidelity.yml`, `tools/notebo ## Simulink Fidelity Summary +| Status | Count | +|---|---:| +| `exact_native_python` | 0 | +| `high_fidelity_native_python` | 2 | +| `generated_code_wrapped` | 0 | +| `packaged_runtime` | 0 | +| `matlab_engine_reference` | 0 | +| `reference_only` | 10 | +| `unsupported` | 0 | + +## Simulink Strategy Summary + | Strategy | Count | |---|---:| | `native_python` | 2 | @@ -85,16 +97,16 @@ No audit/runtime symbol mismatches were detected. ## Simulink Fidelity Deltas -- `PointProcessSimulationCont` -> `PointProcessSimulationCont.slx` [reference_only/reference_only]: Keep as reference while the Python port uses the native discrete simulation path. -- `PointProcessSimulationLegacy2010b` -> `PointProcessSimulation.mdl.r2010b` [reference_only/reference_only]: Treat as a compatibility/reference asset because the native Python port targets the current `PointProcessSimulation.slx` behavior rather than every historic MATLAB model format. -- `PointProcessSimulationLegacy2011a` -> `PointProcessSimulation.mdl.r2011a` [reference_only/reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. -- `PointProcessSimulationLegacy2011b` -> `PointProcessSimulation.mdl.r2011b` [reference_only/reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. -- `PointProcessSimulationLegacy2013a` -> `PointProcessSimulation.mdl.r2013a` [reference_only/reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. -- `PointProcessSimulationLegacySLX2013a` -> `PointProcessSimulation.slx.r2013a` [reference_only/reference_only]: Treat as a versioned MATLAB reference asset rather than a distinct Python execution target. -- `PointProcessSimulationThinningLegacy2011a` -> `PointProcessSimulationThinning.mdl.r2011a` [reference_only/reference_only]: Keep as a MATLAB reference asset while the Python port validates thinning behavior through `CIF.simulateCIFByThinning` and MATLAB-side fixture export. -- `PointProcessSimulationCache` -> `PointProcessSimulation.slxc` [reference_only/reference_only]: Treat as a MATLAB build artifact, not as a Python execution target. -- `HelpPointProcessSimulationCache` -> `helpfiles/PointProcessSimulation.slxc` [reference_only/reference_only]: Treat as a published-help artifact only. -- `SimulatedNetwork2Cache` -> `helpfiles/SimulatedNetwork2.slxc` [reference_only/reference_only]: Treat as a MATLAB build artifact, not a Python target. +- `PointProcessSimulationCont` -> `PointProcessSimulationCont.slx` [reference_only]: Keep as reference while the Python port uses the native discrete simulation path. +- `PointProcessSimulationLegacy2010b` -> `PointProcessSimulation.mdl.r2010b` [reference_only]: Treat as a compatibility/reference asset because the native Python port targets the current `PointProcessSimulation.slx` behavior rather than every historic MATLAB model format. +- `PointProcessSimulationLegacy2011a` -> `PointProcessSimulation.mdl.r2011a` [reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. +- `PointProcessSimulationLegacy2011b` -> `PointProcessSimulation.mdl.r2011b` [reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. +- `PointProcessSimulationLegacy2013a` -> `PointProcessSimulation.mdl.r2013a` [reference_only]: Treat as a compatibility/reference asset alongside the current `.slx` model. +- `PointProcessSimulationLegacySLX2013a` -> `PointProcessSimulation.slx.r2013a` [reference_only]: Treat as a versioned MATLAB reference asset rather than a distinct Python execution target. +- `PointProcessSimulationThinningLegacy2011a` -> `PointProcessSimulationThinning.mdl.r2011a` [reference_only]: Keep as a MATLAB reference asset while the Python port validates thinning behavior through `CIF.simulateCIFByThinning` and MATLAB-side fixture export. +- `PointProcessSimulationCache` -> `PointProcessSimulation.slxc` [reference_only]: Treat as a MATLAB build artifact, not as a Python execution target. +- `HelpPointProcessSimulationCache` -> `helpfiles/PointProcessSimulation.slxc` [reference_only]: Treat as a published-help artifact only. +- `SimulatedNetwork2Cache` -> `helpfiles/SimulatedNetwork2.slxc` [reference_only]: Treat as a MATLAB build artifact, not a Python target. ## Justified Non-Applicable Items diff --git a/parity/simulink_fidelity.yml b/parity/simulink_fidelity.yml index 490557e2..cd9b1ba8 100644 --- a/parity/simulink_fidelity.yml +++ b/parity/simulink_fidelity.yml @@ -4,151 +4,273 @@ source_repositories: matlab: https://github.com/cajigaslab/nSTAT python: https://github.com/cajigaslab/nSTAT-python strategy_legend: - - native_python - - generated_code_wrapped - - packaged_runtime - - matlab_engine_fallback - - unsupported - - reference_only +- native_python +- generated_code_wrapped +- packaged_runtime +- matlab_engine_fallback +- unsupported +- reference_only items: - - model_name: PointProcessSimulation - model_path: PointProcessSimulation.slx - purpose: Discrete point-process simulation used by `CIF.simulateCIF`, `PPSimExample`, and related help workflows. - matlab_usage: required_for_behavioral_parity - python_strategy: native_python - current_python_status: high_fidelity - deterministic_fixture_backed: yes - stochastic_tolerance_backed: yes - chosen_interoperability_strategy: Native Python simulation through `nstat.cif.CIF.simulateCIF`, with MATLAB-side `tests/python_port_fidelity/TestPythonSimulinkParity.m` serving as the cross-language reference checker. - fidelity_risks: - - Exact stochastic spike-count realizations differ between MATLAB and NumPy random generators even when the same seed is requested. - - The native Python path mirrors the Simulink transfer-function semantics for the published help workflows, but not every internal Simulink block configuration has a one-to-one Python analogue. - validation_plan: - - Compare deterministic lambda traces against MATLAB-generated fixtures and the MATLAB-side Simulink parity harness. - - Keep committed MATLAB gold fixtures for deterministic injected-uniform traces covering recursive history, eta, lambda-delta, and spike indicators, plus seeded Python regression tests for PPSimExample outputs in CI. - - model_name: PointProcessSimulationCont - model_path: PointProcessSimulationCont.slx - purpose: Continuous-time companion model kept with the MATLAB toolbox for simulation/reference work. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Keep as reference while the Python port uses the native discrete simulation path. - fidelity_risks: - - No Python-executable equivalent currently mirrors the continuous Simulink model directly. - validation_plan: - - Audit whether any MATLAB helpfile or paper workflow depends on the continuous model before promoting it beyond reference-only. - - model_name: PointProcessSimulationLegacy2010b - model_path: PointProcessSimulation.mdl.r2010b - purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility and regression reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a compatibility/reference asset because the native Python port targets the current `PointProcessSimulation.slx` behavior rather than every historic MATLAB model format. - fidelity_risks: - - Legacy `.mdl` files may embed solver or block-version behavior that differs from the current `.slx` model. - validation_plan: - - Keep inventoried and compare only if a MATLAB helpfile or published baseline is shown to depend on the legacy model specifically. - - model_name: PointProcessSimulationLegacy2011a - model_path: PointProcessSimulation.mdl.r2011a - purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility and regression reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside the current `.slx` model. - fidelity_risks: - - Block behavior may differ subtly from the current `.slx` model even when the published workflow is unchanged. - validation_plan: - - Keep inventoried and promote only if a workflow is shown to require this exact legacy model. - - model_name: PointProcessSimulationLegacy2011b - model_path: PointProcessSimulation.mdl.r2011b - purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility and regression reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside the current `.slx` model. - fidelity_risks: - - Block behavior may differ subtly from the current `.slx` model even when the published workflow is unchanged. - validation_plan: - - Keep inventoried and promote only if a workflow is shown to require this exact legacy model. - - model_name: PointProcessSimulationLegacy2013a - model_path: PointProcessSimulation.mdl.r2013a - purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility and regression reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside the current `.slx` model. - fidelity_risks: - - Block behavior may differ subtly from the current `.slx` model even when the published workflow is unchanged. - validation_plan: - - Keep inventoried and promote only if a workflow is shown to require this exact legacy model. - - model_name: PointProcessSimulationLegacySLX2013a - model_path: PointProcessSimulation.slx.r2013a - purpose: Version-specific discrete point-process SLX asset retained for MATLAB compatibility and regression reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a versioned MATLAB reference asset rather than a distinct Python execution target. - fidelity_risks: - - Version-specific SLX files are not stable Python execution targets and may diverge from the current published model. - validation_plan: - - Keep inventoried and compare only if a published workflow is tied to this asset specifically. - - model_name: PointProcessSimulationThinningLegacy2011a - model_path: PointProcessSimulationThinning.mdl.r2011a - purpose: Legacy thinning-based point-process simulation model retained for MATLAB compatibility/reference. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Keep as a MATLAB reference asset while the Python port validates thinning behavior through `CIF.simulateCIFByThinning` and MATLAB-side fixture export. - fidelity_risks: - - The legacy thinning model may encode branch behavior that is not separately exercised by current Python CI. - validation_plan: - - Keep inventoried and add direct MATLAB-reference comparisons if a helpfile or paper workflow depends on thinning-specific semantics. - - model_name: PointProcessSimulationCache - model_path: PointProcessSimulation.slxc - purpose: Simulink compiled cache artifact for `PointProcessSimulation`. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a MATLAB build artifact, not as a Python execution target. - fidelity_risks: - - Cache files are version-specific and not portable across environments. - validation_plan: - - None beyond confirming the source `.slx` model remains inventoried. - - model_name: HelpPointProcessSimulationCache - model_path: helpfiles/PointProcessSimulation.slxc - purpose: Published-help compiled cache artifact for the point-process simulation model. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a published-help artifact only. - fidelity_risks: - - Not executable from Python and tied to MATLAB's published help pipeline. - validation_plan: - - None beyond inventory coverage. - - model_name: SimulatedNetwork2 - model_path: helpfiles/SimulatedNetwork2.mdl - purpose: Two-neuron network simulation used by `NetworkTutorial` and related connectivity examples. - matlab_usage: required_for_example_execution - python_strategy: native_python - current_python_status: high_fidelity - deterministic_fixture_backed: yes - stochastic_tolerance_backed: yes - chosen_interoperability_strategy: Native Python execution through `nstat.simulators.simulate_two_neuron_network`, with MATLAB-side `tests/python_port_fidelity/TestPythonSimulinkParity.m` serving as the reference checker. - fidelity_risks: - - Exact spike trains still differ from Simulink because MATLAB and NumPy do not share the same binomial random stream. - - The native port mirrors the published NetworkTutorial parameterization and one-sample-delay semantics, but not every internal Simulink block detail is separately exposed. - validation_plan: - - Keep deterministic injected-uniform fixtures for probability traces, binary state traces, history/ensemble terms, and eta traces in CI. - - Keep committed MATLAB gold fixtures for `prob_head` and `state_head`, and treat seeded spike-count summaries as tolerance-based because MATLAB and NumPy random streams are not identical. - - Keep MATLAB-side parity checks for the actual connectivity layout and deterministic probability/state traces. - - model_name: SimulatedNetwork2Cache - model_path: helpfiles/SimulatedNetwork2.slxc - purpose: Simulink compiled cache artifact for `SimulatedNetwork2`. - matlab_usage: used_for_reference - python_strategy: reference_only - current_python_status: reference_only - chosen_interoperability_strategy: Treat as a MATLAB build artifact, not a Python target. - fidelity_risks: - - Cache files are version-specific and cannot serve as a stable Python execution path. - validation_plan: - - None beyond inventory coverage. +- model_name: PointProcessSimulation + model_path: PointProcessSimulation.slx + purpose: Discrete point-process simulation used by `CIF.simulateCIF`, `PPSimExample`, + and related help workflows. + matlab_usage: required_for_behavioral_parity + python_strategy: native_python + current_python_status: high_fidelity + deterministic_fixture_backed: true + stochastic_tolerance_backed: true + chosen_interoperability_strategy: Native Python simulation through `nstat.cif.CIF.simulateCIF`, + with MATLAB-side `tests/python_port_fidelity/TestPythonSimulinkParity.m` serving + as the cross-language reference checker. + fidelity_risks: + - Exact stochastic spike-count realizations differ between MATLAB and NumPy random + generators even when the same seed is requested. + - The native Python path mirrors the Simulink transfer-function semantics for the + published help workflows, but not every internal Simulink block configuration + has a one-to-one Python analogue. + validation_plan: + - Compare deterministic lambda traces against MATLAB-generated fixtures and the + MATLAB-side Simulink parity harness. + - Keep committed MATLAB gold fixtures for deterministic injected-uniform traces + covering recursive history, eta, lambda-delta, and spike indicators, plus seeded + Python regression tests for PPSimExample outputs in CI. + status: high_fidelity_native_python + python_equivalent: nstat.cif.CIF.simulateCIF + validation_strategy: deterministic injected-uniform trace fixtures plus seeded tolerance + checks + required_remediation: Broaden deterministic fixture coverage to additional branch + variants before promoting exact_native_python. +- model_name: PointProcessSimulationCont + model_path: PointProcessSimulationCont.slx + purpose: Continuous-time companion model kept with the MATLAB toolbox for simulation/reference + work. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Keep as reference while the Python port uses the + native discrete simulation path. + fidelity_risks: + - No Python-executable equivalent currently mirrors the continuous Simulink model + directly. + validation_plan: + - Audit whether any MATLAB helpfile or paper workflow depends on the continuous + model before promoting it beyond reference-only. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep reference_only unless a published workflow is shown to + depend on the continuous model. +- model_name: PointProcessSimulationLegacy2010b + model_path: PointProcessSimulation.mdl.r2010b + purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility + and regression reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a compatibility/reference asset because + the native Python port targets the current `PointProcessSimulation.slx` behavior + rather than every historic MATLAB model format. + fidelity_risks: + - Legacy `.mdl` files may embed solver or block-version behavior that differs from + the current `.slx` model. + validation_plan: + - Keep inventoried and compare only if a MATLAB helpfile or published baseline is + shown to depend on the legacy model specifically. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationLegacy2011a + model_path: PointProcessSimulation.mdl.r2011a + purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility + and regression reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside + the current `.slx` model. + fidelity_risks: + - Block behavior may differ subtly from the current `.slx` model even when the published + workflow is unchanged. + validation_plan: + - Keep inventoried and promote only if a workflow is shown to require this exact + legacy model. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationLegacy2011b + model_path: PointProcessSimulation.mdl.r2011b + purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility + and regression reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside + the current `.slx` model. + fidelity_risks: + - Block behavior may differ subtly from the current `.slx` model even when the published + workflow is unchanged. + validation_plan: + - Keep inventoried and promote only if a workflow is shown to require this exact + legacy model. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationLegacy2013a + model_path: PointProcessSimulation.mdl.r2013a + purpose: Legacy pre-SLX discrete point-process model retained for MATLAB compatibility + and regression reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a compatibility/reference asset alongside + the current `.slx` model. + fidelity_risks: + - Block behavior may differ subtly from the current `.slx` model even when the published + workflow is unchanged. + validation_plan: + - Keep inventoried and promote only if a workflow is shown to require this exact + legacy model. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationLegacySLX2013a + model_path: PointProcessSimulation.slx.r2013a + purpose: Version-specific discrete point-process SLX asset retained for MATLAB compatibility + and regression reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a versioned MATLAB reference asset rather + than a distinct Python execution target. + fidelity_risks: + - Version-specific SLX files are not stable Python execution targets and may diverge + from the current published model. + validation_plan: + - Keep inventoried and compare only if a published workflow is tied to this asset + specifically. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationThinningLegacy2011a + model_path: PointProcessSimulationThinning.mdl.r2011a + purpose: Legacy thinning-based point-process simulation model retained for MATLAB + compatibility/reference. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Keep as a MATLAB reference asset while the Python + port validates thinning behavior through `CIF.simulateCIFByThinning` and MATLAB-side + fixture export. + fidelity_risks: + - The legacy thinning model may encode branch behavior that is not separately exercised + by current Python CI. + validation_plan: + - Keep inventoried and add direct MATLAB-reference comparisons if a helpfile or + paper workflow depends on thinning-specific semantics. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: PointProcessSimulationCache + model_path: PointProcessSimulation.slxc + purpose: Simulink compiled cache artifact for `PointProcessSimulation`. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a MATLAB build artifact, not as a Python + execution target. + fidelity_risks: + - Cache files are version-specific and not portable across environments. + validation_plan: + - None beyond confirming the source `.slx` model remains inventoried. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: HelpPointProcessSimulationCache + model_path: helpfiles/PointProcessSimulation.slxc + purpose: Published-help compiled cache artifact for the point-process simulation + model. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a published-help artifact only. + fidelity_risks: + - Not executable from Python and tied to MATLAB's published help pipeline. + validation_plan: + - None beyond inventory coverage. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +- model_name: SimulatedNetwork2 + model_path: helpfiles/SimulatedNetwork2.mdl + purpose: Two-neuron network simulation used by `NetworkTutorial` and related connectivity + examples. + matlab_usage: required_for_example_execution + python_strategy: native_python + current_python_status: high_fidelity + deterministic_fixture_backed: true + stochastic_tolerance_backed: true + chosen_interoperability_strategy: Native Python execution through `nstat.simulators.simulate_two_neuron_network`, + with MATLAB-side `tests/python_port_fidelity/TestPythonSimulinkParity.m` serving + as the reference checker. + fidelity_risks: + - Exact spike trains still differ from Simulink because MATLAB and NumPy do not + share the same binomial random stream. + - The native port mirrors the published NetworkTutorial parameterization and one-sample-delay + semantics, but not every internal Simulink block detail is separately exposed. + validation_plan: + - Keep deterministic injected-uniform fixtures for probability traces, binary state + traces, history/ensemble terms, and eta traces in CI. + - Keep committed MATLAB gold fixtures for `prob_head` and `state_head`, and treat + seeded spike-count summaries as tolerance-based because MATLAB and NumPy random + streams are not identical. + - Keep MATLAB-side parity checks for the actual connectivity layout and deterministic + probability/state traces. + status: high_fidelity_native_python + python_equivalent: nstat.simulators.simulate_two_neuron_network + validation_strategy: deterministic injected-uniform state/probability fixtures plus + seeded summary checks + required_remediation: Broaden deterministic state-trace fixtures and document any + remaining solver-level deviations before promoting exact_native_python. +- model_name: SimulatedNetwork2Cache + model_path: helpfiles/SimulatedNetwork2.slxc + purpose: Simulink compiled cache artifact for `SimulatedNetwork2`. + matlab_usage: used_for_reference + python_strategy: reference_only + current_python_status: reference_only + chosen_interoperability_strategy: Treat as a MATLAB build artifact, not a Python + target. + fidelity_risks: + - Cache files are version-specific and cannot serve as a stable Python execution + path. + validation_plan: + - None beyond inventory coverage. + status: reference_only + python_equivalent: None + validation_strategy: inventory-only reference classification + required_remediation: Keep as inventory/reference only unless a public workflow + is shown to depend on this asset. +status_legend: +- exact_native_python +- high_fidelity_native_python +- generated_code_wrapped +- packaged_runtime +- matlab_engine_reference +- reference_only +- unsupported diff --git a/tests/test_notebook_fidelity_audit.py b/tests/test_notebook_fidelity_audit.py index 9e3cb3ef..35764d7d 100644 --- a/tests/test_notebook_fidelity_audit.py +++ b/tests/test_notebook_fidelity_audit.py @@ -25,6 +25,10 @@ def test_notebook_fidelity_audit_covers_all_parity_notes() -> None: def test_notebook_fidelity_audit_has_structural_counts() -> None: audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} for row in audit.get("items", []): + assert row["status"] in {"high_fidelity", "exact", "partial", "missing"} + assert isinstance(row["executable_in_ci"], bool) + assert "current_run_group" in row + assert isinstance(row["fixture_backed"], bool) assert "python_sections" in row assert "python_expected_figures" in row assert row["python_expected_figures"] >= 0 @@ -35,7 +39,7 @@ def test_notebook_fidelity_audit_has_structural_counts() -> None: def test_notebook_fidelity_audit_marks_upgraded_ports_as_high_fidelity() -> None: audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} - high_fidelity_topics = {row["topic"] for row in audit.get("items", []) if row["fidelity_status"] == "high_fidelity"} + high_fidelity_topics = {row["topic"] for row in audit.get("items", []) if row["status"] == "high_fidelity"} assert { "AnalysisExamples", "AnalysisExamples2", @@ -47,14 +51,14 @@ def test_notebook_fidelity_audit_marks_upgraded_ports_as_high_fidelity() -> None def test_notebook_fidelity_audit_tracks_only_known_partial_notebooks() -> None: audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} - partial_topics = {row["topic"] for row in audit.get("items", []) if row["fidelity_status"] in {"partial", "placeholder", "missing"}} + partial_topics = {row["topic"] for row in audit.get("items", []) if row["status"] in {"partial", "missing"}} assert partial_topics == set() def test_high_fidelity_notebooks_have_no_placeholder_or_tracker_only_cells() -> None: audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} for row in audit.get("items", []): - if row["fidelity_status"] not in {"high_fidelity", "exact"}: + if row["status"] not in {"high_fidelity", "exact"}: continue assert not row["python_contains_placeholders"], f"{row['topic']} still contains placeholder code" assert not row["python_contains_tracker_only_cells"], f"{row['topic']} still contains tracker-only cells" @@ -63,7 +67,7 @@ def test_high_fidelity_notebooks_have_no_placeholder_or_tracker_only_cells() -> def test_high_fidelity_notebooks_have_near_matlab_structural_counts() -> None: audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} for row in audit.get("items", []): - if row["fidelity_status"] not in {"high_fidelity", "exact"}: + if row["status"] not in {"high_fidelity", "exact"}: continue if row.get("section_delta") is None or row.get("figure_delta") is None: continue @@ -71,6 +75,13 @@ def test_high_fidelity_notebooks_have_near_matlab_structural_counts() -> None: assert abs(int(row["figure_delta"])) <= 1, f"{row['topic']} has a large MATLAB figure delta" +def test_required_notebook_ports_are_executable_in_ci() -> None: + audit = yaml.safe_load(AUDIT_PATH.read_text(encoding="utf-8")) or {} + for row in audit.get("items", []): + assert row["executable_in_ci"] is True + assert row["current_run_group"] in {"helpfile_full", "parity_core", "ci_smoke", "core", "smoke"} + + def test_notebook_fidelity_audit_matches_generator_when_matlab_repo_is_available() -> None: matlab_repo = default_matlab_repo_root(REPO_ROOT) if not matlab_repo.exists(): diff --git a/tests/test_parity_manifest.py b/tests/test_parity_manifest.py index 94e31b5f..1fb10ef5 100644 --- a/tests/test_parity_manifest.py +++ b/tests/test_parity_manifest.py @@ -2,12 +2,16 @@ from pathlib import Path +from collections import Counter + import yaml REPO_ROOT = Path(__file__).resolve().parents[1] MANIFEST_PATH = REPO_ROOT / "parity" / "manifest.yml" NOTEBOOK_AUDIT_PATH = REPO_ROOT / "parity" / "notebook_fidelity.yml" +CLASS_AUDIT_PATH = REPO_ROOT / "parity" / "class_fidelity.yml" +SIMULINK_AUDIT_PATH = REPO_ROOT / "parity" / "simulink_fidelity.yml" EXPECTED_MATLAB_PUBLIC_API = { "Analysis", @@ -118,4 +122,18 @@ def test_manifest_help_workflows_align_with_notebook_fidelity_audit() -> None: manifest_row = manifest_help_rows[topic] audit_row = audit_rows[topic] if manifest_row["status"] == "mapped": - assert audit_row["fidelity_status"] in {"high_fidelity", "exact"} + assert audit_row["status"] in {"high_fidelity", "exact"} + + +def test_manifest_fidelity_summary_matches_detailed_audits() -> None: + manifest = _load_manifest() + class_audit = yaml.safe_load(CLASS_AUDIT_PATH.read_text(encoding="utf-8")) or {} + notebook_audit = yaml.safe_load(NOTEBOOK_AUDIT_PATH.read_text(encoding="utf-8")) or {} + simulink_audit = yaml.safe_load(SIMULINK_AUDIT_PATH.read_text(encoding="utf-8")) or {} + + expected = { + "class_fidelity": dict(Counter(str(row.get("status", "")).strip() for row in class_audit.get("items", []))), + "notebook_fidelity": dict(Counter(str(row.get("status", "")).strip() for row in notebook_audit.get("items", []))), + "simulink_fidelity": dict(Counter(str(row.get("status", "")).strip() for row in simulink_audit.get("items", []))), + } + assert manifest["fidelity_summary"] == expected diff --git a/tests/test_simulink_fidelity_audit.py b/tests/test_simulink_fidelity_audit.py index 114e57af..b3a1bd4d 100644 --- a/tests/test_simulink_fidelity_audit.py +++ b/tests/test_simulink_fidelity_audit.py @@ -17,6 +17,15 @@ "unsupported", "reference_only", } +VALID_STATUSES = { + "exact_native_python", + "high_fidelity_native_python", + "generated_code_wrapped", + "packaged_runtime", + "matlab_engine_reference", + "reference_only", + "unsupported", +} REQUIRED_MODEL_PATHS = { "PointProcessSimulation.slx", "PointProcessSimulationCont.slx", @@ -40,6 +49,7 @@ def test_simulink_fidelity_audit_uses_known_strategy_values() -> None: payload = _load_audit() for row in payload["items"]: assert row["python_strategy"] in VALID_STRATEGIES + assert row["status"] in VALID_STATUSES def test_simulink_fidelity_audit_records_required_execution_fields() -> None: @@ -47,6 +57,9 @@ def test_simulink_fidelity_audit_records_required_execution_fields() -> None: for row in payload["items"]: assert row["model_path"] assert row["purpose"] + assert row["python_equivalent"] is not None + assert row["validation_strategy"] + assert row["required_remediation"] is not None assert row["chosen_interoperability_strategy"] assert row["validation_plan"] @@ -85,6 +98,6 @@ def test_simulink_fidelity_audit_has_no_partial_or_missing_behavioral_paths() -> row["model_name"] for row in payload["items"] if row["model_name"] in {"PointProcessSimulation", "SimulatedNetwork2"} - and row["current_python_status"] in {"partial", "missing", "unsupported"} + and row["status"] in {"unsupported", "reference_only"} } assert not outstanding