iints-sdk-python35 1.5.12__tar.gz → 1.5.13__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.5.12/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.5.13}/PKG-INFO +1 -1
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/pyproject.toml +1 -1
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/__init__.py +1 -1
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/clinical_benchmark.py +2 -2
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/explainable_ai.py +46 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/cli/cli.py +300 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/devices/models.py +3 -3
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/__init__.py +3 -1
- iints_sdk_python35-1.5.13/src/iints/core/patient/advanced_metabolic_model.py +226 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/bergman_model.py +77 -38
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/__init__.py +36 -1
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/config.py +5 -1
- iints_sdk_python35-1.5.13/src/iints/research/glucose_model.py +1604 -0
- iints_sdk_python35-1.5.13/src/iints/research/losses.py +190 -0
- iints_sdk_python35-1.5.13/src/iints/tools/ai_realism_auditor.py +324 -0
- iints_sdk_python35-1.5.13/src/iints/tools/digital_twin_calibrator.py +85 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13/src/iints_sdk_python35.egg-info}/PKG-INFO +1 -1
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints_sdk_python35.egg-info/SOURCES.txt +4 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_bergman.py +2 -2
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_research_workflows.py +67 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_presets_realism.py +1 -1
- iints_sdk_python35-1.5.12/src/iints/research/losses.py +0 -98
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/LICENSE +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/LICENSE-MIT-IINTS-LEGACY +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/NOTICE +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/README.md +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/setup.cfg +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/assistant.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/backends/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/backends/base.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/backends/mistral_api.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/backends/ollama.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/cli.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/mdmp_guard.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/model_catalog.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/prepare.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/ai/prompts.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/algorithm_xray.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/baseline.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/booth_demo.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/carelink_workbench.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/clinical_metrics.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/clinical_tir_analyzer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/diabetes_metrics.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/edge_efficiency.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/edge_performance_monitor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/eucys_results.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/evidence_bundle.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/explainability.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/hardware_benchmark.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/metrics.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/population_report.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/poster.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/reporting.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/run_quality.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/safety_index.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/safety_visualizer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/sensor_filtering.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/study_analysis.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/study_engine.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/study_experiment.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/study_poster.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/study_protocol.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/validator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/api/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/api/base_algorithm.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/api/registry.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/api/template_algorithm.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/assets/iints_logo.png +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/cli/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/cli/patient_cli.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/battle_runner.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/clinical_baseline.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/correction_bolus.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/discovery.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/fixed_basal_bolus.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/hybrid_algorithm.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/imitation_controller.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/lstm_algorithm.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/mock_algorithms.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/mpc_controller.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/neural_controller.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/pid_controller.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/algorithms/standard_pump_algo.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/device.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/device_manager.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/devices/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/digital_twin.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/hovorka_model.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/models.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/patient_factory.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/patient/profile.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/physiology_variation.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/safety/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/safety/config.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/safety/input_validator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/safety/supervisor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/simulation/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/simulation/scenario_parser.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/simulator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/core/supervisor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/adapter.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/certify.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/column_mapper.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/contracts.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/datasets.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/demo/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/demo/demo_cgm.csv +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/evidence.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/guardians.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/importer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/ingestor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/mdmp_visualizer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/medtronic_live.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/nightscout.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/physiology_residual_profiles.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/quality_checker.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/realism_dashboard.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/realism_governance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/realism_reference.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/realism_references.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/realism_validator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/registry.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/research_catalog.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/runner.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/study_corruption.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/synthetic_mirror.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/tidepool.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/universal_parser.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_baseline.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_hyper_challenge.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_hypo_prone.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_midnight.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_pizza.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/clinic_safe_stress_meal.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/default_patient.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/patient_559_config.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/reference_azt1d_t1d.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/reference_free_living_t1d.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/data/virtual_patients/reference_hupa_ucm_t1d.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/demo_assets.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/emulation/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/emulation/legacy_base.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/emulation/medtronic_780g.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/emulation/omnipod_5.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/emulation/tandem_controliq.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/highlevel.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/jetson/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/jetson/endurance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/jetson/research_pipeline.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/learning/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/learning/autonomous_optimizer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/learning/learning_system.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/api.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/daemon.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/edge_benchmark.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/edge_ops.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/fpga.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/long_study.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/medtronic_direct.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/pico_pump.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/runtime.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/service_export.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/live_patient/uno_q.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/mdmp/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/mdmp/backend.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/mdmp/eu_ai_pact.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/metrics.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/population/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/population/generator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/population/runner.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/evidence_sources.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/forecast_calibration_profiles.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/golden_benchmark.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/presets.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/safety_contract_default.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/presets/validation_profiles.yaml +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/audit.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/calibration_gate.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/control.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/control_eval.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/data_blend.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/dataset.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/evaluation.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/forecasting.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/local_ai.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/local_ai_gate.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/metrics.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/model_registry.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/neural_control.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/predictor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/research/results_manager.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/scenarios/generator.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/scenarios/study_pack.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/default_algorithm.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/demos/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/demos/live_stage_demo.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/pico_pump/README.md +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/pico_pump/code.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/pico_pump/serial_protocol.txt +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/scenarios/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/scenarios/chaos_insulin_stacking.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/scenarios/chaos_runaway_ai.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/scenarios/example_scenario.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/scenarios/exercise_stress.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/uno_q/README.md +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/templates/uno_q/iints_supervisor_bridge.ino +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/utils/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/utils/csv_safety.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/utils/plotting.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/utils/run_io.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/utils/url_safety.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/golden.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/replay.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/run_doctor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/run_validation.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/safety_contract.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/validation/schemas.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/visualization/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/visualization/cockpit.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/visualization/uncertainty_cloud.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints_sdk_python35.egg-info/dependency_links.txt +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints_sdk_python35.egg-info/entry_points.txt +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints_sdk_python35.egg-info/requires.txt +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints_sdk_python35.egg-info/top_level.txt +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_ai/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_ai/lineage.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/audit.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/bias_hooks.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/bundle.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/certification.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/cli.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/compare.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/conformance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/contracts.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/crypto.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/data/conformance/vectors/delegation.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/data/conformance/vectors/fingerprint.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/data/conformance/vectors/grading.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/data/conformance/vectors/signing.json +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/delegate.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/diffing.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/drift.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/exceptions.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/fingerprint.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/fingerprint_store.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/hf.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/keys/mdmp_pub_v1.pem +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/llm_provenance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/migrate.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/policy.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/prov.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/registry.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/runner.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/schema_export.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/synthetic.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/trust.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_core/visualizer.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_flavors/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_integrations/__init__.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_integrations/dvc.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_integrations/mlflow.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/mdmp_integrations/wandb.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_ci_governance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_algorithm_loading.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_booth_demo.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_carelink_workbench.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_cloud_import_security.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_demo_export.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_demo_live.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_edge_runtime.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_expo_tools.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_fpga.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_onboarding.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_patient_runtime.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_poster.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_cli_run_summary.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_install_doctor.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_jetson_endurance.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_physiology_variation.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_plugin_system.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_population.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_research_realism_tools.py +0 -0
- {iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/tests/test_simulator_calibration.py +0 -0
|
@@ -11,7 +11,7 @@ except ImportError: # pragma: no cover - Python < 3.8 fallback
|
|
|
11
11
|
try:
|
|
12
12
|
__version__ = version("iints-sdk-python35")
|
|
13
13
|
except PackageNotFoundError: # pragma: no cover - source tree fallback
|
|
14
|
-
__version__ = "1.5.
|
|
14
|
+
__version__ = "1.5.13"
|
|
15
15
|
|
|
16
16
|
# Note to developers: this SDK is currently maintained by a single author.
|
|
17
17
|
# Please report bugs via GitHub issues and feel free to contribute fixes via PRs.
|
{iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/clinical_benchmark.py
RENAMED
|
@@ -14,7 +14,7 @@ from rich.panel import Panel
|
|
|
14
14
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
15
15
|
|
|
16
16
|
# Add project root to path
|
|
17
|
-
project_root = Path(__file__).parent.parent.parent
|
|
17
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
18
18
|
sys.path.insert(0, str(project_root))
|
|
19
19
|
|
|
20
20
|
from iints.data.adapter import DataAdapter
|
|
@@ -81,7 +81,7 @@ class ClinicalBenchmark:
|
|
|
81
81
|
"""Display benchmark results in formatted table with visualization"""
|
|
82
82
|
|
|
83
83
|
# Import visualization tools
|
|
84
|
-
from tools.glucose_visualizer import GlucoseVisualizer
|
|
84
|
+
from tools.analysis.glucose_visualizer import GlucoseVisualizer
|
|
85
85
|
viz = GlucoseVisualizer()
|
|
86
86
|
|
|
87
87
|
# Show patient overview first
|
{iints_sdk_python35-1.5.12 → iints_sdk_python35-1.5.13}/src/iints/analysis/explainable_ai.py
RENAMED
|
@@ -9,13 +9,59 @@ from datetime import datetime, timedelta
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
12
|
+
# Import the local Ollama backend
|
|
13
|
+
from iints.ai.backends.ollama import OllamaBackend
|
|
14
|
+
|
|
12
15
|
class ClinicalAuditTrail:
|
|
13
16
|
"""Explainable AI system for clinical decision transparency"""
|
|
14
17
|
|
|
15
18
|
def __init__(self):
|
|
16
19
|
self.audit_log = []
|
|
17
20
|
self.decision_context = {}
|
|
21
|
+
self.ollama = None
|
|
22
|
+
|
|
23
|
+
def _init_ollama(self):
|
|
24
|
+
if self.ollama is None:
|
|
25
|
+
self.ollama = OllamaBackend()
|
|
26
|
+
try:
|
|
27
|
+
self.ollama.ensure_model_ready()
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print(f"Warning: Local AI not available: {e}")
|
|
30
|
+
|
|
31
|
+
def generate_ollama_insight(self, times, glucose, ffa, ketones, insulin):
|
|
32
|
+
"""
|
|
33
|
+
Sends the raw physiological arrays to the local Mistral LLM via Ollama
|
|
34
|
+
for an Explainable AI clinical diagnosis.
|
|
35
|
+
"""
|
|
36
|
+
self._init_ollama()
|
|
37
|
+
if not self.ollama or not self.ollama.available():
|
|
38
|
+
return "ERROR: Local Ollama AI is not running or available."
|
|
39
|
+
|
|
40
|
+
# Format the data arrays for the LLM
|
|
41
|
+
data_summary = (
|
|
42
|
+
f"Time (min): {times[-5:]}\n"
|
|
43
|
+
f"Glucose (mg/dL): {[round(g, 1) for g in glucose[-5:]]}\n"
|
|
44
|
+
f"Insulin (U): {[round(i, 2) for i in insulin[-5:]]}\n"
|
|
45
|
+
f"FFA (mmol/L): {[round(f, 2) for f in ffa[-5:]]}\n"
|
|
46
|
+
f"Ketones (mmol/L): {[round(k, 2) for k in ketones[-5:]]}\n"
|
|
47
|
+
)
|
|
18
48
|
|
|
49
|
+
system_prompt = (
|
|
50
|
+
"You are an Explainable AI for a Type 1 Diabetes Digital Twin. "
|
|
51
|
+
"You analyze raw mathematical arrays from the simulation and provide a clinical explanation. "
|
|
52
|
+
"Explain what the math is doing to the patient. If insulin is 0, mention hepatic glucose production. "
|
|
53
|
+
"If FFA and Ketones are rising, diagnose the lipotoxicity and Diabetic Ketoacidosis (DKA). "
|
|
54
|
+
"Keep the response professional, clinical, and under 4 sentences."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
user_prompt = f"Analyze the following patient state from the last 25 minutes of the simulation:\n{data_summary}"
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
response = self.ollama.complete(system_prompt=system_prompt, user_prompt=user_prompt)
|
|
61
|
+
return response
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return f"AI Generation Failed: {e}"
|
|
64
|
+
|
|
19
65
|
def log_decision(self, timestamp, glucose_current, glucose_trend, insulin_decision,
|
|
20
66
|
algorithm_confidence, safety_override=False, context=None):
|
|
21
67
|
"""Log AI decision with clinical reasoning"""
|
|
@@ -8501,6 +8501,10 @@ def sources(
|
|
|
8501
8501
|
|
|
8502
8502
|
research_app = typer.Typer(help="Research pipeline: dataset preparation and quality reporting.")
|
|
8503
8503
|
app.add_typer(research_app, name="research")
|
|
8504
|
+
glucose_model_app = typer.Typer(
|
|
8505
|
+
help="Dedicated glucose forecasting model workflow for training and Hugging Face export."
|
|
8506
|
+
)
|
|
8507
|
+
research_app.add_typer(glucose_model_app, name="glucose-model")
|
|
8504
8508
|
|
|
8505
8509
|
|
|
8506
8510
|
@research_app.command(name="prepare-azt1d")
|
|
@@ -9602,6 +9606,302 @@ def research_forecast_run(
|
|
|
9602
9606
|
)
|
|
9603
9607
|
|
|
9604
9608
|
|
|
9609
|
+
@glucose_model_app.command(name="build-dataset")
|
|
9610
|
+
def research_glucose_model_build_dataset(
|
|
9611
|
+
input_paths: Annotated[
|
|
9612
|
+
List[Path],
|
|
9613
|
+
typer.Option(
|
|
9614
|
+
"--input",
|
|
9615
|
+
"-i",
|
|
9616
|
+
help="Prepared glucose dataset CSV/Parquet. Repeat for Ohio, AZT1D, simulator exports, etc.",
|
|
9617
|
+
),
|
|
9618
|
+
],
|
|
9619
|
+
output_dir: Annotated[
|
|
9620
|
+
Path,
|
|
9621
|
+
typer.Option(help="Output folder for normalized training dataset, manifest, and config."),
|
|
9622
|
+
] = Path("models/iints-glucose-forecast-v0/dataset"),
|
|
9623
|
+
labels_csv: Annotated[
|
|
9624
|
+
Optional[str],
|
|
9625
|
+
typer.Option(
|
|
9626
|
+
"--labels",
|
|
9627
|
+
help="Optional comma-separated labels matching --input order, e.g. ohio_train,sim_10k.",
|
|
9628
|
+
),
|
|
9629
|
+
] = None,
|
|
9630
|
+
profile: Annotated[str, typer.Option(help="Training profile: smoke, quick, long, or paper.")] = "long",
|
|
9631
|
+
output_format: Annotated[str, typer.Option(help="Dataset output format: csv or parquet.")] = "csv",
|
|
9632
|
+
history_minutes: Annotated[int, typer.Option(help="Model history window in minutes.")] = 360,
|
|
9633
|
+
horizon_minutes: Annotated[int, typer.Option(help="Prediction horizon in minutes.")] = 120,
|
|
9634
|
+
time_step_minutes: Annotated[int, typer.Option(help="Expected CGM sample interval in minutes.")] = 5,
|
|
9635
|
+
) -> None:
|
|
9636
|
+
"""Build the dedicated IINTS glucose-forecast training pack."""
|
|
9637
|
+
console = Console()
|
|
9638
|
+
labels = None
|
|
9639
|
+
if labels_csv:
|
|
9640
|
+
labels = [item.strip() for item in labels_csv.split(",") if item.strip()]
|
|
9641
|
+
try:
|
|
9642
|
+
from iints.research.glucose_model import build_glucose_training_pack
|
|
9643
|
+
|
|
9644
|
+
pack = build_glucose_training_pack(
|
|
9645
|
+
input_paths,
|
|
9646
|
+
output_dir,
|
|
9647
|
+
labels=labels,
|
|
9648
|
+
output_format=output_format,
|
|
9649
|
+
profile=profile,
|
|
9650
|
+
history_minutes=history_minutes,
|
|
9651
|
+
horizon_minutes=horizon_minutes,
|
|
9652
|
+
time_step_minutes=time_step_minutes,
|
|
9653
|
+
)
|
|
9654
|
+
except Exception as exc:
|
|
9655
|
+
console.print(f"[bold red]glucose-model build-dataset failed:[/bold red] {exc}")
|
|
9656
|
+
raise typer.Exit(code=1)
|
|
9657
|
+
|
|
9658
|
+
table = Table(title="IINTS Glucose Model Training Pack")
|
|
9659
|
+
table.add_column("Artifact", style="cyan")
|
|
9660
|
+
table.add_column("Value", overflow="fold")
|
|
9661
|
+
table.add_row("Rows", str(pack.row_count))
|
|
9662
|
+
table.add_row("Subjects", str(pack.subject_count))
|
|
9663
|
+
table.add_row("Sources", str(pack.source_count))
|
|
9664
|
+
table.add_row("Dataset", str(pack.dataset_path))
|
|
9665
|
+
table.add_row("Config", str(pack.config_path))
|
|
9666
|
+
table.add_row("Manifest", str(pack.manifest_path))
|
|
9667
|
+
table.add_row("Intent", str(pack.model_intent_path))
|
|
9668
|
+
console.print(table)
|
|
9669
|
+
console.print(
|
|
9670
|
+
"[green]Next:[/green] "
|
|
9671
|
+
f"iints research glucose-model train --data {pack.dataset_path} "
|
|
9672
|
+
f"--config {pack.config_path} --output-dir models/iints-glucose-forecast-v0"
|
|
9673
|
+
)
|
|
9674
|
+
|
|
9675
|
+
|
|
9676
|
+
@glucose_model_app.command(name="init")
|
|
9677
|
+
def research_glucose_model_init(
|
|
9678
|
+
output_dir: Annotated[Path, typer.Option(help="Output directory for the glucose model starter files.")] = Path(
|
|
9679
|
+
"models/iints-glucose-forecast-v0"
|
|
9680
|
+
),
|
|
9681
|
+
profile: Annotated[str, typer.Option(help="Training profile: smoke, quick, long, or paper.")] = "long",
|
|
9682
|
+
history_minutes: Annotated[int, typer.Option(help="Model history window in minutes.")] = 360,
|
|
9683
|
+
horizon_minutes: Annotated[int, typer.Option(help="Prediction horizon in minutes.")] = 120,
|
|
9684
|
+
time_step_minutes: Annotated[int, typer.Option(help="Expected CGM sample interval in minutes.")] = 5,
|
|
9685
|
+
) -> None:
|
|
9686
|
+
"""Create a glucose-model config and intent file without touching data."""
|
|
9687
|
+
console = Console()
|
|
9688
|
+
try:
|
|
9689
|
+
from iints.research.glucose_model import _render_model_intent, write_glucose_model_config
|
|
9690
|
+
|
|
9691
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
9692
|
+
config_path = output_dir / "glucose_model_config.yaml"
|
|
9693
|
+
payload = write_glucose_model_config(
|
|
9694
|
+
config_path,
|
|
9695
|
+
profile=profile,
|
|
9696
|
+
history_minutes=history_minutes,
|
|
9697
|
+
horizon_minutes=horizon_minutes,
|
|
9698
|
+
time_step_minutes=time_step_minutes,
|
|
9699
|
+
)
|
|
9700
|
+
intent_payload = {
|
|
9701
|
+
"row_count": "pending",
|
|
9702
|
+
"subject_count": "pending",
|
|
9703
|
+
"source_count": "pending",
|
|
9704
|
+
"history_minutes": history_minutes,
|
|
9705
|
+
"horizon_minutes": horizon_minutes,
|
|
9706
|
+
}
|
|
9707
|
+
intent_path = output_dir / "MODEL_INTENT.md"
|
|
9708
|
+
intent_path.write_text(_render_model_intent(intent_payload))
|
|
9709
|
+
except Exception as exc:
|
|
9710
|
+
console.print(f"[bold red]glucose-model init failed:[/bold red] {exc}")
|
|
9711
|
+
raise typer.Exit(code=1)
|
|
9712
|
+
|
|
9713
|
+
console.print(f"[green]Config written:[/green] {config_path}")
|
|
9714
|
+
console.print(f"[green]Intent written:[/green] {intent_path}")
|
|
9715
|
+
console.print(f"Profile: {payload['iints_glucose_model']['profile']}")
|
|
9716
|
+
|
|
9717
|
+
|
|
9718
|
+
@glucose_model_app.command(name="train")
|
|
9719
|
+
def research_glucose_model_train(
|
|
9720
|
+
data: Annotated[Path, typer.Option(help="Normalized glucose training dataset CSV/Parquet.")],
|
|
9721
|
+
output_dir: Annotated[Path, typer.Option(help="Output directory for predictor.pt and training_report.json.")] = Path(
|
|
9722
|
+
"models/iints-glucose-forecast-v0"
|
|
9723
|
+
),
|
|
9724
|
+
config: Annotated[Optional[Path], typer.Option(help="Config YAML. If omitted, one is generated.")] = None,
|
|
9725
|
+
profile: Annotated[str, typer.Option(help="Generated config profile: smoke, quick, long, or paper.")] = "long",
|
|
9726
|
+
epochs: Annotated[Optional[int], typer.Option(help="Override training.epochs for long local runs.")] = None,
|
|
9727
|
+
batch_size: Annotated[Optional[int], typer.Option(help="Override training.batch_size.")] = None,
|
|
9728
|
+
learning_rate: Annotated[Optional[float], typer.Option(help="Override training.learning_rate.")] = None,
|
|
9729
|
+
warm_start: Annotated[Optional[Path], typer.Option(help="Optional predictor.pt warm-start checkpoint.")] = None,
|
|
9730
|
+
export_hf: Annotated[
|
|
9731
|
+
bool,
|
|
9732
|
+
typer.Option("--export-hf/--no-export-hf", help="Build a Hugging Face-ready folder after training."),
|
|
9733
|
+
] = True,
|
|
9734
|
+
repo_id: Annotated[Optional[str], typer.Option(help="Optional Hugging Face repo id for model card hints.")] = None,
|
|
9735
|
+
dataset_manifest: Annotated[Optional[Path], typer.Option(help="Optional dataset manifest for HF public metadata.")] = None,
|
|
9736
|
+
comparison_dir: Annotated[
|
|
9737
|
+
Optional[Path],
|
|
9738
|
+
typer.Option(help="Optional glucose-model compare output directory to bundle with the Hugging Face export."),
|
|
9739
|
+
] = None,
|
|
9740
|
+
) -> None:
|
|
9741
|
+
"""Train the dedicated IINTS glucose-forecast model using the existing predictor engine."""
|
|
9742
|
+
console = Console()
|
|
9743
|
+
if not data.exists():
|
|
9744
|
+
console.print(f"[bold red]Dataset not found: {data}[/bold red]")
|
|
9745
|
+
raise typer.Exit(code=1)
|
|
9746
|
+
|
|
9747
|
+
try:
|
|
9748
|
+
from iints.research.glucose_model import write_glucose_model_config, write_huggingface_export_bundle
|
|
9749
|
+
|
|
9750
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
9751
|
+
resolved_config = output_dir / "glucose_model_config.resolved.yaml"
|
|
9752
|
+
if config is None:
|
|
9753
|
+
payload = write_glucose_model_config(output_dir / "glucose_model_config.yaml", profile=profile)
|
|
9754
|
+
else:
|
|
9755
|
+
payload = yaml.safe_load(config.read_text())
|
|
9756
|
+
if epochs is not None:
|
|
9757
|
+
payload.setdefault("training", {})["epochs"] = int(epochs)
|
|
9758
|
+
if batch_size is not None:
|
|
9759
|
+
payload.setdefault("training", {})["batch_size"] = int(batch_size)
|
|
9760
|
+
if learning_rate is not None:
|
|
9761
|
+
payload.setdefault("training", {})["learning_rate"] = float(learning_rate)
|
|
9762
|
+
resolved_config.write_text(yaml.safe_dump(payload, sort_keys=False))
|
|
9763
|
+
|
|
9764
|
+
script = Path(__file__).resolve().parents[3] / "research" / "train_predictor.py"
|
|
9765
|
+
cmd = [
|
|
9766
|
+
sys.executable,
|
|
9767
|
+
str(script),
|
|
9768
|
+
"--data",
|
|
9769
|
+
str(data),
|
|
9770
|
+
"--config",
|
|
9771
|
+
str(resolved_config),
|
|
9772
|
+
"--out",
|
|
9773
|
+
str(output_dir),
|
|
9774
|
+
]
|
|
9775
|
+
if warm_start is not None:
|
|
9776
|
+
cmd.extend(["--warm-start", str(warm_start)])
|
|
9777
|
+
subprocess.run(cmd, check=True)
|
|
9778
|
+
hf_outputs = None
|
|
9779
|
+
if export_hf:
|
|
9780
|
+
manifest = dataset_manifest
|
|
9781
|
+
if manifest is None:
|
|
9782
|
+
candidate = data.parent / "glucose_dataset_manifest.json"
|
|
9783
|
+
manifest = candidate if candidate.exists() else None
|
|
9784
|
+
hf_outputs = write_huggingface_export_bundle(
|
|
9785
|
+
model_dir=output_dir,
|
|
9786
|
+
output_dir=output_dir / "huggingface",
|
|
9787
|
+
repo_id=repo_id,
|
|
9788
|
+
dataset_manifest=manifest,
|
|
9789
|
+
comparison_dir=comparison_dir,
|
|
9790
|
+
)
|
|
9791
|
+
except subprocess.CalledProcessError as exc:
|
|
9792
|
+
console.print(f"[bold red]glucose-model train failed with exit code {exc.returncode}[/bold red]")
|
|
9793
|
+
raise typer.Exit(code=exc.returncode)
|
|
9794
|
+
except Exception as exc:
|
|
9795
|
+
console.print(f"[bold red]glucose-model train failed:[/bold red] {exc}")
|
|
9796
|
+
raise typer.Exit(code=1)
|
|
9797
|
+
|
|
9798
|
+
console.print(f"[green]Model written:[/green] {output_dir / 'predictor.pt'}")
|
|
9799
|
+
console.print(f"[green]Training report:[/green] {output_dir / 'training_report.json'}")
|
|
9800
|
+
if hf_outputs:
|
|
9801
|
+
console.print(f"[green]Hugging Face bundle:[/green] {hf_outputs['output_dir']}")
|
|
9802
|
+
|
|
9803
|
+
|
|
9804
|
+
@glucose_model_app.command(name="export-hf")
|
|
9805
|
+
def research_glucose_model_export_hf(
|
|
9806
|
+
model_dir: Annotated[Path, typer.Option(help="Directory containing predictor.pt and training_report.json.")] = Path(
|
|
9807
|
+
"models/iints-glucose-forecast-v0"
|
|
9808
|
+
),
|
|
9809
|
+
output_dir: Annotated[Path, typer.Option(help="Output directory for the Hugging Face-ready bundle.")] = Path(
|
|
9810
|
+
"models/iints-glucose-forecast-v0/huggingface"
|
|
9811
|
+
),
|
|
9812
|
+
repo_id: Annotated[Optional[str], typer.Option(help="Optional Hugging Face repo id, e.g. user/iints-glucose-forecast-v0.")] = None,
|
|
9813
|
+
dataset_manifest: Annotated[Optional[Path], typer.Option(help="Optional private manifest to redact into public metadata.")] = None,
|
|
9814
|
+
comparison_dir: Annotated[
|
|
9815
|
+
Optional[Path],
|
|
9816
|
+
typer.Option(help="Optional glucose-model compare output directory to include comparison metrics and reports."),
|
|
9817
|
+
] = None,
|
|
9818
|
+
) -> None:
|
|
9819
|
+
"""Export predictor.pt plus a research-safe Hugging Face model card."""
|
|
9820
|
+
console = Console()
|
|
9821
|
+
try:
|
|
9822
|
+
from iints.research.glucose_model import write_huggingface_export_bundle
|
|
9823
|
+
|
|
9824
|
+
outputs = write_huggingface_export_bundle(
|
|
9825
|
+
model_dir=model_dir,
|
|
9826
|
+
output_dir=output_dir,
|
|
9827
|
+
repo_id=repo_id,
|
|
9828
|
+
dataset_manifest=dataset_manifest,
|
|
9829
|
+
comparison_dir=comparison_dir,
|
|
9830
|
+
)
|
|
9831
|
+
except Exception as exc:
|
|
9832
|
+
console.print(f"[bold red]glucose-model export-hf failed:[/bold red] {exc}")
|
|
9833
|
+
raise typer.Exit(code=1)
|
|
9834
|
+
|
|
9835
|
+
table = Table(title="Hugging Face Export Bundle")
|
|
9836
|
+
table.add_column("Artifact", style="cyan")
|
|
9837
|
+
table.add_column("Path", overflow="fold")
|
|
9838
|
+
for key, value in outputs.items():
|
|
9839
|
+
table.add_row(key, value)
|
|
9840
|
+
console.print(table)
|
|
9841
|
+
console.print("[yellow]Recommended:[/yellow] upload private first, review README.md, then decide whether public is allowed.")
|
|
9842
|
+
|
|
9843
|
+
|
|
9844
|
+
@glucose_model_app.command(name="compare")
|
|
9845
|
+
def research_glucose_model_compare(
|
|
9846
|
+
data: Annotated[Path, typer.Option(help="Normalized glucose dataset CSV/Parquet to evaluate on.")],
|
|
9847
|
+
output_dir: Annotated[Path, typer.Option(help="Output directory for comparison reports.")] = Path(
|
|
9848
|
+
"results/glucose_model_comparison"
|
|
9849
|
+
),
|
|
9850
|
+
model_specs: Annotated[
|
|
9851
|
+
Optional[List[str]],
|
|
9852
|
+
typer.Option(
|
|
9853
|
+
"--model",
|
|
9854
|
+
"-m",
|
|
9855
|
+
help="Model checkpoint as label=path/to/predictor.pt. Repeat for MSE/Band/PINN models.",
|
|
9856
|
+
),
|
|
9857
|
+
] = None,
|
|
9858
|
+
config: Annotated[Optional[Path], typer.Option(help="Comparison config YAML. Defaults to glucose-model quick config.")] = None,
|
|
9859
|
+
include_baselines: Annotated[
|
|
9860
|
+
bool,
|
|
9861
|
+
typer.Option("--include-baselines/--no-baselines", help="Compare transparent LastValue/LinearTrend/Physiology baselines."),
|
|
9862
|
+
] = True,
|
|
9863
|
+
mc_samples: Annotated[int, typer.Option(help="MC dropout samples for checkpoint uncertainty. Use 0 to disable.")] = 0,
|
|
9864
|
+
max_roc_mgdl_min: Annotated[
|
|
9865
|
+
float,
|
|
9866
|
+
typer.Option(help="Maximum plausible predicted glucose rate-of-change in mg/dL/min."),
|
|
9867
|
+
] = 10.0,
|
|
9868
|
+
) -> None:
|
|
9869
|
+
"""Compare MSE/Band/PINN glucose models against baselines and physiology gates."""
|
|
9870
|
+
console = Console()
|
|
9871
|
+
try:
|
|
9872
|
+
from iints.research.glucose_model import compare_glucose_models, parse_model_specs
|
|
9873
|
+
|
|
9874
|
+
bundle = compare_glucose_models(
|
|
9875
|
+
data_path=data,
|
|
9876
|
+
output_dir=output_dir,
|
|
9877
|
+
model_specs=parse_model_specs(model_specs or []),
|
|
9878
|
+
config_path=config,
|
|
9879
|
+
include_baselines=include_baselines,
|
|
9880
|
+
mc_samples=mc_samples,
|
|
9881
|
+
max_roc_mgdl_min=max_roc_mgdl_min,
|
|
9882
|
+
)
|
|
9883
|
+
except Exception as exc:
|
|
9884
|
+
console.print(f"[bold red]glucose-model compare failed:[/bold red] {exc}")
|
|
9885
|
+
raise typer.Exit(code=1)
|
|
9886
|
+
|
|
9887
|
+
table = Table(title="IINTS Glucose Model Comparison")
|
|
9888
|
+
table.add_column("Artifact", style="cyan")
|
|
9889
|
+
table.add_column("Path / Value", overflow="fold")
|
|
9890
|
+
table.add_row("Rows", str(bundle.row_count))
|
|
9891
|
+
table.add_row("Models", str(bundle.model_count))
|
|
9892
|
+
table.add_row("Report JSON", str(bundle.report_json))
|
|
9893
|
+
table.add_row("Report Markdown", str(bundle.report_md))
|
|
9894
|
+
table.add_row("Horizon metrics", str(bundle.horizon_metrics_csv))
|
|
9895
|
+
table.add_row("Physiology violations", str(bundle.physiological_violations_csv))
|
|
9896
|
+
table.add_row("Hypo detection", str(bundle.hypo_detection_csv))
|
|
9897
|
+
table.add_row("Model-card metrics", str(bundle.model_card_metrics_json))
|
|
9898
|
+
console.print(table)
|
|
9899
|
+
console.print(
|
|
9900
|
+
"[yellow]Promotion rule:[/yellow] do not promote a model just because MAE improves; "
|
|
9901
|
+
"also inspect missed hypo rate, uncertainty, and physiological violations."
|
|
9902
|
+
)
|
|
9903
|
+
|
|
9904
|
+
|
|
9605
9905
|
@research_app.command(name="parity-check")
|
|
9606
9906
|
def research_parity_check(
|
|
9607
9907
|
model: Annotated[Path, typer.Option(help="Predictor checkpoint (.pt)")],
|
|
@@ -22,12 +22,12 @@ class SensorModel:
|
|
|
22
22
|
|
|
23
23
|
def __init__(
|
|
24
24
|
self,
|
|
25
|
-
noise_std: float =
|
|
25
|
+
noise_std: float = 8.5,
|
|
26
26
|
bias: float = 0.0,
|
|
27
|
-
lag_minutes: int =
|
|
27
|
+
lag_minutes: int = 5,
|
|
28
28
|
isf_tau_minutes: float = 5.0,
|
|
29
29
|
noise_ar1_phi: float = 0.85,
|
|
30
|
-
noise_fbm_hurst: Optional[float] =
|
|
30
|
+
noise_fbm_hurst: Optional[float] = 0.78,
|
|
31
31
|
dropout_prob: float = 0.0,
|
|
32
32
|
seed: Optional[int] = None,
|
|
33
33
|
drift_std_per_hour: float = 0.0,
|
|
@@ -3,7 +3,9 @@ from .models import PatientModel
|
|
|
3
3
|
|
|
4
4
|
try:
|
|
5
5
|
from .bergman_model import BergmanPatientModel
|
|
6
|
+
from .advanced_metabolic_model import AdvancedMetabolicModel
|
|
6
7
|
except ImportError: # pragma: no cover - scipy may not be installed
|
|
7
8
|
BergmanPatientModel = None # type: ignore[assignment,misc]
|
|
9
|
+
AdvancedMetabolicModel = None
|
|
8
10
|
|
|
9
|
-
__all__ = ["PatientProfile", "PatientModel", "BergmanPatientModel"]
|
|
11
|
+
__all__ = ["PatientProfile", "PatientModel", "BergmanPatientModel", "AdvancedMetabolicModel"]
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
from scipy.integrate import solve_ivp
|
|
4
|
+
|
|
5
|
+
from .bergman_model import BergmanPatientModel, BergmanParameters
|
|
6
|
+
|
|
7
|
+
class AdvancedMetabolicModel(BergmanPatientModel):
|
|
8
|
+
"""
|
|
9
|
+
Advanced Metabolic Model for IINTS-AF.
|
|
10
|
+
Extends the 13-state Bergman model to a 16-state model including:
|
|
11
|
+
- F: Free Fatty Acids (FFA) (mmol/L)
|
|
12
|
+
- K: Ketone Bodies (mmol/L)
|
|
13
|
+
- Beta: Residual Beta-cell mass fraction (0.0 to 1.0)
|
|
14
|
+
|
|
15
|
+
Includes lipotoxicity (high FFA causes insulin resistance) and
|
|
16
|
+
DKA (Ketone production under extreme insulin deficiency).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
initial_beta_mass: float = 0.0, # 0.0 = completely destroyed, 1.0 = healthy
|
|
22
|
+
autoimmune_aggressiveness: float = 7e-6, # Decay rate of beta cells per min
|
|
23
|
+
initial_ffa: float = 0.4,
|
|
24
|
+
initial_ketones: float = 0.1,
|
|
25
|
+
gamma_healthy: float = 0.005,
|
|
26
|
+
**kwargs,
|
|
27
|
+
) -> None:
|
|
28
|
+
self.initial_beta_mass = initial_beta_mass
|
|
29
|
+
self.autoimmune_aggressiveness = autoimmune_aggressiveness
|
|
30
|
+
self.initial_ffa = initial_ffa
|
|
31
|
+
self.initial_ketones = initial_ketones
|
|
32
|
+
self.gamma_healthy = gamma_healthy
|
|
33
|
+
|
|
34
|
+
super().__init__(**kwargs)
|
|
35
|
+
|
|
36
|
+
# Override the 13-state with 16-state
|
|
37
|
+
# State vector: [G, X, I, Q_sto1, Q_sto2, Q_gut, S1, S2, Y1, Y2, Gamma, x_gluc, HAAF, F, K, Beta]
|
|
38
|
+
self._state = np.array([
|
|
39
|
+
self.initial_glucose, # 0: G
|
|
40
|
+
0.0, # 1: X
|
|
41
|
+
self.params.Ib, # 2: I
|
|
42
|
+
0.0, # 3: Q_sto1
|
|
43
|
+
0.0, # 4: Q_sto2
|
|
44
|
+
0.0, # 5: Q_gut
|
|
45
|
+
0.0, # 6: S1
|
|
46
|
+
0.0, # 7: S2
|
|
47
|
+
0.0, # 8: Y1
|
|
48
|
+
0.0, # 9: Y2
|
|
49
|
+
0.0, # 10: Gamma
|
|
50
|
+
0.0, # 11: x_gluc
|
|
51
|
+
0.0, # 12: HAAF
|
|
52
|
+
self.initial_ffa, # 13: F (FFA)
|
|
53
|
+
self.initial_ketones, # 14: K (Ketones)
|
|
54
|
+
self.initial_beta_mass,# 15: Beta
|
|
55
|
+
], dtype=np.float64)
|
|
56
|
+
|
|
57
|
+
def reset(self) -> None:
|
|
58
|
+
super().reset()
|
|
59
|
+
self._state = np.array([
|
|
60
|
+
self.initial_glucose, 0.0, self.params.Ib, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
61
|
+
0.0, 0.0, 0.0, 0.0, 0.0, self.initial_ffa, self.initial_ketones, self.initial_beta_mass
|
|
62
|
+
], dtype=np.float64)
|
|
63
|
+
|
|
64
|
+
def get_patient_state(self) -> Dict[str, float]:
|
|
65
|
+
state_dict = super().get_patient_state()
|
|
66
|
+
state_dict.update({
|
|
67
|
+
"plasma_ffa_mmol_L": float(self._state[13]),
|
|
68
|
+
"plasma_ketones_mmol_L": float(self._state[14]),
|
|
69
|
+
"residual_beta_cell_mass": float(self._state[15]),
|
|
70
|
+
})
|
|
71
|
+
return state_dict
|
|
72
|
+
|
|
73
|
+
def set_state(self, state: Dict[str, Any]) -> None:
|
|
74
|
+
if "ode_state" in state:
|
|
75
|
+
ode_state = np.array(state["ode_state"], dtype=np.float64)
|
|
76
|
+
if ode_state.size == 13:
|
|
77
|
+
# Upgrade legacy 13-state to 16-state
|
|
78
|
+
ode_state = np.append(ode_state, [self.initial_ffa, self.initial_ketones, self.initial_beta_mass])
|
|
79
|
+
self._state = ode_state
|
|
80
|
+
# Call super for the rest, but temporarly pop ode_state so super doesn't overwrite it
|
|
81
|
+
st_copy = state.copy()
|
|
82
|
+
if "ode_state" in st_copy:
|
|
83
|
+
del st_copy["ode_state"]
|
|
84
|
+
super().set_state(st_copy)
|
|
85
|
+
|
|
86
|
+
def _ode(
|
|
87
|
+
self,
|
|
88
|
+
t: float,
|
|
89
|
+
y: np.ndarray,
|
|
90
|
+
u_insulin_mu_per_min: float,
|
|
91
|
+
u_glucagon_pg_per_min: float,
|
|
92
|
+
current_time: float,
|
|
93
|
+
) -> np.ndarray:
|
|
94
|
+
# Unpack 16 states
|
|
95
|
+
G, X, I, Q_sto1, Q_sto2, Q_gut, S1, S2, Y1, Y2, Gamma, x_gluc, HAAF, F, K, Beta = y
|
|
96
|
+
p = self.params
|
|
97
|
+
|
|
98
|
+
Vg_abs = p.Vg * p.body_weight_kg # dL
|
|
99
|
+
Vi_abs = p.Vi * p.body_weight_kg # L
|
|
100
|
+
V_glucagon = p.V_glucagon_per_kg * p.body_weight_kg
|
|
101
|
+
|
|
102
|
+
# --- Glucose rate of appearance from gut ---
|
|
103
|
+
Ra = (p.k_abs * Q_gut) / Vg_abs # mg/dL/min
|
|
104
|
+
|
|
105
|
+
# --- Exogenous Glucagon Kinetics ---
|
|
106
|
+
dY1_dt = u_glucagon_pg_per_min - Y1 / p.t_max_glucagon
|
|
107
|
+
dY2_dt = Y1 / p.t_max_glucagon - Y2 / p.t_max_glucagon
|
|
108
|
+
U_Gamma = Y2 / p.t_max_glucagon
|
|
109
|
+
dGamma_dt = U_Gamma / V_glucagon - p.k_e_glucagon * Gamma
|
|
110
|
+
dx_gluc_dt = -p.k_a_glucagon * x_gluc + p.S_glucagon * p.k_a_glucagon * Gamma
|
|
111
|
+
|
|
112
|
+
# --- Dawn phenomenon ---
|
|
113
|
+
dawn = 0.0
|
|
114
|
+
if self.dawn_phenomenon_strength > 0:
|
|
115
|
+
minutes_in_day = current_time % 1440
|
|
116
|
+
ds = self.dawn_start_hour * 60
|
|
117
|
+
de = self.dawn_end_hour * 60
|
|
118
|
+
if ds <= minutes_in_day <= de:
|
|
119
|
+
dawn = self.dawn_phenomenon_strength / 60.0 # mg/dL/min
|
|
120
|
+
|
|
121
|
+
# --- Exercise & Stress Physiologic Impact ---
|
|
122
|
+
exercise_p1_multiplier = 1.0
|
|
123
|
+
exercise_p3_multiplier = 1.0
|
|
124
|
+
exercise_glucose_uptake = 0.0
|
|
125
|
+
if self.is_exercising:
|
|
126
|
+
exercise_p1_multiplier = 1.0 + 2.0 * self.exercise_intensity
|
|
127
|
+
exercise_p3_multiplier = 1.0 + 2.0 * self.exercise_intensity
|
|
128
|
+
exercise_glucose_uptake = self.exercise_intensity * self.exercise_glucose_consumption_rate
|
|
129
|
+
|
|
130
|
+
stress_p1_multiplier = 1.0
|
|
131
|
+
stress_p3_multiplier = 1.0
|
|
132
|
+
stress_Gb_multiplier = 1.0
|
|
133
|
+
if self.is_stressed:
|
|
134
|
+
stress_p1_multiplier = 1.0 - 0.2 * self.stress_intensity
|
|
135
|
+
stress_p3_multiplier = 1.0 - 0.7 * self.stress_intensity
|
|
136
|
+
stress_Gb_multiplier = 1.0 + 0.5 * self.stress_intensity
|
|
137
|
+
|
|
138
|
+
# --- Endogenous Rescue & HAAF ---
|
|
139
|
+
hypo_delta = max(0.0, 70.0 - G)
|
|
140
|
+
rescue_multiplier = 1.0 + (hypo_delta / 10.0) * (1.0 - HAAF)
|
|
141
|
+
|
|
142
|
+
# HAAF Memory Dynamics
|
|
143
|
+
k_haaf_build = 0.005
|
|
144
|
+
k_haaf_decay = 1.0 / (24 * 60)
|
|
145
|
+
dHAAF_dt = k_haaf_build * hypo_delta * (1.0 - HAAF) - k_haaf_decay * HAAF
|
|
146
|
+
|
|
147
|
+
# --- NEW: Beta-cell autoimmune decay ---
|
|
148
|
+
dBeta_dt = -self.autoimmune_aggressiveness * Beta
|
|
149
|
+
|
|
150
|
+
# --- NEW: FFA & Ketone Dynamics ---
|
|
151
|
+
# F basal = 0.4. Max = 2.0. Insulin sharply suppresses lipolysis.
|
|
152
|
+
l_0 = 0.2
|
|
153
|
+
l_1 = 0.23
|
|
154
|
+
k_f = 0.1
|
|
155
|
+
dF_dt = l_0 * np.exp(-l_1 * I) - k_f * F
|
|
156
|
+
|
|
157
|
+
# K basal = 0.1. Max = 5.0. Ketone production driven by high F and very low I.
|
|
158
|
+
k_0 = 0.125
|
|
159
|
+
k_1 = 0.33
|
|
160
|
+
k_2 = 0.05
|
|
161
|
+
dK_dt = k_0 * F * np.exp(-k_1 * I) - k_2 * K
|
|
162
|
+
|
|
163
|
+
# --- Lipotoxicity (Insulin Resistance via FFAs) ---
|
|
164
|
+
# Normal F is 0.4. If F rises to 2.0, sensitivity (p3) drops to 0.4 / 2.0 = 20%
|
|
165
|
+
lipotoxicity_factor = 0.4 / max(0.4, F)
|
|
166
|
+
|
|
167
|
+
p1_eff = p.p1 * exercise_p1_multiplier * stress_p1_multiplier
|
|
168
|
+
p3_eff = p.p3 * exercise_p3_multiplier * stress_p3_multiplier * lipotoxicity_factor
|
|
169
|
+
|
|
170
|
+
# In T1D with zero insulin, the liver aggressively produces glucose (EGP).
|
|
171
|
+
# We model this by increasing the basal glucose target Gb_eff exponentially
|
|
172
|
+
# as insulin drops and FFAs rise (hepatic insulin resistance).
|
|
173
|
+
starvation_factor = np.exp(-0.4 * I) * (max(F, 0.4) / 0.4)
|
|
174
|
+
hepatic_glucose_production_multiplier = 1.0 + 3.0 * starvation_factor
|
|
175
|
+
|
|
176
|
+
# Gb is multiplied by stress, rescue adrenaline, exogenous glucagon, and hepatic starvation
|
|
177
|
+
Gb_eff = p.Gb * stress_Gb_multiplier * rescue_multiplier * max(0.0, 1.0 + x_gluc) * hepatic_glucose_production_multiplier
|
|
178
|
+
|
|
179
|
+
# --- Physiological Renal Clearance ---
|
|
180
|
+
smooth_threshold_diff = G - 162.0
|
|
181
|
+
softplus_diff = 10.0 * np.log1p(np.exp(smooth_threshold_diff / 10.0))
|
|
182
|
+
F_R = 0.003 * softplus_diff
|
|
183
|
+
|
|
184
|
+
# --- dG/dt (INSTABILITY UPGRADE) ---
|
|
185
|
+
# In the original model: dGdt = -(p1_eff + X)*G + p1_eff*Gb_eff + ...
|
|
186
|
+
# This forces G to magically return to Gb_eff (Homeostasis).
|
|
187
|
+
# We decouple this to make it a true T1D unstable model.
|
|
188
|
+
# Basal Endogenous Glucose Production:
|
|
189
|
+
EGP = p1_eff * Gb_eff
|
|
190
|
+
|
|
191
|
+
# In T1D, Glucose Effectiveness at zero insulin (GEZI) is very low.
|
|
192
|
+
# We drop the automatic -p1_eff * G tissue uptake and ONLY rely on insulin (X).
|
|
193
|
+
dGdt = -X * G + EGP + Ra + dawn - exercise_glucose_uptake - F_R
|
|
194
|
+
|
|
195
|
+
# --- dX/dt ---
|
|
196
|
+
dXdt = -p.p2 * X + p3_eff * max(I - p.Ib, 0.0)
|
|
197
|
+
|
|
198
|
+
# --- dS1/dt, dS2/dt (Subcutaneous Insulin Absorption) ---
|
|
199
|
+
dS1dt = u_insulin_mu_per_min - p.k_a * S1
|
|
200
|
+
dS2dt = p.k_a * S1 - p.k_a * S2
|
|
201
|
+
|
|
202
|
+
# Rate of appearance of insulin into plasma (mU/min)
|
|
203
|
+
Ra_I = p.k_a * S2
|
|
204
|
+
|
|
205
|
+
# --- dI/dt (Including residual beta-cell endogenous secretion) ---
|
|
206
|
+
# Beta is fraction of healthy beta cells.
|
|
207
|
+
endogenous_secretion = Beta * self.gamma_healthy * max(G - p.h, 0.0)
|
|
208
|
+
|
|
209
|
+
# In T1D, basal endogenous insulin (p.Ib) should be proportional to Beta mass.
|
|
210
|
+
# If Beta = 0, and pump is off, insulin should decay to ZERO, not p.Ib.
|
|
211
|
+
target_Ib = p.Ib * Beta
|
|
212
|
+
|
|
213
|
+
dIdt = -p.n * (I - target_Ib) + endogenous_secretion + Ra_I / Vi_abs
|
|
214
|
+
|
|
215
|
+
# --- Dalla Man Multi-compartment Meal Kinetcs ---
|
|
216
|
+
gastric_emptying_rate = 1.0 / max(float(p.tau_meal), 1.0)
|
|
217
|
+
solid_to_liquid_rate = gastric_emptying_rate * 1.5
|
|
218
|
+
dQ_sto1_dt = -solid_to_liquid_rate * Q_sto1
|
|
219
|
+
dQ_sto2_dt = solid_to_liquid_rate * Q_sto1 - gastric_emptying_rate * Q_sto2
|
|
220
|
+
dQ_gut_dt = gastric_emptying_rate * Q_sto2 - p.k_abs * Q_gut
|
|
221
|
+
|
|
222
|
+
return np.array([
|
|
223
|
+
dGdt, dXdt, dIdt, dQ_sto1_dt, dQ_sto2_dt, dQ_gut_dt,
|
|
224
|
+
dS1dt, dS2dt, dY1_dt, dY2_dt, dGamma_dt, dx_gluc_dt,
|
|
225
|
+
dHAAF_dt, dF_dt, dK_dt, dBeta_dt
|
|
226
|
+
])
|