neurocvguard 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. neurocvguard-0.1.0/.gitignore +39 -0
  2. neurocvguard-0.1.0/LICENSE +29 -0
  3. neurocvguard-0.1.0/PKG-INFO +97 -0
  4. neurocvguard-0.1.0/README.md +65 -0
  5. neurocvguard-0.1.0/examples/01_cohort_audit.py +10 -0
  6. neurocvguard-0.1.0/examples/02_repeated_observations.py +11 -0
  7. neurocvguard-0.1.0/examples/03_site_held_out.py +11 -0
  8. neurocvguard-0.1.0/examples/04_preprocessing_provenance.py +11 -0
  9. neurocvguard-0.1.0/examples/05_explicit_feature_join.py +11 -0
  10. neurocvguard-0.1.0/pyproject.toml +85 -0
  11. neurocvguard-0.1.0/src/neurocvguard/__init__.py +199 -0
  12. neurocvguard-0.1.0/src/neurocvguard/__main__.py +6 -0
  13. neurocvguard-0.1.0/src/neurocvguard/_diagnostics.py +57 -0
  14. neurocvguard-0.1.0/src/neurocvguard/_evaluation_fits.py +186 -0
  15. neurocvguard-0.1.0/src/neurocvguard/_evaluation_inputs.py +138 -0
  16. neurocvguard-0.1.0/src/neurocvguard/_features.py +61 -0
  17. neurocvguard-0.1.0/src/neurocvguard/_inner_plans.py +50 -0
  18. neurocvguard-0.1.0/src/neurocvguard/_paths.py +12 -0
  19. neurocvguard-0.1.0/src/neurocvguard/_projection.py +554 -0
  20. neurocvguard-0.1.0/src/neurocvguard/_records.py +130 -0
  21. neurocvguard-0.1.0/src/neurocvguard/_report_tables.py +72 -0
  22. neurocvguard-0.1.0/src/neurocvguard/_report_writes.py +100 -0
  23. neurocvguard-0.1.0/src/neurocvguard/_tables.py +128 -0
  24. neurocvguard-0.1.0/src/neurocvguard/_tuning.py +97 -0
  25. neurocvguard-0.1.0/src/neurocvguard/audit.py +164 -0
  26. neurocvguard-0.1.0/src/neurocvguard/checks/__init__.py +1 -0
  27. neurocvguard-0.1.0/src/neurocvguard/checks/associations.py +267 -0
  28. neurocvguard-0.1.0/src/neurocvguard/checks/cohort.py +556 -0
  29. neurocvguard-0.1.0/src/neurocvguard/checks/partitions.py +585 -0
  30. neurocvguard-0.1.0/src/neurocvguard/checks/preprocessing.py +144 -0
  31. neurocvguard-0.1.0/src/neurocvguard/cli.py +504 -0
  32. neurocvguard-0.1.0/src/neurocvguard/comparison.py +174 -0
  33. neurocvguard-0.1.0/src/neurocvguard/config.py +244 -0
  34. neurocvguard-0.1.0/src/neurocvguard/demo.py +368 -0
  35. neurocvguard-0.1.0/src/neurocvguard/errors.py +38 -0
  36. neurocvguard-0.1.0/src/neurocvguard/evaluation.py +235 -0
  37. neurocvguard-0.1.0/src/neurocvguard/fit_boundaries.py +129 -0
  38. neurocvguard-0.1.0/src/neurocvguard/identity.py +214 -0
  39. neurocvguard-0.1.0/src/neurocvguard/io.py +499 -0
  40. neurocvguard-0.1.0/src/neurocvguard/metrics.py +147 -0
  41. neurocvguard-0.1.0/src/neurocvguard/models.py +864 -0
  42. neurocvguard-0.1.0/src/neurocvguard/provenance.py +132 -0
  43. neurocvguard-0.1.0/src/neurocvguard/py.typed +0 -0
  44. neurocvguard-0.1.0/src/neurocvguard/reporting.py +316 -0
  45. neurocvguard-0.1.0/src/neurocvguard/rules.py +503 -0
  46. neurocvguard-0.1.0/src/neurocvguard/schema.py +126 -0
  47. neurocvguard-0.1.0/src/neurocvguard/schemas/audit-report.schema.json +1336 -0
  48. neurocvguard-0.1.0/src/neurocvguard/schemas/comparison-summary.schema.json +474 -0
  49. neurocvguard-0.1.0/src/neurocvguard/schemas/config.schema.json +295 -0
  50. neurocvguard-0.1.0/src/neurocvguard/schemas/evaluation-result.schema.json +1087 -0
  51. neurocvguard-0.1.0/src/neurocvguard/schemas/preprocessing-ledger.schema.json +102 -0
  52. neurocvguard-0.1.0/src/neurocvguard/schemas/split-plan.schema.json +156 -0
  53. neurocvguard-0.1.0/src/neurocvguard/serialization.py +173 -0
  54. neurocvguard-0.1.0/src/neurocvguard/splitting.py +488 -0
  55. neurocvguard-0.1.0/src/neurocvguard/synthetic.py +172 -0
  56. neurocvguard-0.1.0/src/neurocvguard/templates/report.css +30 -0
  57. neurocvguard-0.1.0/src/neurocvguard/templates/report.html +103 -0
  58. neurocvguard-0.1.0/src/neurocvguard/workflows.py +83 -0
