iints-sdk-python35 0.1.22__tar.gz → 1.0.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.
- iints_sdk_python35-1.0.0/PKG-INFO +154 -0
- iints_sdk_python35-1.0.0/README.md +103 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/pyproject.toml +5 -2
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/cli/cli.py +63 -9
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/mdmp/__init__.py +18 -1
- iints_sdk_python35-1.0.0/src/iints/mdmp/backend.py +185 -0
- iints_sdk_python35-1.0.0/src/iints_sdk_python35.egg-info/PKG-INFO +154 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints_sdk_python35.egg-info/SOURCES.txt +1 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints_sdk_python35.egg-info/requires.txt +3 -0
- iints_sdk_python35-0.1.22/PKG-INFO +0 -226
- iints_sdk_python35-0.1.22/README.md +0 -177
- iints_sdk_python35-0.1.22/src/iints_sdk_python35.egg-info/PKG-INFO +0 -226
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/LICENSE +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/setup.cfg +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/algorithm_xray.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/baseline.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/clinical_benchmark.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/clinical_metrics.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/clinical_tir_analyzer.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/diabetes_metrics.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/edge_efficiency.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/edge_performance_monitor.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/explainability.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/explainable_ai.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/hardware_benchmark.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/metrics.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/population_report.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/reporting.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/safety_index.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/sensor_filtering.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/analysis/validator.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/api/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/api/base_algorithm.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/api/registry.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/api/template_algorithm.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/assets/iints_logo.png +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/cli/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/battle_runner.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/correction_bolus.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/discovery.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/fixed_basal_bolus.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/hybrid_algorithm.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/lstm_algorithm.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/mock_algorithms.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/pid_controller.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/algorithms/standard_pump_algo.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/device.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/device_manager.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/devices/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/devices/models.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/patient/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/patient/bergman_model.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/patient/models.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/patient/patient_factory.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/patient/profile.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/safety/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/safety/config.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/safety/input_validator.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/safety/supervisor.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/simulation/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/simulation/scenario_parser.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/simulator.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/core/supervisor.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/adapter.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/column_mapper.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/contracts.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/datasets.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/demo/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/demo/demo_cgm.csv +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/guardians.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/importer.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/ingestor.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/mdmp_visualizer.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/nightscout.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/quality_checker.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/registry.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/runner.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/synthetic_mirror.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/tidepool.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/universal_parser.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_baseline.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_hyper_challenge.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_hypo_prone.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_midnight.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_pizza.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/clinic_safe_stress_meal.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/default_patient.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/data/virtual_patients/patient_559_config.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/emulation/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/emulation/legacy_base.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/emulation/medtronic_780g.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/emulation/omnipod_5.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/emulation/tandem_controliq.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/highlevel.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/learning/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/learning/autonomous_optimizer.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/learning/learning_system.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/metrics.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/population/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/population/generator.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/population/runner.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/evidence_sources.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/forecast_calibration_profiles.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/golden_benchmark.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/presets.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/safety_contract_default.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/presets/validation_profiles.yaml +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/audit.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/calibration_gate.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/config.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/dataset.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/evaluation.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/losses.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/metrics.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/model_registry.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/research/predictor.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/scenarios/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/scenarios/generator.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/default_algorithm.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/scenarios/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/scenarios/chaos_insulin_stacking.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/scenarios/chaos_runaway_ai.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/scenarios/example_scenario.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/templates/scenarios/exercise_stress.json +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/utils/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/utils/plotting.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/utils/run_io.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/golden.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/replay.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/run_validation.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/safety_contract.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/validation/schemas.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/visualization/__init__.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/visualization/cockpit.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints/visualization/uncertainty_cloud.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints_sdk_python35.egg-info/dependency_links.txt +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints_sdk_python35.egg-info/entry_points.txt +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/src/iints_sdk_python35.egg-info/top_level.txt +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/tests/test_bergman.py +0 -0
- {iints_sdk_python35-0.1.22 → iints_sdk_python35-1.0.0}/tests/test_population.py +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iints-sdk-python35
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A pre-clinical Edge-AI SDK for diabetes management validation.
|
|
5
|
+
Author-email: Rune Bobbaers <rune.bobbaers@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/python35/IINTS-SDK
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: fpdf2>=2.8.0
|
|
19
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
20
|
+
Requires-Dist: numpy>=1.24.0
|
|
21
|
+
Requires-Dist: openpyxl>=3.0.0
|
|
22
|
+
Requires-Dist: pandas>=2.0.0
|
|
23
|
+
Requires-Dist: pillow>=12.1.1
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Requires-Dist: PyYAML
|
|
26
|
+
Requires-Dist: rich>=12.0.0
|
|
27
|
+
Requires-Dist: scipy>=1.9.0
|
|
28
|
+
Requires-Dist: seaborn>=0.11.0
|
|
29
|
+
Requires-Dist: typer[all]
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy; extra == "dev"
|
|
35
|
+
Requires-Dist: pandas-stubs; extra == "dev"
|
|
36
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
37
|
+
Requires-Dist: types-psutil; extra == "dev"
|
|
38
|
+
Provides-Extra: torch
|
|
39
|
+
Requires-Dist: torch>=1.9.0; extra == "torch"
|
|
40
|
+
Provides-Extra: nightscout
|
|
41
|
+
Requires-Dist: py-nightscout; extra == "nightscout"
|
|
42
|
+
Provides-Extra: research
|
|
43
|
+
Requires-Dist: torch>=2.0.0; extra == "research"
|
|
44
|
+
Requires-Dist: pyarrow>=12.0.0; extra == "research"
|
|
45
|
+
Requires-Dist: h5py>=3.10.0; extra == "research"
|
|
46
|
+
Requires-Dist: onnx>=1.16.0; extra == "research"
|
|
47
|
+
Requires-Dist: onnxscript>=0.1.0; extra == "research"
|
|
48
|
+
Provides-Extra: mdmp
|
|
49
|
+
Requires-Dist: mdmp-protocol>=0.2.1; extra == "mdmp"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# IINTS-AF SDK
|
|
53
|
+
[](https://badge.fury.io/py/iints-sdk-python35)
|
|
54
|
+
[](https://github.com/python35/IINTS-SDK/actions/workflows/python-package.yml)
|
|
55
|
+
[](https://python35.github.io/IINTS-Site/index.html)
|
|
56
|
+
|
|
57
|
+
IINTS-AF is a safety-first SDK for insulin-algorithm research.
|
|
58
|
+
It lets you simulate, validate, and report results with reproducible artifacts.
|
|
59
|
+
|
|
60
|
+
Docs (GitHub Pages): [python35.github.io/IINTS-SDK](https://python35.github.io/IINTS-SDK/)
|
|
61
|
+
|
|
62
|
+
## What You Can Do
|
|
63
|
+
- Run virtual patient simulations.
|
|
64
|
+
- Test algorithm safety gates (deterministic supervisor).
|
|
65
|
+
- Add optional AI glucose forecasting.
|
|
66
|
+
- Validate datasets before training/evaluation.
|
|
67
|
+
- Generate audit-ready CSV/JSON/PDF/HTML outputs.
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
```bash
|
|
71
|
+
python3 -m venv .venv
|
|
72
|
+
source .venv/bin/activate
|
|
73
|
+
python -m pip install -U pip
|
|
74
|
+
pip install iints-sdk-python35
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
iints doctor --smoke-run
|
|
79
|
+
iints quickstart --project-name iints_quickstart
|
|
80
|
+
cd iints_quickstart
|
|
81
|
+
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## MDMP (Short)
|
|
85
|
+
MDMP is the data-quality protocol used by IINTS.
|
|
86
|
+
|
|
87
|
+
- `Contract`: defines expected columns, types, units, and bounds.
|
|
88
|
+
- `Validation`: checks a dataset against the contract.
|
|
89
|
+
- `Fingerprint + Grade`: writes deterministic hashes and a grade (`draft`, `research_grade`, `clinical_grade`).
|
|
90
|
+
- `Visualizer`: builds a single-file HTML report for audits.
|
|
91
|
+
|
|
92
|
+
Use the dedicated namespace:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
iints mdmp template --output-path mdmp_contract.yaml
|
|
96
|
+
iints mdmp validate mdmp_contract.yaml data/my_cgm.csv --output-json results/mdmp_report.json
|
|
97
|
+
iints mdmp visualizer results/mdmp_report.json --output-html results/mdmp_dashboard.html
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Use standalone MDMP backend (optional):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
export IINTS_MDMP_BACKEND=mdmp_core
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Staleness / lineage checks (standalone MDMP CLI):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
mdmp fingerprint-record data/my_cgm.csv --output-json results/fingerprint.json --expires-days 365
|
|
110
|
+
mdmp fingerprint-check results/fingerprint.json data/my_cgm.csv
|
|
111
|
+
mdmp lineage-card-refresh results/mdmp_model_card.yaml
|
|
112
|
+
mdmp registry init --registry registry/mdmp_registry.json
|
|
113
|
+
mdmp registry push --registry registry/mdmp_registry.json --report results/mdmp_report.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Dual Repo Workflow
|
|
117
|
+
- SDK repo: `python35/IINTS-SDK`
|
|
118
|
+
- MDMP repo: `python35/MDMP`
|
|
119
|
+
|
|
120
|
+
Local helper scripts:
|
|
121
|
+
- `tools/local/dual_repo_status.sh`
|
|
122
|
+
- `tools/local/dual_repo_commit_push.sh`
|
|
123
|
+
|
|
124
|
+
Full process: `docs/DUAL_REPO_WORKFLOW.md`
|
|
125
|
+
|
|
126
|
+
MDMP sync CI gate:
|
|
127
|
+
- `.github/workflows/mdmp-sync.yml`
|
|
128
|
+
- Pulls the public `python35/MDMP` repo directly.
|
|
129
|
+
- Auto dependency updates for MDMP are handled via Dependabot (`.github/dependabot.yml`).
|
|
130
|
+
|
|
131
|
+
## Typical Workflow
|
|
132
|
+
1. Prepare or import data.
|
|
133
|
+
2. Validate data with MDMP.
|
|
134
|
+
3. Run simulation or forecast evaluation.
|
|
135
|
+
4. Review report artifacts and metrics.
|
|
136
|
+
|
|
137
|
+
## Key Commands
|
|
138
|
+
```bash
|
|
139
|
+
iints run-full --algo algorithms/example_algorithm.py --scenario-path scenarios/clinic_safe_baseline.json --output-dir results/run_full
|
|
140
|
+
iints scorecard --algo algorithms/example_algorithm.py --profile research_default --output-dir results/scorecard
|
|
141
|
+
iints study-ready --algo algorithms/example_algorithm.py --output-dir results/study_ready
|
|
142
|
+
iints sources --output-json results/source_manifest.json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Documentation
|
|
146
|
+
- Docs site: [python35.github.io/IINTS-SDK](https://python35.github.io/IINTS-SDK/)
|
|
147
|
+
- Plain guide: [docs/PLAIN_LANGUAGE_GUIDE.md](https://github.com/python35/IINTS-SDK/blob/main/docs/PLAIN_LANGUAGE_GUIDE.md)
|
|
148
|
+
- Comprehensive guide: [docs/COMPREHENSIVE_GUIDE.md](https://github.com/python35/IINTS-SDK/blob/main/docs/COMPREHENSIVE_GUIDE.md)
|
|
149
|
+
- MDMP draft: [docs/MDMP.md](https://github.com/python35/IINTS-SDK/blob/main/docs/MDMP.md)
|
|
150
|
+
- Demos: [examples/demos](https://github.com/python35/IINTS-SDK/tree/main/examples/demos)
|
|
151
|
+
- Notebooks: [examples/notebooks](https://github.com/python35/IINTS-SDK/tree/main/examples/notebooks)
|
|
152
|
+
|
|
153
|
+
## Safety Notice
|
|
154
|
+
For research use only. Not a medical device. No clinical dosing advice.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# IINTS-AF SDK
|
|
2
|
+
[](https://badge.fury.io/py/iints-sdk-python35)
|
|
3
|
+
[](https://github.com/python35/IINTS-SDK/actions/workflows/python-package.yml)
|
|
4
|
+
[](https://python35.github.io/IINTS-Site/index.html)
|
|
5
|
+
|
|
6
|
+
IINTS-AF is a safety-first SDK for insulin-algorithm research.
|
|
7
|
+
It lets you simulate, validate, and report results with reproducible artifacts.
|
|
8
|
+
|
|
9
|
+
Docs (GitHub Pages): [python35.github.io/IINTS-SDK](https://python35.github.io/IINTS-SDK/)
|
|
10
|
+
|
|
11
|
+
## What You Can Do
|
|
12
|
+
- Run virtual patient simulations.
|
|
13
|
+
- Test algorithm safety gates (deterministic supervisor).
|
|
14
|
+
- Add optional AI glucose forecasting.
|
|
15
|
+
- Validate datasets before training/evaluation.
|
|
16
|
+
- Generate audit-ready CSV/JSON/PDF/HTML outputs.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
```bash
|
|
20
|
+
python3 -m venv .venv
|
|
21
|
+
source .venv/bin/activate
|
|
22
|
+
python -m pip install -U pip
|
|
23
|
+
pip install iints-sdk-python35
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
iints doctor --smoke-run
|
|
28
|
+
iints quickstart --project-name iints_quickstart
|
|
29
|
+
cd iints_quickstart
|
|
30
|
+
iints presets run --name baseline_t1d --algo algorithms/example_algorithm.py
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## MDMP (Short)
|
|
34
|
+
MDMP is the data-quality protocol used by IINTS.
|
|
35
|
+
|
|
36
|
+
- `Contract`: defines expected columns, types, units, and bounds.
|
|
37
|
+
- `Validation`: checks a dataset against the contract.
|
|
38
|
+
- `Fingerprint + Grade`: writes deterministic hashes and a grade (`draft`, `research_grade`, `clinical_grade`).
|
|
39
|
+
- `Visualizer`: builds a single-file HTML report for audits.
|
|
40
|
+
|
|
41
|
+
Use the dedicated namespace:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
iints mdmp template --output-path mdmp_contract.yaml
|
|
45
|
+
iints mdmp validate mdmp_contract.yaml data/my_cgm.csv --output-json results/mdmp_report.json
|
|
46
|
+
iints mdmp visualizer results/mdmp_report.json --output-html results/mdmp_dashboard.html
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use standalone MDMP backend (optional):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
export IINTS_MDMP_BACKEND=mdmp_core
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Staleness / lineage checks (standalone MDMP CLI):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
mdmp fingerprint-record data/my_cgm.csv --output-json results/fingerprint.json --expires-days 365
|
|
59
|
+
mdmp fingerprint-check results/fingerprint.json data/my_cgm.csv
|
|
60
|
+
mdmp lineage-card-refresh results/mdmp_model_card.yaml
|
|
61
|
+
mdmp registry init --registry registry/mdmp_registry.json
|
|
62
|
+
mdmp registry push --registry registry/mdmp_registry.json --report results/mdmp_report.json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Dual Repo Workflow
|
|
66
|
+
- SDK repo: `python35/IINTS-SDK`
|
|
67
|
+
- MDMP repo: `python35/MDMP`
|
|
68
|
+
|
|
69
|
+
Local helper scripts:
|
|
70
|
+
- `tools/local/dual_repo_status.sh`
|
|
71
|
+
- `tools/local/dual_repo_commit_push.sh`
|
|
72
|
+
|
|
73
|
+
Full process: `docs/DUAL_REPO_WORKFLOW.md`
|
|
74
|
+
|
|
75
|
+
MDMP sync CI gate:
|
|
76
|
+
- `.github/workflows/mdmp-sync.yml`
|
|
77
|
+
- Pulls the public `python35/MDMP` repo directly.
|
|
78
|
+
- Auto dependency updates for MDMP are handled via Dependabot (`.github/dependabot.yml`).
|
|
79
|
+
|
|
80
|
+
## Typical Workflow
|
|
81
|
+
1. Prepare or import data.
|
|
82
|
+
2. Validate data with MDMP.
|
|
83
|
+
3. Run simulation or forecast evaluation.
|
|
84
|
+
4. Review report artifacts and metrics.
|
|
85
|
+
|
|
86
|
+
## Key Commands
|
|
87
|
+
```bash
|
|
88
|
+
iints run-full --algo algorithms/example_algorithm.py --scenario-path scenarios/clinic_safe_baseline.json --output-dir results/run_full
|
|
89
|
+
iints scorecard --algo algorithms/example_algorithm.py --profile research_default --output-dir results/scorecard
|
|
90
|
+
iints study-ready --algo algorithms/example_algorithm.py --output-dir results/study_ready
|
|
91
|
+
iints sources --output-json results/source_manifest.json
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
- Docs site: [python35.github.io/IINTS-SDK](https://python35.github.io/IINTS-SDK/)
|
|
96
|
+
- Plain guide: [docs/PLAIN_LANGUAGE_GUIDE.md](https://github.com/python35/IINTS-SDK/blob/main/docs/PLAIN_LANGUAGE_GUIDE.md)
|
|
97
|
+
- Comprehensive guide: [docs/COMPREHENSIVE_GUIDE.md](https://github.com/python35/IINTS-SDK/blob/main/docs/COMPREHENSIVE_GUIDE.md)
|
|
98
|
+
- MDMP draft: [docs/MDMP.md](https://github.com/python35/IINTS-SDK/blob/main/docs/MDMP.md)
|
|
99
|
+
- Demos: [examples/demos](https://github.com/python35/IINTS-SDK/tree/main/examples/demos)
|
|
100
|
+
- Notebooks: [examples/notebooks](https://github.com/python35/IINTS-SDK/tree/main/examples/notebooks)
|
|
101
|
+
|
|
102
|
+
## Safety Notice
|
|
103
|
+
For research use only. Not a medical device. No clinical dosing advice.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iints-sdk-python35"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "1.0.0"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Rune Bobbaers", email="rune.bobbaers@gmail.com" },
|
|
10
10
|
]
|
|
@@ -19,7 +19,7 @@ classifiers = [
|
|
|
19
19
|
"Programming Language :: Python :: 3.13",
|
|
20
20
|
"License :: OSI Approved :: MIT License",
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
|
-
"Development Status ::
|
|
22
|
+
"Development Status :: 5 - Production/Stable",
|
|
23
23
|
]
|
|
24
24
|
dependencies = [
|
|
25
25
|
"fpdf2>=2.8.0",
|
|
@@ -59,6 +59,9 @@ research = [
|
|
|
59
59
|
"onnx>=1.16.0",
|
|
60
60
|
"onnxscript>=0.1.0",
|
|
61
61
|
]
|
|
62
|
+
mdmp = [
|
|
63
|
+
"mdmp-protocol>=0.2.1",
|
|
64
|
+
]
|
|
62
65
|
|
|
63
66
|
[project.scripts]
|
|
64
67
|
iints = "iints.cli.cli:app"
|
|
@@ -15,6 +15,7 @@ import time
|
|
|
15
15
|
import yaml # Added for Virtual Patient Registry
|
|
16
16
|
import pandas as pd # Added for DataFrame in benchmark results
|
|
17
17
|
import numpy as np
|
|
18
|
+
from typer.core import TyperGroup
|
|
18
19
|
|
|
19
20
|
from rich.console import Console # type: ignore # For pretty printing
|
|
20
21
|
from rich.table import Table # type: ignore # For comparison table
|
|
@@ -45,13 +46,15 @@ from iints.data.registry import (
|
|
|
45
46
|
DatasetRegistryError,
|
|
46
47
|
)
|
|
47
48
|
from iints.data.contracts import load_contract_yaml
|
|
48
|
-
from iints.data.
|
|
49
|
-
|
|
49
|
+
from iints.data.synthetic_mirror import generate_synthetic_mirror
|
|
50
|
+
from iints.mdmp.backend import (
|
|
50
51
|
MDMP_GRADE_ORDER,
|
|
52
|
+
active_mdmp_backend,
|
|
53
|
+
build_mdmp_dashboard_html,
|
|
54
|
+
load_mdmp_contract,
|
|
51
55
|
mdmp_grade_meets_minimum,
|
|
56
|
+
run_mdmp_validation,
|
|
52
57
|
)
|
|
53
|
-
from iints.data.mdmp_visualizer import build_mdmp_dashboard_html
|
|
54
|
-
from iints.data.synthetic_mirror import generate_synthetic_mirror
|
|
55
58
|
from iints.utils.run_io import (
|
|
56
59
|
build_run_metadata,
|
|
57
60
|
build_run_manifest,
|
|
@@ -84,7 +87,33 @@ from iints.validation import (
|
|
|
84
87
|
)
|
|
85
88
|
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
IINTS_ASCII_LOGO = r"""
|
|
91
|
+
/$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$ /$$
|
|
92
|
+
|_ $$_/|_ $$_/| $$$ | $$|__ $$__//$$__ $$ /$$__ $$| $$__ $$| $$ /$$/
|
|
93
|
+
| $$ | $$ | $$$$| $$ | $$ | $$ \__/ | $$ \__/| $$ \ $$| $$ /$$/
|
|
94
|
+
| $$ | $$ | $$ $$ $$ | $$ | $$$$$$ /$$$$$$| $$$$$$ | $$ | $$| $$$$$/
|
|
95
|
+
| $$ | $$ | $$ $$$$ | $$ \____ $$|______/ \____ $$| $$ | $$| $$ $$
|
|
96
|
+
| $$ | $$ | $$\ $$$ | $$ /$$ \ $$ /$$ \ $$| $$ | $$| $$\ $$
|
|
97
|
+
/$$$$$$ /$$$$$$| $$ \ $$ | $$ | $$$$$$/ | $$$$$$/| $$$$$$$/| $$ \ $$
|
|
98
|
+
|______/|______/|__/ \__/ |__/ \______/ \______/ |_______/ |__/ \__/
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
APP_HELP = (
|
|
102
|
+
"IINTS-AF SDK CLI - Intelligent Insulin Titration System for Artificial Pancreas research."
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class BrandedTyperGroup(TyperGroup):
|
|
107
|
+
def get_help(self, ctx): # type: ignore[override]
|
|
108
|
+
return f"{IINTS_ASCII_LOGO}\n\n{super().get_help(ctx)}"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
app = typer.Typer(
|
|
112
|
+
help=APP_HELP,
|
|
113
|
+
context_settings={"max_content_width": 120},
|
|
114
|
+
cls=BrandedTyperGroup,
|
|
115
|
+
rich_markup_mode=None,
|
|
116
|
+
)
|
|
88
117
|
docs_app = typer.Typer(help="Generate documentation and technical summaries for IINTS-AF components.")
|
|
89
118
|
presets_app = typer.Typer(help="Clinic-safe presets and quickstart runs.")
|
|
90
119
|
profiles_app = typer.Typer(help="Patient profiles and physiological presets.")
|
|
@@ -2809,16 +2838,37 @@ def _build_data_contract_template() -> Dict[str, Any]:
|
|
|
2809
2838
|
}
|
|
2810
2839
|
|
|
2811
2840
|
|
|
2841
|
+
def _build_mdmp_core_contract_template() -> Dict[str, Any]:
|
|
2842
|
+
return {
|
|
2843
|
+
"schema": {
|
|
2844
|
+
"name": "cgm_dataset",
|
|
2845
|
+
"version": "1.0",
|
|
2846
|
+
"industry": "health",
|
|
2847
|
+
"columns": [
|
|
2848
|
+
{"name": "timestamp", "type": "datetime", "required": True},
|
|
2849
|
+
{"name": "glucose", "type": "float", "unit": "mg/dL", "bounds": [40, 400], "required": True},
|
|
2850
|
+
],
|
|
2851
|
+
},
|
|
2852
|
+
"consent": {
|
|
2853
|
+
"ai_training_allowed": True,
|
|
2854
|
+
"jurisdiction": "GDPR",
|
|
2855
|
+
"anonymized": True,
|
|
2856
|
+
},
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
|
|
2812
2860
|
@data_app.command("contract-template")
|
|
2813
2861
|
def data_contract_template(
|
|
2814
2862
|
output_path: Annotated[Path, typer.Option(help="Where to write the starter contract YAML")] = Path("data_contract.yaml"),
|
|
2815
2863
|
):
|
|
2816
2864
|
"""Write a starter data contract template for model-ready validation."""
|
|
2817
2865
|
console = Console()
|
|
2818
|
-
|
|
2866
|
+
backend = active_mdmp_backend()
|
|
2867
|
+
template = _build_mdmp_core_contract_template() if backend == "mdmp_core" else _build_data_contract_template()
|
|
2819
2868
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
2820
2869
|
output_path.write_text(yaml.safe_dump(template, sort_keys=False))
|
|
2821
2870
|
console.print(f"[green]Contract template written:[/green] {output_path}")
|
|
2871
|
+
console.print(f"[cyan]Template backend:[/cyan] {backend}")
|
|
2822
2872
|
|
|
2823
2873
|
|
|
2824
2874
|
@data_app.command("contract-run")
|
|
@@ -2843,10 +2893,13 @@ def data_contract_run(
|
|
|
2843
2893
|
raise typer.Exit(code=1)
|
|
2844
2894
|
|
|
2845
2895
|
try:
|
|
2846
|
-
contract =
|
|
2896
|
+
contract = load_mdmp_contract(contract_path)
|
|
2847
2897
|
df = pd.read_csv(input_csv)
|
|
2848
|
-
|
|
2849
|
-
|
|
2898
|
+
report = run_mdmp_validation(
|
|
2899
|
+
contract,
|
|
2900
|
+
df,
|
|
2901
|
+
apply_builtin_transforms=apply_builtin_transforms,
|
|
2902
|
+
)
|
|
2850
2903
|
except Exception as exc:
|
|
2851
2904
|
console.print(f"[bold red]Contract runner failed: {exc}[/bold red]")
|
|
2852
2905
|
raise typer.Exit(code=1)
|
|
@@ -2857,6 +2910,7 @@ def data_contract_run(
|
|
|
2857
2910
|
summary.add_row("Rows", str(report.row_count))
|
|
2858
2911
|
summary.add_row("Compliance", f"{report.compliance_score:.2f}%")
|
|
2859
2912
|
summary.add_row("Status", "[green]PASS[/green]" if report.is_compliant else "[red]FAIL[/red]")
|
|
2913
|
+
summary.add_row("Backend", active_mdmp_backend())
|
|
2860
2914
|
summary.add_row("MDMP grade", report.mdmp_grade)
|
|
2861
2915
|
summary.add_row("MDMP protocol", report.mdmp_protocol_version)
|
|
2862
2916
|
summary.add_row(
|
|
@@ -29,6 +29,16 @@ from ..data.runner import (
|
|
|
29
29
|
from ..data.guardians import mdmp_gate, MDMPGateError
|
|
30
30
|
from ..data.synthetic_mirror import generate_synthetic_mirror, SyntheticMirrorArtifact
|
|
31
31
|
from ..data.mdmp_visualizer import build_mdmp_dashboard_html
|
|
32
|
+
from .backend import (
|
|
33
|
+
MDMPValidationResult,
|
|
34
|
+
MDMPCheckResult,
|
|
35
|
+
MDMP_GRADE_ORDER as BACKEND_MDMP_GRADE_ORDER,
|
|
36
|
+
mdmp_grade_meets_minimum as backend_mdmp_grade_meets_minimum,
|
|
37
|
+
active_mdmp_backend,
|
|
38
|
+
load_mdmp_contract,
|
|
39
|
+
run_mdmp_validation,
|
|
40
|
+
build_mdmp_dashboard_html as build_mdmp_dashboard_html_with_backend,
|
|
41
|
+
)
|
|
32
42
|
|
|
33
43
|
__all__ = [
|
|
34
44
|
"StreamSpec",
|
|
@@ -53,5 +63,12 @@ __all__ = [
|
|
|
53
63
|
"generate_synthetic_mirror",
|
|
54
64
|
"SyntheticMirrorArtifact",
|
|
55
65
|
"build_mdmp_dashboard_html",
|
|
66
|
+
"MDMPValidationResult",
|
|
67
|
+
"MDMPCheckResult",
|
|
68
|
+
"BACKEND_MDMP_GRADE_ORDER",
|
|
69
|
+
"backend_mdmp_grade_meets_minimum",
|
|
70
|
+
"active_mdmp_backend",
|
|
71
|
+
"load_mdmp_contract",
|
|
72
|
+
"run_mdmp_validation",
|
|
73
|
+
"build_mdmp_dashboard_html_with_backend",
|
|
56
74
|
]
|
|
57
|
-
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Iterable, List, Optional
|
|
7
|
+
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
from iints.data.contracts import load_contract_yaml as _load_iints_contract_yaml
|
|
12
|
+
from iints.data.mdmp_visualizer import build_mdmp_dashboard_html as _build_iints_dashboard_html
|
|
13
|
+
from iints.data.runner import ContractRunner as _IintsContractRunner
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
try: # Optional standalone MDMP backend
|
|
17
|
+
from mdmp_core.contracts import load_contract as _load_external_contract
|
|
18
|
+
from mdmp_core.runner import ContractRunner as _ExternalContractRunner
|
|
19
|
+
from mdmp_core.visualizer import build_dashboard_html as _build_external_dashboard_html
|
|
20
|
+
|
|
21
|
+
_EXTERNAL_MDMP_AVAILABLE = True
|
|
22
|
+
except Exception: # pragma: no cover - depends on optional install
|
|
23
|
+
_EXTERNAL_MDMP_AVAILABLE = False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
MDMP_GRADE_ORDER = ("raw", "draft", "research_grade", "clinical_grade", "ai_ready")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class MDMPCheckResult:
|
|
31
|
+
name: str
|
|
32
|
+
passed: bool
|
|
33
|
+
detail: str
|
|
34
|
+
failed_rows: int = 0
|
|
35
|
+
|
|
36
|
+
def to_dict(self) -> dict[str, Any]:
|
|
37
|
+
return {
|
|
38
|
+
"name": self.name,
|
|
39
|
+
"passed": self.passed,
|
|
40
|
+
"detail": self.detail,
|
|
41
|
+
"failed_rows": self.failed_rows,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class MDMPValidationResult:
|
|
47
|
+
is_compliant: bool
|
|
48
|
+
compliance_score: float
|
|
49
|
+
mdmp_grade: str
|
|
50
|
+
mdmp_protocol_version: str
|
|
51
|
+
certified_for_medical_research: bool
|
|
52
|
+
contract_fingerprint_sha256: str
|
|
53
|
+
dataset_fingerprint_sha256: str
|
|
54
|
+
row_count: int
|
|
55
|
+
checks: List[MDMPCheckResult]
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> dict[str, Any]:
|
|
58
|
+
return {
|
|
59
|
+
"is_compliant": self.is_compliant,
|
|
60
|
+
"compliance_score": self.compliance_score,
|
|
61
|
+
"mdmp_grade": self.mdmp_grade,
|
|
62
|
+
"mdmp_protocol_version": self.mdmp_protocol_version,
|
|
63
|
+
"certified_for_medical_research": self.certified_for_medical_research,
|
|
64
|
+
"contract_fingerprint_sha256": self.contract_fingerprint_sha256,
|
|
65
|
+
"dataset_fingerprint_sha256": self.dataset_fingerprint_sha256,
|
|
66
|
+
"row_count": self.row_count,
|
|
67
|
+
"checks": [check.to_dict() for check in self.checks],
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def mdmp_grade_meets_minimum(actual_grade: str, minimum_grade: str) -> bool:
|
|
72
|
+
try:
|
|
73
|
+
actual_idx = MDMP_GRADE_ORDER.index(actual_grade)
|
|
74
|
+
minimum_idx = MDMP_GRADE_ORDER.index(minimum_grade)
|
|
75
|
+
except ValueError:
|
|
76
|
+
return False
|
|
77
|
+
return actual_idx >= minimum_idx
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _normalize_grade(grade: str) -> str:
|
|
81
|
+
value = (grade or "").strip().lower()
|
|
82
|
+
if value in MDMP_GRADE_ORDER:
|
|
83
|
+
return value
|
|
84
|
+
# Backward compatibility with legacy/report variants
|
|
85
|
+
aliases = {
|
|
86
|
+
"clinical": "clinical_grade",
|
|
87
|
+
"research": "research_grade",
|
|
88
|
+
}
|
|
89
|
+
return aliases.get(value, "draft")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _requested_backend() -> str:
|
|
93
|
+
return os.getenv("IINTS_MDMP_BACKEND", "iints").strip().lower()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def active_mdmp_backend() -> str:
|
|
97
|
+
requested = _requested_backend()
|
|
98
|
+
if requested in {"mdmp", "mdmp_core", "external"} and _EXTERNAL_MDMP_AVAILABLE:
|
|
99
|
+
return "mdmp_core"
|
|
100
|
+
if requested == "auto" and _EXTERNAL_MDMP_AVAILABLE:
|
|
101
|
+
return "mdmp_core"
|
|
102
|
+
return "iints"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def load_mdmp_contract(path: Path) -> Any:
|
|
106
|
+
backend = active_mdmp_backend()
|
|
107
|
+
if backend == "mdmp_core":
|
|
108
|
+
try:
|
|
109
|
+
payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
|
|
110
|
+
except Exception:
|
|
111
|
+
payload = {}
|
|
112
|
+
if isinstance(payload, dict) and ("streams" in payload or "processes" in payload):
|
|
113
|
+
# Legacy IINTS contract format.
|
|
114
|
+
return _load_iints_contract_yaml(path)
|
|
115
|
+
try:
|
|
116
|
+
return _load_external_contract(path)
|
|
117
|
+
except Exception:
|
|
118
|
+
# Backward compatibility: legacy IINTS contract format.
|
|
119
|
+
return _load_iints_contract_yaml(path)
|
|
120
|
+
return _load_iints_contract_yaml(path)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _normalize_checks(checks: Iterable[Any]) -> List[MDMPCheckResult]:
|
|
124
|
+
rows: List[MDMPCheckResult] = []
|
|
125
|
+
for check in checks:
|
|
126
|
+
rows.append(
|
|
127
|
+
MDMPCheckResult(
|
|
128
|
+
name=str(getattr(check, "name", "")),
|
|
129
|
+
passed=bool(getattr(check, "passed", False)),
|
|
130
|
+
detail=str(getattr(check, "detail", "")),
|
|
131
|
+
failed_rows=int(getattr(check, "failed_rows", 0) or 0),
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
return rows
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def run_mdmp_validation(
|
|
138
|
+
contract: Any,
|
|
139
|
+
df: pd.DataFrame,
|
|
140
|
+
*,
|
|
141
|
+
apply_builtin_transforms: bool = True,
|
|
142
|
+
) -> MDMPValidationResult:
|
|
143
|
+
backend = active_mdmp_backend()
|
|
144
|
+
if backend == "mdmp_core":
|
|
145
|
+
try:
|
|
146
|
+
raw_result = _ExternalContractRunner(contract).run(df)
|
|
147
|
+
grade = _normalize_grade(str(getattr(raw_result, "grade", "draft")))
|
|
148
|
+
checks = _normalize_checks(getattr(raw_result, "checks", []))
|
|
149
|
+
return MDMPValidationResult(
|
|
150
|
+
is_compliant=bool(getattr(raw_result, "is_compliant", False)),
|
|
151
|
+
compliance_score=float(getattr(raw_result, "compliance_score", 0.0)),
|
|
152
|
+
mdmp_grade=grade,
|
|
153
|
+
mdmp_protocol_version=str(getattr(raw_result, "protocol_version", "1.0")),
|
|
154
|
+
certified_for_medical_research=grade in {"clinical_grade", "ai_ready"},
|
|
155
|
+
contract_fingerprint_sha256=str(getattr(raw_result, "contract_fingerprint_sha256", "")),
|
|
156
|
+
dataset_fingerprint_sha256=str(getattr(raw_result, "dataset_fingerprint_sha256", "")),
|
|
157
|
+
row_count=int(getattr(raw_result, "row_count", len(df))),
|
|
158
|
+
checks=checks,
|
|
159
|
+
)
|
|
160
|
+
except Exception:
|
|
161
|
+
# Backward compatibility for legacy contracts and mixed environments.
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
raw_result = _IintsContractRunner(contract).run(
|
|
165
|
+
df,
|
|
166
|
+
apply_builtin_transforms=apply_builtin_transforms,
|
|
167
|
+
)
|
|
168
|
+
checks = _normalize_checks(raw_result.checks)
|
|
169
|
+
return MDMPValidationResult(
|
|
170
|
+
is_compliant=raw_result.is_compliant,
|
|
171
|
+
compliance_score=raw_result.compliance_score,
|
|
172
|
+
mdmp_grade=_normalize_grade(raw_result.mdmp_grade),
|
|
173
|
+
mdmp_protocol_version=raw_result.mdmp_protocol_version,
|
|
174
|
+
certified_for_medical_research=raw_result.certified_for_medical_research,
|
|
175
|
+
contract_fingerprint_sha256=raw_result.contract_fingerprint_sha256,
|
|
176
|
+
dataset_fingerprint_sha256=raw_result.dataset_fingerprint_sha256,
|
|
177
|
+
row_count=raw_result.row_count,
|
|
178
|
+
checks=checks,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def build_mdmp_dashboard_html(report: dict[str, Any], *, title: str) -> str:
|
|
183
|
+
if active_mdmp_backend() == "mdmp_core":
|
|
184
|
+
return _build_external_dashboard_html(report, title=title)
|
|
185
|
+
return _build_iints_dashboard_html(report, title=title)
|