@@ -0,0 +1,39 @@
1
+ # Isolated local environments and build products
2
+ .venv/
3
+ .venv-install/
4
+ build/
5
+ dist/
6
+ *.egg-info/
7
+
8
+ # Python and development caches
9
+ __pycache__/
10
+ *.py[cod]
11
+ .pytest_cache/
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+ .hypothesis/
15
+ .coverage
16
+ .coverage.*
17
+ .coverage-s15/
18
+ htmlcov/
19
+ docs/_build/
20
+
21
+ # Local research inputs and outputs; synthetic fixtures remain visible
22
+ /data/private/
23
+ /private_data/
24
+ /local_outputs/
25
+ /results/
26
+ *.private.json
27
+
28
+ # Credentials and per-user IDE settings
29
+ .env
30
+ .env.*
31
+ !.env.example
32
+ *.pem
33
+ *.key
34
+ .secrets/
35
+ .vscode/
36
+ .idea/
37
+ *.code-workspace
38
+ # Local backup copies
39
+ /Backup/
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Alireza Emad
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.5
2
+ Name: neurocvguard
3
+ Version: 0.1.0
4
+ Summary: Research-only cohort audits and independently checked split plans for neuroimaging ML
5
+ Project-URL: Source, https://github.com/Alireza2177/NeuroCVguard
6
+ Author: Alireza Emad
7
+ Maintainer-email: Alireza Emad <Alireza221177@gmail.com>
8
+ License-Expression: BSD-3-Clause
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.11
11
+ Requires-Dist: jinja2>=3.1.6
12
+ Requires-Dist: jsonschema>=4.23.0
13
+ Requires-Dist: numpy>=1.26.4
14
+ Requires-Dist: pandas>=2.2.3
15
+ Requires-Dist: scikit-learn>=1.5.2
16
+ Requires-Dist: scipy>=1.13.1
17
+ Provides-Extra: dev
18
+ Requires-Dist: build; extra == 'dev'
19
+ Requires-Dist: hypothesis; extra == 'dev'
20
+ Requires-Dist: mypy; extra == 'dev'
21
+ Requires-Dist: pandas-stubs; extra == 'dev'
22
+ Requires-Dist: pytest; extra == 'dev'
23
+ Requires-Dist: pytest-cov; extra == 'dev'
24
+ Requires-Dist: ruff; extra == 'dev'
25
+ Requires-Dist: twine; extra == 'dev'
26
+ Requires-Dist: types-jsonschema; extra == 'dev'
27
+ Provides-Extra: docs
28
+ Requires-Dist: myst-parser; extra == 'docs'
29
+ Requires-Dist: sphinx; extra == 'docs'
30
+ Requires-Dist: sphinx-rtd-theme; extra == 'docs'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # NeuroCVguard
34
+
35
+ Research-only Python software for checking whether supplied cohort identities,
36
+ partitions and evaluation procedures match an intended generalization claim.
37
+ It reads local CSV/TSV/JSON, checks participant/transitive dependence and requested
38
+ domain separation, describes acquisition–target association, generates checked
39
+ splits and runs a controlled participant-level logistic baseline with optional
40
+ nested C selection. Offline HTML/JSON reports retain incomplete coverage and
41
+ limitations. No account, GPU or runtime internet connection is needed.
42
+
43
+ It does not process MRI images, provide clinical advice, authenticate upstream
44
+ preprocessing, prove causal confounding or certify a study as leakage-free.
45
+ Repeated visits alone are not leakage; inspect actual membership and objective.
46
+ Unknown upstream preprocessing remains unassessable even with a correct Pipeline.
47
+
48
+ ## Install and try
49
+
50
+ From an authorized local source checkout, create a dedicated Python environment.
51
+ Use `.venv/Scripts/python.exe` on Windows or `.venv/bin/python` on Linux/macOS
52
+ after `python -m venv .venv`. With that interpreter selected:
53
+
54
+ ```text
55
+ python -m pip install -e ".[dev,docs]"
56
+ python -m neurocvguard demo --out local_outputs/demo
57
+ ```
58
+
59
+ Open `local_outputs/demo/report.html`. Inputs are fully synthetic, not patient
60
+ data. Choose a new output path or explicitly use `--overwrite`. Read warnings
61
+ beside coverage: association suggests reviewing acquisition imbalance, while
62
+ unknown preprocessing asks for evidence rather than a passing verdict.
63
+
64
+ **Private plans/evaluations are separate from projected reports.** Default
65
+ projection is not guaranteed anonymity; inspect artifacts before sharing.
66
+ Version: 0.1.0. See the [release procedure and evidence](docs/release.md) for
67
+ publication status and the actual verified installation/platform results.
68
+
69
+ ## Documentation and development
70
+
71
+ - [Installation and troubleshooting](docs/installation.md)
72
+ - [Executable quickstart](docs/quickstart.md) and [synthetic tutorials](docs/synthetic_examples.md)
73
+ - [Inputs](docs/input_tables.md), [configuration](docs/configuration.md),
74
+ [CLI](docs/cli.md) and [Python API](docs/api.rst)
75
+ - [Objectives/warning actions](docs/objectives.md), [evaluation](docs/evaluation.md),
76
+ [report privacy](docs/reporting.md) and [limitations](docs/limitations.md)
77
+ - [Contributing/testing](CONTRIBUTING.md), [changelog](CHANGELOG.md),
78
+ [security](SECURITY.md) and [release procedure](docs/release.md)
79
+
80
+ Build the full local site with
81
+ `python -m sphinx -W --keep-going -b html docs docs/_build/html` and open
82
+ `docs/_build/html/index.html`. Run
83
+ `python -m pytest -q --strict-markers --strict-config` for the test suite.
84
+ Actual stage evidence and unrun checks are recorded under `state/handoffs/`.
85
+ Local Windows and Linux WSL2 checks and the Python 3.11 direct-dependency floor
86
+ have been exercised; see [installation evidence](docs/installation.md).
87
+ macOS and hosted CI remain unverified until their recorded runs pass.
88
+
89
+ ## License, support and citation
90
+
91
+ Copyright 2026 Alireza Emad. Released under the [BSD-3-Clause license](LICENSE).
92
+ Maintainer: Alireza Emad. For private security reports, use the approved contact in
93
+ [SECURITY.md](SECURITY.md); share only synthetic reproductions. No response-time
94
+ or long-term support commitment is claimed.
95
+ Citation metadata will be added only after verified authorship and release details;
96
+ no DOI or citation badge exists. [AI assistance](AI_ASSISTANCE.md) is recorded
97
+ honestly. Human walkthrough, external-user testing and acceptance remain pending.
@@ -0,0 +1,65 @@
1
+ # NeuroCVguard
2
+
3
+ Research-only Python software for checking whether supplied cohort identities,
4
+ partitions and evaluation procedures match an intended generalization claim.
5
+ It reads local CSV/TSV/JSON, checks participant/transitive dependence and requested
6
+ domain separation, describes acquisition–target association, generates checked
7
+ splits and runs a controlled participant-level logistic baseline with optional
8
+ nested C selection. Offline HTML/JSON reports retain incomplete coverage and
9
+ limitations. No account, GPU or runtime internet connection is needed.
10
+
11
+ It does not process MRI images, provide clinical advice, authenticate upstream
12
+ preprocessing, prove causal confounding or certify a study as leakage-free.
13
+ Repeated visits alone are not leakage; inspect actual membership and objective.
14
+ Unknown upstream preprocessing remains unassessable even with a correct Pipeline.
15
+
16
+ ## Install and try
17
+
18
+ From an authorized local source checkout, create a dedicated Python environment.
19
+ Use `.venv/Scripts/python.exe` on Windows or `.venv/bin/python` on Linux/macOS
20
+ after `python -m venv .venv`. With that interpreter selected:
21
+
22
+ ```text
23
+ python -m pip install -e ".[dev,docs]"
24
+ python -m neurocvguard demo --out local_outputs/demo
25
+ ```
26
+
27
+ Open `local_outputs/demo/report.html`. Inputs are fully synthetic, not patient
28
+ data. Choose a new output path or explicitly use `--overwrite`. Read warnings
29
+ beside coverage: association suggests reviewing acquisition imbalance, while
30
+ unknown preprocessing asks for evidence rather than a passing verdict.
31
+
32
+ **Private plans/evaluations are separate from projected reports.** Default
33
+ projection is not guaranteed anonymity; inspect artifacts before sharing.
34
+ Version: 0.1.0. See the [release procedure and evidence](docs/release.md) for
35
+ publication status and the actual verified installation/platform results.
36
+
37
+ ## Documentation and development
38
+
39
+ - [Installation and troubleshooting](docs/installation.md)
40
+ - [Executable quickstart](docs/quickstart.md) and [synthetic tutorials](docs/synthetic_examples.md)
41
+ - [Inputs](docs/input_tables.md), [configuration](docs/configuration.md),
42
+ [CLI](docs/cli.md) and [Python API](docs/api.rst)
43
+ - [Objectives/warning actions](docs/objectives.md), [evaluation](docs/evaluation.md),
44
+ [report privacy](docs/reporting.md) and [limitations](docs/limitations.md)
45
+ - [Contributing/testing](CONTRIBUTING.md), [changelog](CHANGELOG.md),
46
+ [security](SECURITY.md) and [release procedure](docs/release.md)
47
+
48
+ Build the full local site with
49
+ `python -m sphinx -W --keep-going -b html docs docs/_build/html` and open
50
+ `docs/_build/html/index.html`. Run
51
+ `python -m pytest -q --strict-markers --strict-config` for the test suite.
52
+ Actual stage evidence and unrun checks are recorded under `state/handoffs/`.
53
+ Local Windows and Linux WSL2 checks and the Python 3.11 direct-dependency floor
54
+ have been exercised; see [installation evidence](docs/installation.md).
55
+ macOS and hosted CI remain unverified until their recorded runs pass.
56
+
57
+ ## License, support and citation
58
+
59
+ Copyright 2026 Alireza Emad. Released under the [BSD-3-Clause license](LICENSE).
60
+ Maintainer: Alireza Emad. For private security reports, use the approved contact in
61
+ [SECURITY.md](SECURITY.md); share only synthetic reproductions. No response-time
62
+ or long-term support commitment is claimed.
63
+ Citation metadata will be added only after verified authorship and release details;
64
+ no DOI or citation badge exists. [AI assistance](AI_ASSISTANCE.md) is recorded
65
+ honestly. Human walkthrough, external-user testing and acceptance remain pending.
@@ -0,0 +1,10 @@
1
+ """Map generated cohort TSV, audit and create participant-disjoint CV; open report.html.
2
+
3
+ Run: python examples/01_cohort_audit.py --out local_outputs/example-01
4
+ All inputs are created locally by the installed package; no patient data.
5
+ """
6
+
7
+ from neurocvguard.demo import example_main
8
+
9
+ if __name__ == "__main__":
10
+ raise SystemExit(example_main(1))
@@ -0,0 +1,11 @@
1
+ """Compare row-random diagnostic and participant-disjoint synthetic evaluations.
2
+
3
+ Run: python examples/02_repeated_observations.py --out local_outputs/example-02
4
+ The row-random score is invalid for unseen-participant generalization.
5
+ No universal ordering or causal leakage amount is claimed.
6
+ """
7
+
8
+ from neurocvguard.demo import example_main
9
+
10
+ if __name__ == "__main__":
11
+ raise SystemExit(example_main(2))
@@ -0,0 +1,11 @@
1
+ """Hold sites out with explicit class-associated domains; retain undefined fold metrics.
2
+
3
+ Run: python examples/03_site_held_out.py --out local_outputs/example-03
4
+ Association=1 is an explicit pedagogical mechanism, not a selected favorable seed.
5
+ Site/participant objectives differ; these tabular data are entirely fictitious.
6
+ """
7
+
8
+ from neurocvguard.demo import example_main
9
+
10
+ if __name__ == "__main__":
11
+ raise SystemExit(example_main(3))
@@ -0,0 +1,11 @@
1
+ """Compare unknown preprocessing with a fictitious global-PCA declaration.
2
+
3
+ Run: python examples/04_preprocessing_provenance.py --out local_outputs/example-04
4
+ Inspect report.html and unknown.report.html. No PCA actually runs; a declaration
5
+ cannot authenticate historical execution, and a Pipeline cannot repair it.
6
+ """
7
+
8
+ from neurocvguard.demo import example_main
9
+
10
+ if __name__ == "__main__":
11
+ raise SystemExit(example_main(4))
@@ -0,0 +1,11 @@
1
+ """Join reversed synthetic feature rows by scan_key with explicit role/feature names.
2
+
3
+ Run: python examples/05_explicit_feature_join.py --out local_outputs/example-05
4
+ The installed workflow writes local TSVs and uses load_cohort's keyed join.
5
+ No hidden notebook state, external dataset or row-order alignment is used.
6
+ """
7
+
8
+ from neurocvguard.demo import example_main
9
+
10
+ if __name__ == "__main__":
11
+ raise SystemExit(example_main(5))
@@ -0,0 +1,85 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "neurocvguard"
7
+ dynamic = ["version"]
8
+ description = "Research-only cohort audits and independently checked split plans for neuroimaging ML"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ authors = [{name = "Alireza Emad"}]
12
+ maintainers = [{name = "Alireza Emad", email = "Alireza221177@gmail.com"}]
13
+ license = "BSD-3-Clause"
14
+ license-files = ["LICENSE"]
15
+ dependencies = ["numpy>=1.26.4", "pandas>=2.2.3", "scipy>=1.13.1", "scikit-learn>=1.5.2", "Jinja2>=3.1.6", "jsonschema>=4.23.0"]
16
+
17
+ [project.urls]
18
+ Source = "https://github.com/Alireza2177/NeuroCVguard"
19
+
20
+ [project.optional-dependencies]
21
+ dev = ["pytest", "pytest-cov", "hypothesis", "ruff", "mypy", "build", "twine", "pandas-stubs", "types-jsonschema"]
22
+ docs = ["sphinx", "myst-parser", "sphinx-rtd-theme"]
23
+
24
+ [project.scripts]
25
+ neurocvguard = "neurocvguard.__main__:main"
26
+
27
+ [tool.hatch.version]
28
+ path = "src/neurocvguard/__init__.py"
29
+
30
+ [tool.hatch.build.targets.wheel]
31
+ packages = ["src/neurocvguard"]
32
+
33
+ [tool.hatch.build.targets.wheel.force-include]
34
+ "examples" = "neurocvguard/examples"
35
+
36
+ [tool.hatch.build.targets.sdist]
37
+ include = ["/src/neurocvguard", "/examples", "/pyproject.toml", "/README.md", "/LICENSE"]
38
+
39
+ [tool.pytest.ini_options]
40
+ testpaths = ["tests"]
41
+ addopts = "--strict-markers --strict-config"
42
+
43
+ [tool.coverage.run]
44
+ branch = true
45
+ source = ["neurocvguard"]
46
+ # CLI/tutorial tests launch real Python processes. Measure those paths as well.
47
+ patch = ["subprocess"]
48
+
49
+ [tool.ruff]
50
+ target-version = "py311"
51
+ line-length = 100
52
+ # The unchanged master builder predates S00. The repaired foundation validator
53
+ # and all new stage helpers now receive the ordinary project lint/format checks.
54
+ extend-exclude = ["tools/build_master.py", ".venv-install"]
55
+
56
+ [tool.ruff.lint]
57
+ select = ["E", "F", "I", "UP", "B"]
58
+
59
+ [tool.mypy]
60
+ python_version = "3.11"
61
+ strict = true
62
+
63
+ # sklearn does not ship typing metadata. Restrict this exception to its import
64
+ # boundary; NeuroCVguard's participant adapters and public functions remain strict.
65
+ [[tool.mypy.overrides]]
66
+ module = ["sklearn", "sklearn.*"]
67
+ ignore_missing_imports = true
68
+
69
+ # SciPy's installed contingency module has no typing metadata. Keep this
70
+ # exception at the external boundary; validate finite outputs and type our adapter.
71
+ [[tool.mypy.overrides]]
72
+ module = ["scipy.stats.contingency"]
73
+ ignore_missing_imports = true
74
+
75
+ [tool.neurocvguard.release]
76
+ proposed-license = "BSD-3-Clause"
77
+ license-status = "OWNER_CONFIRMED"
78
+ copyright-owner = "Alireza Emad"
79
+ maintainer = "Alireza Emad"
80
+ security-contact = "Alireza221177@gmail.com"
81
+ repository-url = "https://github.com/Alireza2177/NeuroCVguard"
82
+ # Selected project name; registry/publisher verification is release evidence.
83
+ package-namespace = "neurocvguard"
84
+ # Publication authorization is recorded in state/PROJECT_STATUS.json, outside
85
+ # immutable distribution metadata, and must name the reviewed artifacts.
@@ -0,0 +1,199 @@
1
+ """Research-only local cohort/split checks, with lazy public API imports."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ import pandas as pd
10
+
11
+ from neurocvguard.config import AuditConfig
12
+ from neurocvguard.models import (
13
+ AuditReport,
14
+ Cohort,
15
+ ComparisonResult,
16
+ EvaluationResult,
17
+ SplitPlan,
18
+ )
19
+
20
+ __version__ = "0.1.0"
21
+
22
+
23
+ def compare_designs(results: dict[str, EvaluationResult]) -> ComparisonResult:
24
+ """Compare private records descriptively; see neurocvguard.comparison.compare_designs."""
25
+ from neurocvguard.comparison import compare_designs as compare
26
+
27
+ return compare(results)
28
+
29
+
30
+ def evaluate_baseline(cohort: Cohort, plan: SplitPlan, *, config: AuditConfig) -> EvaluationResult:
31
+ """Run classification with optional nested C selection; see evaluation.evaluate_baseline."""
32
+ from neurocvguard.evaluation import evaluate_baseline as evaluate
33
+
34
+ return evaluate(cohort, plan, config=config)
35
+
36
+
37
+ def load_config(path: str | Path) -> AuditConfig:
38
+ """Read strict local JSON settings; see neurocvguard.config.load_config."""
39
+ from neurocvguard.config import load_config as load
40
+
41
+ return load(path)
42
+
43
+
44
+ def load_cohort(
45
+ metadata: str | Path | pd.DataFrame,
46
+ *,
47
+ config: AuditConfig,
48
+ features: str | Path | pd.DataFrame | None = None,
49
+ ) -> Cohort:
50
+ """Load strict local tables; see neurocvguard.io.load_cohort for the input contract."""
51
+ from neurocvguard.io import load_cohort as load
52
+
53
+ return load(metadata, config=config, features=features)
54
+
55
+
56
+ def audit_cohort(
57
+ cohort: Cohort,
58
+ *,
59
+ config: AuditConfig,
60
+ ledger: dict[str, object] | None = None,
61
+ ) -> AuditReport:
62
+ """Audit constructed cohort data and declarations without fitting or writing.
63
+
64
+ Parameters
65
+ ----------
66
+ cohort : Cohort
67
+ Explicitly keyed in-memory metadata and optional aligned features.
68
+ config : AuditConfig
69
+ Matching roles and diagnostic settings.
70
+ ledger : dict or None, optional
71
+ Strict user-declaration contract; it cannot authenticate historical fitting.
72
+
73
+ Returns
74
+ -------
75
+ AuditReport
76
+ Scoped findings and persistent upstream limitations; see neurocvguard.audit.
77
+
78
+ Examples
79
+ --------
80
+ ``audit_cohort(cohort, config=config).to_dict()`` returns the public projection.
81
+ """
82
+ from neurocvguard.audit import audit_cohort as audit
83
+
84
+ return audit(cohort, config=config, ledger=ledger)
85
+
86
+
87
+ def make_splits(cohort: Cohort, *, config: AuditConfig) -> SplitPlan:
88
+ """Generate and independently audit deterministic outer assignments.
89
+
90
+ Parameters
91
+ ----------
92
+ cohort : Cohort
93
+ Constructed keyed cohort with constant targets and complete protected fields.
94
+ config : AuditConfig
95
+ Explicit supported objective, splitter settings and seed.
96
+
97
+ Returns
98
+ -------
99
+ SplitPlan
100
+ Sensitive operational plan with separate in-memory generation_report.
101
+
102
+ Raises
103
+ ------
104
+ PlanningError, UnsupportedDesignError, ConfigurationError, InputValidationError
105
+ Unsupported inputs, infeasible design or failed independent audit.
106
+
107
+ Examples
108
+ --------
109
+ ``plan = make_splits(cohort, config=config)`` writes no files and fits no model.
110
+ """
111
+ from neurocvguard.splitting import make_splits as make
112
+
113
+ return make(cohort, config=config)
114
+
115
+
116
+ def load_split_plan(
117
+ source: str | Path | dict[str, object],
118
+ *,
119
+ cohort: Cohort,
120
+ config: AuditConfig,
121
+ ) -> SplitPlan:
122
+ """Load and bind supplied assignments; see neurocvguard.io.load_split_plan.
123
+
124
+ Parameters
125
+ ----------
126
+ source : str, Path or dict
127
+ Local JSON/TSV path or schema-shaped plan dictionary.
128
+ cohort : Cohort
129
+ Already validated, explicitly keyed in-memory data.
130
+ config : AuditConfig
131
+ Matching objective/roles and input limits.
132
+
133
+ Returns
134
+ -------
135
+ SplitPlan
136
+ Bound sensitive operational plan, not a design approval.
137
+
138
+ Raises
139
+ ------
140
+ InputValidationError, ConfigurationError, SplitValidationError
141
+ Invalid source structure, identities, mapping, objective or digest.
142
+
143
+ Examples
144
+ --------
145
+ ``load_split_plan("plan.json", cohort=cohort, config=config)``
146
+ """
147
+ from neurocvguard.io import load_split_plan as load
148
+
149
+ return load(source, cohort=cohort, config=config)
150
+
151
+
152
+ def audit_splits(cohort: Cohort, plan: SplitPlan, *, config: AuditConfig) -> AuditReport:
153
+ """Audit supplied partitions; see neurocvguard.audit.audit_splits.
154
+
155
+ Parameters
156
+ ----------
157
+ cohort : Cohort
158
+ Validated in-memory input.
159
+ plan : SplitPlan
160
+ Supplied structural plan record.
161
+ config : AuditConfig
162
+ Matching roles/objective; no diagnostic relaxation of invariants.
163
+
164
+ Returns
165
+ -------
166
+ AuditReport
167
+ Scoped checks and separate objective/complete-CV eligibility flags.
168
+
169
+ Raises
170
+ ------
171
+ InputValidationError, ConfigurationError, SplitValidationError
172
+ Corrupt identities or incompatible objective, mapping or digest.
173
+
174
+ Examples
175
+ --------
176
+ ``audit_splits(cohort, plan, config=config).to_dict()`` is privacy-projected.
177
+ """
178
+ from neurocvguard.audit import audit_splits as audit
179
+
180
+ return audit(cohort, plan, config=config)
181
+
182
+
183
+ def write_report(
184
+ result: AuditReport | EvaluationResult | ComparisonResult,
185
+ *,
186
+ output_dir: str | Path,
187
+ sensitive_details: bool = False,
188
+ overwrite: bool = False,
189
+ ) -> dict[str, Path]:
190
+ """Write local projected JSON/HTML; see neurocvguard.reporting.write_report.
191
+
192
+ Safe defaults omit private evidence and refuse overwriting. Sensitive output
193
+ requires an explicit argument; no operational evaluation or split file is written.
194
+ """
195
+ from neurocvguard.reporting import write_report as write
196
+
197
+ return write(
198
+ result, output_dir=output_dir, sensitive_details=sensitive_details, overwrite=overwrite
199
+ )
@@ -0,0 +1,6 @@
1
+ """Module and installed console entry points share the same CLI."""
2
+
3
+ from neurocvguard.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ raise SystemExit(main())
@@ -0,0 +1,57 @@
1
+ """Narrow evaluation exception; audit findings and objective validity never change."""
2
+
3
+ from neurocvguard.config import AuditConfig, Objective
4
+ from neurocvguard.errors import UnsupportedDesignError
5
+ from neurocvguard.models import AuditReport, CheckStatus
6
+
7
+ DIAGNOSTIC_LIMITATION = (
8
+ "Diagnostic only; valid_for_objective=false. Do not report as evidence for "
9
+ "unseen-participant generalization. Participant-level aggregation does not remove "
10
+ "the training leakage already present. Every observation has one held-out prediction; "
11
+ "all held-out observation probabilities are averaged once per participant."
12
+ )
13
+
14
+
15
+ def validate_diagnostic_request(config: AuditConfig) -> None:
16
+ if config.evaluation.diagnostic_allow_subject_overlap and (
17
+ config.study.objective != Objective.UNSEEN_PARTICIPANT or config.columns.independence
18
+ ):
19
+ raise UnsupportedDesignError(
20
+ "Diagnostic overlap requires unseen_participant and no extra independence columns. "
21
+ "It cannot waive family, site or phase constraints."
22
+ )
23
+
24
+
25
+ def evaluation_eligibility(audit: AuditReport, config: AuditConfig) -> bool:
26
+ """Return whether the narrow outer-overlap exception was actually necessary.
27
+
28
+ Inner participant/component overlap is never waived, including during tuning.
29
+ Without extra dependence columns, component overlap is participant overlap.
30
+ All original audit failures remain in the retained report.
31
+ """
32
+ validate_diagnostic_request(config)
33
+ summary = next(c for c in audit.checks if c.scope.get("field") == "split_summary")
34
+ if summary.evidence.get("evaluation_permitted") is True:
35
+ return False
36
+ required = {f"NCG-SPLIT-{n:03d}" for n in (1, 2, 3, 4, 5, 7, 8, 9, 10, 11)}
37
+ failures = [
38
+ c
39
+ for c in audit.checks
40
+ if c.rule_id in required and c.status in (CheckStatus.FAIL, CheckStatus.NOT_ASSESSABLE)
41
+ ]
42
+ if (
43
+ config.evaluation.diagnostic_allow_subject_overlap
44
+ and summary.evidence.get("complete_cv") is True
45
+ and failures
46
+ and all(
47
+ c.status == CheckStatus.FAIL
48
+ and c.rule_id in {"NCG-SPLIT-002", "NCG-SPLIT-003"}
49
+ and c.scope.get("inner_fold_id") is None
50
+ for c in failures
51
+ )
52
+ ):
53
+ return True
54
+ raise UnsupportedDesignError(
55
+ "Evaluation requires complete, protected and objective-valid partitions with all "
56
+ "training classes. Diagnostic permission cannot waive other violations; run audit."
57
+ )