iints-sdk-python35 1.5.7__tar.gz → 1.5.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. {iints_sdk_python35-1.5.7/src/iints_sdk_python35.egg-info → iints_sdk_python35-1.5.9}/PKG-INFO +2 -2
  2. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/pyproject.toml +7 -2
  3. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/__init__.py +43 -1
  4. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/__init__.py +3 -0
  5. iints_sdk_python35-1.5.9/src/iints/analysis/evidence_bundle.py +328 -0
  6. iints_sdk_python35-1.5.9/src/iints/analysis/reporting.py +716 -0
  7. iints_sdk_python35-1.5.9/src/iints/analysis/run_quality.py +91 -0
  8. iints_sdk_python35-1.5.9/src/iints/analysis/safety_visualizer.py +363 -0
  9. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/cli/cli.py +1365 -73
  10. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/patient/bergman_model.py +5 -1
  11. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/__init__.py +36 -0
  12. iints_sdk_python35-1.5.9/src/iints/data/datasets.json +428 -0
  13. iints_sdk_python35-1.5.9/src/iints/data/evidence.py +62 -0
  14. iints_sdk_python35-1.5.9/src/iints/data/medtronic_live.py +484 -0
  15. iints_sdk_python35-1.5.9/src/iints/data/realism_governance.py +208 -0
  16. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/realism_validator.py +1 -0
  17. iints_sdk_python35-1.5.9/src/iints/data/research_catalog.py +248 -0
  18. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/reference_azt1d_t1d.yaml +1 -1
  19. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/reference_free_living_t1d.yaml +1 -1
  20. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/reference_hupa_ucm_t1d.yaml +1 -1
  21. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/highlevel.py +39 -0
  22. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/__init__.py +18 -0
  23. iints_sdk_python35-1.5.9/src/iints/live_patient/medtronic_direct.py +365 -0
  24. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/pico_pump.py +65 -0
  25. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/mdmp/__init__.py +12 -0
  26. iints_sdk_python35-1.5.9/src/iints/mdmp/eu_ai_pact.py +168 -0
  27. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/evidence_sources.yaml +8 -0
  28. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/__init__.py +12 -0
  29. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/control_eval.py +21 -2
  30. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/local_ai.py +12 -0
  31. iints_sdk_python35-1.5.9/src/iints/research/local_ai_gate.py +247 -0
  32. iints_sdk_python35-1.5.9/src/iints/validation/run_doctor.py +304 -0
  33. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9/src/iints_sdk_python35.egg-info}/PKG-INFO +2 -2
  34. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints_sdk_python35.egg-info/SOURCES.txt +12 -0
  35. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints_sdk_python35.egg-info/requires.txt +1 -1
  36. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/certification.py +3 -0
  37. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/drift.py +4 -3
  38. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_bergman.py +17 -0
  39. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_demo_live.py +12 -2
  40. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_onboarding.py +37 -2
  41. iints_sdk_python35-1.5.9/tests/test_cli_research_workflows.py +246 -0
  42. iints_sdk_python35-1.5.7/src/iints/analysis/reporting.py +0 -365
  43. iints_sdk_python35-1.5.7/src/iints/data/datasets.json +0 -189
  44. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/LICENSE +0 -0
  45. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/LICENSE-MIT-IINTS-LEGACY +0 -0
  46. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/NOTICE +0 -0
  47. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/README.md +0 -0
  48. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/setup.cfg +0 -0
  49. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/__init__.py +0 -0
  50. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/assistant.py +0 -0
  51. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/backends/__init__.py +0 -0
  52. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/backends/base.py +0 -0
  53. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/backends/mistral_api.py +0 -0
  54. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/backends/ollama.py +0 -0
  55. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/cli.py +0 -0
  56. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/mdmp_guard.py +0 -0
  57. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/model_catalog.py +0 -0
  58. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/prepare.py +0 -0
  59. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/ai/prompts.py +0 -0
  60. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/algorithm_xray.py +0 -0
  61. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/baseline.py +0 -0
  62. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/booth_demo.py +0 -0
  63. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/carelink_workbench.py +0 -0
  64. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/clinical_benchmark.py +0 -0
  65. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/clinical_metrics.py +0 -0
  66. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/clinical_tir_analyzer.py +0 -0
  67. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/diabetes_metrics.py +0 -0
  68. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/edge_efficiency.py +0 -0
  69. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/edge_performance_monitor.py +0 -0
  70. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/eucys_results.py +0 -0
  71. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/explainability.py +0 -0
  72. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/explainable_ai.py +0 -0
  73. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/hardware_benchmark.py +0 -0
  74. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/metrics.py +0 -0
  75. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/population_report.py +0 -0
  76. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/poster.py +0 -0
  77. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/safety_index.py +0 -0
  78. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/sensor_filtering.py +0 -0
  79. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/study_analysis.py +0 -0
  80. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/study_engine.py +0 -0
  81. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/study_experiment.py +0 -0
  82. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/study_poster.py +0 -0
  83. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/study_protocol.py +0 -0
  84. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/analysis/validator.py +0 -0
  85. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/api/__init__.py +0 -0
  86. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/api/base_algorithm.py +0 -0
  87. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/api/registry.py +0 -0
  88. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/api/template_algorithm.py +0 -0
  89. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/assets/iints_logo.png +0 -0
  90. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/cli/__init__.py +0 -0
  91. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/cli/patient_cli.py +0 -0
  92. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/__init__.py +0 -0
  93. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/__init__.py +0 -0
  94. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/battle_runner.py +0 -0
  95. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/clinical_baseline.py +0 -0
  96. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/correction_bolus.py +0 -0
  97. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/discovery.py +0 -0
  98. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/fixed_basal_bolus.py +0 -0
  99. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/hybrid_algorithm.py +0 -0
  100. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/imitation_controller.py +0 -0
  101. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/lstm_algorithm.py +0 -0
  102. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/mock_algorithms.py +0 -0
  103. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/neural_controller.py +0 -0
  104. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/pid_controller.py +0 -0
  105. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/algorithms/standard_pump_algo.py +0 -0
  106. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/device.py +0 -0
  107. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/device_manager.py +0 -0
  108. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/devices/__init__.py +0 -0
  109. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/devices/models.py +0 -0
  110. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/patient/__init__.py +0 -0
  111. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/patient/models.py +0 -0
  112. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/patient/patient_factory.py +0 -0
  113. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/patient/profile.py +0 -0
  114. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/physiology_variation.py +0 -0
  115. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/safety/__init__.py +0 -0
  116. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/safety/config.py +0 -0
  117. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/safety/input_validator.py +0 -0
  118. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/safety/supervisor.py +0 -0
  119. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/simulation/__init__.py +0 -0
  120. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/simulation/scenario_parser.py +0 -0
  121. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/simulator.py +0 -0
  122. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/core/supervisor.py +0 -0
  123. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/adapter.py +0 -0
  124. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/certify.py +0 -0
  125. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/column_mapper.py +0 -0
  126. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/contracts.py +0 -0
  127. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/demo/__init__.py +0 -0
  128. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/demo/demo_cgm.csv +0 -0
  129. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/guardians.py +0 -0
  130. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/importer.py +0 -0
  131. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/ingestor.py +0 -0
  132. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/mdmp_visualizer.py +0 -0
  133. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/nightscout.py +0 -0
  134. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/physiology_residual_profiles.json +0 -0
  135. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/quality_checker.py +0 -0
  136. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/realism_dashboard.py +0 -0
  137. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/realism_reference.py +0 -0
  138. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/realism_references.json +0 -0
  139. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/registry.py +0 -0
  140. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/runner.py +0 -0
  141. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/study_corruption.py +0 -0
  142. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/synthetic_mirror.py +0 -0
  143. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/tidepool.py +0 -0
  144. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/universal_parser.py +0 -0
  145. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_baseline.yaml +0 -0
  146. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_hyper_challenge.yaml +0 -0
  147. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_hypo_prone.yaml +0 -0
  148. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_midnight.yaml +0 -0
  149. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_pizza.yaml +0 -0
  150. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/clinic_safe_stress_meal.yaml +0 -0
  151. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/default_patient.yaml +0 -0
  152. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/data/virtual_patients/patient_559_config.yaml +0 -0
  153. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/demo_assets.py +0 -0
  154. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/emulation/__init__.py +0 -0
  155. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/emulation/legacy_base.py +0 -0
  156. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/emulation/medtronic_780g.py +0 -0
  157. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/emulation/omnipod_5.py +0 -0
  158. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/emulation/tandem_controliq.py +0 -0
  159. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/jetson/__init__.py +0 -0
  160. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/jetson/endurance.py +0 -0
  161. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/jetson/research_pipeline.py +0 -0
  162. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/learning/__init__.py +0 -0
  163. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/learning/autonomous_optimizer.py +0 -0
  164. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/learning/learning_system.py +0 -0
  165. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/api.py +0 -0
  166. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/daemon.py +0 -0
  167. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/edge_benchmark.py +0 -0
  168. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/edge_ops.py +0 -0
  169. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/long_study.py +0 -0
  170. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/runtime.py +0 -0
  171. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/service_export.py +0 -0
  172. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/live_patient/uno_q.py +0 -0
  173. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/mdmp/backend.py +0 -0
  174. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/metrics.py +0 -0
  175. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/population/__init__.py +0 -0
  176. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/population/generator.py +0 -0
  177. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/population/runner.py +0 -0
  178. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/__init__.py +0 -0
  179. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/forecast_calibration_profiles.yaml +0 -0
  180. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/golden_benchmark.yaml +0 -0
  181. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/presets.json +0 -0
  182. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/safety_contract_default.yaml +0 -0
  183. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/presets/validation_profiles.yaml +0 -0
  184. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/audit.py +0 -0
  185. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/calibration_gate.py +0 -0
  186. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/config.py +0 -0
  187. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/control.py +0 -0
  188. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/data_blend.py +0 -0
  189. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/dataset.py +0 -0
  190. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/evaluation.py +0 -0
  191. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/losses.py +0 -0
  192. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/metrics.py +0 -0
  193. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/model_registry.py +0 -0
  194. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/neural_control.py +0 -0
  195. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/research/predictor.py +0 -0
  196. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/scenarios/__init__.py +0 -0
  197. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/scenarios/generator.py +0 -0
  198. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/scenarios/study_pack.py +0 -0
  199. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/__init__.py +0 -0
  200. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/default_algorithm.py +0 -0
  201. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/demos/__init__.py +0 -0
  202. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/demos/live_stage_demo.py +0 -0
  203. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/pico_pump/README.md +0 -0
  204. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/pico_pump/code.py +0 -0
  205. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/pico_pump/serial_protocol.txt +0 -0
  206. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/scenarios/__init__.py +0 -0
  207. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/scenarios/chaos_insulin_stacking.json +0 -0
  208. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/scenarios/chaos_runaway_ai.json +0 -0
  209. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/scenarios/example_scenario.json +0 -0
  210. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/scenarios/exercise_stress.json +0 -0
  211. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/uno_q/README.md +0 -0
  212. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/templates/uno_q/iints_supervisor_bridge.ino +0 -0
  213. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/utils/__init__.py +0 -0
  214. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/utils/csv_safety.py +0 -0
  215. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/utils/plotting.py +0 -0
  216. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/utils/run_io.py +0 -0
  217. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/utils/url_safety.py +0 -0
  218. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/__init__.py +0 -0
  219. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/golden.py +0 -0
  220. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/replay.py +0 -0
  221. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/run_validation.py +0 -0
  222. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/safety_contract.py +0 -0
  223. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/validation/schemas.py +0 -0
  224. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/visualization/__init__.py +0 -0
  225. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/visualization/cockpit.py +0 -0
  226. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints/visualization/uncertainty_cloud.py +0 -0
  227. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints_sdk_python35.egg-info/dependency_links.txt +0 -0
  228. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints_sdk_python35.egg-info/entry_points.txt +0 -0
  229. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/iints_sdk_python35.egg-info/top_level.txt +0 -0
  230. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_ai/__init__.py +0 -0
  231. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_ai/lineage.py +0 -0
  232. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/__init__.py +0 -0
  233. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/audit.py +0 -0
  234. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/bias_hooks.py +0 -0
  235. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/bundle.py +0 -0
  236. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/cli.py +0 -0
  237. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/compare.py +0 -0
  238. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/conformance.py +0 -0
  239. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/contracts.py +0 -0
  240. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/crypto.py +0 -0
  241. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/data/conformance/vectors/delegation.json +0 -0
  242. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/data/conformance/vectors/fingerprint.json +0 -0
  243. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/data/conformance/vectors/grading.json +0 -0
  244. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/data/conformance/vectors/signing.json +0 -0
  245. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/delegate.py +0 -0
  246. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/diffing.py +0 -0
  247. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/exceptions.py +0 -0
  248. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/fingerprint.py +0 -0
  249. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/fingerprint_store.py +0 -0
  250. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/hf.py +0 -0
  251. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/keys/mdmp_pub_v1.pem +0 -0
  252. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/llm_provenance.py +0 -0
  253. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/migrate.py +0 -0
  254. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/policy.py +0 -0
  255. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/prov.py +0 -0
  256. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/registry.py +0 -0
  257. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/runner.py +0 -0
  258. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/schema_export.py +0 -0
  259. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/synthetic.py +0 -0
  260. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/trust.py +0 -0
  261. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_core/visualizer.py +0 -0
  262. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_flavors/__init__.py +0 -0
  263. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_integrations/__init__.py +0 -0
  264. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_integrations/dvc.py +0 -0
  265. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_integrations/mlflow.py +0 -0
  266. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/src/mdmp_integrations/wandb.py +0 -0
  267. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_ci_governance.py +0 -0
  268. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_algorithm_loading.py +0 -0
  269. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_booth_demo.py +0 -0
  270. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_carelink_workbench.py +0 -0
  271. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_cloud_import_security.py +0 -0
  272. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_demo_export.py +0 -0
  273. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_edge_runtime.py +0 -0
  274. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_expo_tools.py +0 -0
  275. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_patient_runtime.py +0 -0
  276. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_poster.py +0 -0
  277. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_cli_run_summary.py +0 -0
  278. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_install_doctor.py +0 -0
  279. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_jetson_endurance.py +0 -0
  280. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_physiology_variation.py +0 -0
  281. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_plugin_system.py +0 -0
  282. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_population.py +0 -0
  283. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_presets_realism.py +0 -0
  284. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_research_realism_tools.py +0 -0
  285. {iints_sdk_python35-1.5.7 → iints_sdk_python35-1.5.9}/tests/test_simulator_calibration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iints-sdk-python35
3
- Version: 1.5.7
3
+ Version: 1.5.9
4
4
  Summary: A pre-clinical Edge-AI SDK for diabetes management validation.
5
5
  Author-email: Rune Bobbaers <rune.bobbaers@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -18,7 +18,7 @@ Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  License-File: NOTICE
20
20
  License-File: LICENSE-MIT-IINTS-LEGACY
21
- Requires-Dist: fastapi<1.0.0,>=0.115.0
21
+ Requires-Dist: fastapi<0.136.4,>=0.115.0
22
22
  Requires-Dist: numpy<3.0.0,>=1.24.0
23
23
  Requires-Dist: pandas<3.0.0,>=2.0.0
24
24
  Requires-Dist: pydantic<3.0.0,>=2.0.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iints-sdk-python35"
7
- version = "1.5.7"
7
+ version = "1.5.9"
8
8
  authors = [
9
9
  { name="Rune Bobbaers", email="rune.bobbaers@gmail.com" },
10
10
  ]
@@ -24,7 +24,7 @@ classifiers = [
24
24
  "Development Status :: 5 - Production/Stable",
25
25
  ]
26
26
  dependencies = [
27
- "fastapi>=0.115.0,<1.0.0",
27
+ "fastapi>=0.115.0,<0.136.4",
28
28
  "numpy>=1.24.0,<3.0.0",
29
29
  "pandas>=2.0.0,<3.0.0",
30
30
  "pydantic>=2.0.0,<3.0.0",
@@ -119,3 +119,8 @@ mdmp_core = [
119
119
  "keys/*.pem",
120
120
  "data/conformance/vectors/*.json",
121
121
  ]
122
+
123
+ [tool.coverage.run]
124
+ omit = [
125
+ "src/iints/templates/default_algorithm.py",
126
+ ]
@@ -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.7"
14
+ __version__ = "1.5.9"
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.
@@ -211,6 +211,46 @@ def generate_demo_report(
211
211
  title="IINTS-AF Demo Report",
212
212
  )
213
213
 
214
+ def generate_agp_report(
215
+ simulation_results: 'pd.DataFrame',
216
+ output_path: Optional[str] = None,
217
+ safety_report: Optional[dict] = None,
218
+ subject_name: str = "Research simulation",
219
+ summary_json_path: Optional[str] = None,
220
+ ) -> Optional[str]:
221
+ """
222
+ Generate an AGP-style research PDF report from dense CGM/simulation data.
223
+ """
224
+ if output_path is None:
225
+ return None
226
+ generator = ClinicalReportGenerator()
227
+ return generator.generate_agp_pdf(
228
+ simulation_results,
229
+ output_path,
230
+ subject_name=subject_name,
231
+ safety_report=safety_report or {},
232
+ summary_json_path=summary_json_path,
233
+ )
234
+
235
+ def generate_agp_assets(
236
+ simulation_results: 'pd.DataFrame',
237
+ output_dir: Optional[str] = None,
238
+ subject_name: str = "Research simulation",
239
+ summary_json_path: Optional[str] = None,
240
+ ) -> Optional[dict]:
241
+ """
242
+ Export AGP-style PNG assets and summary JSON from dense CGM/simulation data.
243
+ """
244
+ if output_dir is None:
245
+ return None
246
+ generator = ClinicalReportGenerator()
247
+ return generator.export_agp_assets(
248
+ simulation_results,
249
+ output_dir,
250
+ subject_name=subject_name,
251
+ summary_json_path=summary_json_path,
252
+ )
253
+
214
254
  # You can also define __all__ to explicitly control what gets imported with `from iints import *`
215
255
  __all__ = [
216
256
  # API
@@ -287,6 +327,8 @@ __all__ = [
287
327
  "generate_report",
288
328
  "generate_quickstart_report",
289
329
  "generate_demo_report",
330
+ "generate_agp_report",
331
+ "generate_agp_assets",
290
332
  "generate_results_poster",
291
333
  # High-level API
292
334
  "run_simulation",
@@ -40,6 +40,7 @@ from .eucys_results import (
40
40
  generate_eucys_main_figure,
41
41
  generate_eucys_results_bundle,
42
42
  )
43
+ from .evidence_bundle import EVIDENCE_SCOPE, build_evidence_bundle
43
44
 
44
45
 
45
46
  def _missing_reports_dependency(feature: str, exc: Exception) -> None:
@@ -100,9 +101,11 @@ __all__ = [
100
101
  "analyze_study_directory",
101
102
  "build_booth_demo",
102
103
  "build_carelink_workbench",
104
+ "build_evidence_bundle",
103
105
  "ClinicalMetricsCalculator",
104
106
  "ClinicalMetricsResult",
105
107
  "ClinicalReportGenerator",
108
+ "EVIDENCE_SCOPE",
106
109
  "compute_metrics",
107
110
  "compare_studies",
108
111
  "build_eucys_abstract_draft_markdown",
@@ -0,0 +1,328 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from datetime import datetime, timezone
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Iterable, List, Optional
7
+ import json
8
+ import shutil
9
+
10
+ import pandas as pd
11
+
12
+ from iints.utils.run_io import compute_sha256
13
+
14
+
15
+ EVIDENCE_SCOPE = (
16
+ "Research and education only. This bundle is not clinical evidence, "
17
+ "not a medical-device submission, and not dosing advice."
18
+ )
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class EvidenceRun:
23
+ label: str
24
+ source_dir: Path
25
+ bundle_dir: Path
26
+ artifacts: Dict[str, str] = field(default_factory=dict)
27
+ metrics: Dict[str, Any] = field(default_factory=dict)
28
+ warnings: List[str] = field(default_factory=list)
29
+
30
+ def to_dict(self) -> Dict[str, Any]:
31
+ return {
32
+ "label": self.label,
33
+ "source_dir": str(self.source_dir),
34
+ "bundle_dir": str(self.bundle_dir),
35
+ "artifacts": self.artifacts,
36
+ "metrics": self.metrics,
37
+ "warnings": self.warnings,
38
+ }
39
+
40
+
41
+ def _safe_slug(value: str) -> str:
42
+ slug = "".join(ch.lower() if ch.isalnum() else "_" for ch in value.strip())
43
+ slug = "_".join(part for part in slug.split("_") if part)
44
+ return slug or "run"
45
+
46
+
47
+ def _read_json(path: Path) -> Dict[str, Any]:
48
+ try:
49
+ payload = json.loads(path.read_text(encoding="utf-8"))
50
+ except Exception:
51
+ return {}
52
+ return payload if isinstance(payload, dict) else {}
53
+
54
+
55
+ def _copy_if_exists(source: Path, target_dir: Path, name: Optional[str] = None) -> Optional[Path]:
56
+ if not source.is_file():
57
+ return None
58
+ target_dir.mkdir(parents=True, exist_ok=True)
59
+ target = target_dir / (name or source.name)
60
+ shutil.copy2(source, target)
61
+ return target
62
+
63
+
64
+ def _find_first(root: Path, names: Iterable[str]) -> Optional[Path]:
65
+ for name in names:
66
+ candidate = root / name
67
+ if candidate.is_file():
68
+ return candidate
69
+ for name in names:
70
+ matches = sorted(root.glob(f"**/{name}"))
71
+ if matches:
72
+ return matches[0]
73
+ return None
74
+
75
+
76
+ def _glucose_metrics(results_csv: Optional[Path]) -> Dict[str, Any]:
77
+ if results_csv is None or not results_csv.is_file():
78
+ return {}
79
+ try:
80
+ df = pd.read_csv(results_csv)
81
+ except Exception:
82
+ return {}
83
+ glucose_column = None
84
+ for candidate in ("glucose_actual_mgdl", "glucose", "glucose_mgdl", "current_glucose"):
85
+ if candidate in df.columns:
86
+ glucose_column = candidate
87
+ break
88
+ if glucose_column is None or df.empty:
89
+ return {"rows": int(len(df))}
90
+ glucose = pd.to_numeric(df[glucose_column], errors="coerce").dropna()
91
+ if glucose.empty:
92
+ return {"rows": int(len(df))}
93
+ time_column = "time_minutes" if "time_minutes" in df.columns else "timestamp" if "timestamp" in df.columns else None
94
+ duration_minutes = None
95
+ if time_column is not None:
96
+ time_values = pd.to_numeric(df[time_column], errors="coerce").dropna()
97
+ if not time_values.empty:
98
+ duration_minutes = float(time_values.max() - time_values.min())
99
+ return {
100
+ "rows": int(len(df)),
101
+ "duration_minutes": duration_minutes,
102
+ "mean_glucose_mgdl": round(float(glucose.mean()), 3),
103
+ "min_glucose_mgdl": round(float(glucose.min()), 3),
104
+ "max_glucose_mgdl": round(float(glucose.max()), 3),
105
+ "tir_70_180_pct": round(float(((glucose >= 70) & (glucose <= 180)).mean() * 100.0), 3),
106
+ "tir_below_70_pct": round(float((glucose < 70).mean() * 100.0), 3),
107
+ "tir_below_54_pct": round(float((glucose < 54).mean() * 100.0), 3),
108
+ }
109
+
110
+
111
+ def _bundle_one_run(label: str, run_dir: Path, output_runs_dir: Path) -> EvidenceRun:
112
+ source = run_dir.expanduser().resolve()
113
+ warnings: list[str] = []
114
+ run_target = output_runs_dir / _safe_slug(label)
115
+ artifacts_dir = run_target / "artifacts"
116
+ run_target.mkdir(parents=True, exist_ok=True)
117
+
118
+ results_csv = _find_first(source, ("results.csv", "sim_results.csv"))
119
+ summary_json = _find_first(source, ("summary.json", "demo_summary.json", "run_summary.json"))
120
+ manifest_json = _find_first(source, ("run_manifest.json", "manifest.json"))
121
+ safety_json = _find_first(source, ("safety_report.json", "safety.json"))
122
+ report_pdf = _find_first(source, ("report.pdf", "clinical_report.pdf", "research_report.pdf"))
123
+
124
+ artifacts: dict[str, str] = {}
125
+ for key, path in {
126
+ "results_csv": results_csv,
127
+ "summary_json": summary_json,
128
+ "run_manifest_json": manifest_json,
129
+ "safety_report_json": safety_json,
130
+ "report_pdf": report_pdf,
131
+ }.items():
132
+ if path is None:
133
+ continue
134
+ copied = _copy_if_exists(path, artifacts_dir)
135
+ if copied is not None:
136
+ artifacts[key] = str(copied)
137
+ artifacts[f"{key}_sha256"] = compute_sha256(copied)
138
+
139
+ if results_csv is None:
140
+ warnings.append("No results.csv-style file found; metrics are limited.")
141
+ if manifest_json is None:
142
+ warnings.append("No run manifest found; reproducibility evidence is incomplete.")
143
+ if safety_json is None:
144
+ warnings.append("No safety report found; safety evidence is incomplete.")
145
+
146
+ metrics = _glucose_metrics(results_csv)
147
+ if safety_json is not None:
148
+ safety_payload = _read_json(safety_json)
149
+ for key in ("terminated_early", "critical_events", "supervisor_interventions"):
150
+ if key in safety_payload:
151
+ metrics[key] = safety_payload[key]
152
+ if summary_json is not None:
153
+ summary_payload = _read_json(summary_json)
154
+ for key in ("status", "completion_ratio", "completed_duration_minutes", "requested_duration_minutes"):
155
+ if key in summary_payload:
156
+ metrics[key] = summary_payload[key]
157
+
158
+ run_card = {
159
+ "label": label,
160
+ "source_dir": str(source),
161
+ "artifacts": artifacts,
162
+ "metrics": metrics,
163
+ "warnings": warnings,
164
+ "scope": EVIDENCE_SCOPE,
165
+ }
166
+ (run_target / "RUN_CARD.json").write_text(json.dumps(run_card, indent=2), encoding="utf-8")
167
+ return EvidenceRun(label=label, source_dir=source, bundle_dir=run_target, artifacts=artifacts, metrics=metrics, warnings=warnings)
168
+
169
+
170
+ def _load_optional_json(root: Optional[Path], names: Iterable[str]) -> Dict[str, Any]:
171
+ if root is None:
172
+ return {}
173
+ path = _find_first(root.expanduser().resolve(), names)
174
+ return _read_json(path) if path is not None else {}
175
+
176
+
177
+ def _write_markdown(path: Path, title: str, payload: Dict[str, Any]) -> None:
178
+ lines = [
179
+ f"# {title}",
180
+ "",
181
+ EVIDENCE_SCOPE,
182
+ "",
183
+ "## Summary",
184
+ "",
185
+ f"- Created UTC: `{payload['created_utc']}`",
186
+ f"- Runs: `{len(payload['runs'])}`",
187
+ f"- Local AI evidence: `{'yes' if payload.get('local_ai') else 'no'}`",
188
+ f"- Pump bench evidence: `{'yes' if payload.get('pump_bench') else 'no'}`",
189
+ "",
190
+ "## Runs",
191
+ "",
192
+ ]
193
+ if not payload["runs"]:
194
+ lines.append("No simulation runs were attached.")
195
+ lines.append("")
196
+ for run in payload["runs"]:
197
+ metrics = run.get("metrics", {})
198
+ lines.extend(
199
+ [
200
+ f"### {run['label']}",
201
+ "",
202
+ f"- Source: `{run['source_dir']}`",
203
+ f"- Bundle: `{run['bundle_dir']}`",
204
+ f"- Rows: `{metrics.get('rows', 'n/a')}`",
205
+ f"- Mean glucose: `{metrics.get('mean_glucose_mgdl', 'n/a')}` mg/dL",
206
+ f"- TIR 70-180: `{metrics.get('tir_70_180_pct', 'n/a')}`%",
207
+ f"- Time <70: `{metrics.get('tir_below_70_pct', 'n/a')}`%",
208
+ f"- Time <54: `{metrics.get('tir_below_54_pct', 'n/a')}`%",
209
+ "",
210
+ ]
211
+ )
212
+ for warning in run.get("warnings", []):
213
+ lines.append(f"- Warning: {warning}")
214
+ if run.get("warnings"):
215
+ lines.append("")
216
+ lines.extend(
217
+ [
218
+ "## Required Interpretation",
219
+ "",
220
+ "- Use this as reproducibility and engineering evidence.",
221
+ "- Do not present this as clinical performance evidence.",
222
+ "- Keep local AI and pump exports behind deterministic safety gates.",
223
+ "",
224
+ ]
225
+ )
226
+ path.write_text("\n".join(lines), encoding="utf-8")
227
+
228
+
229
+ def _write_model_card(path: Path, payload: Dict[str, Any]) -> None:
230
+ local_ai = payload.get("local_ai") or {}
231
+ gate = local_ai.get("training_safety_gate") or local_ai.get("closed_loop_evaluation", {}).get("safety_gate") or {}
232
+ lines = [
233
+ "# IINTS Research Model Card",
234
+ "",
235
+ EVIDENCE_SCOPE,
236
+ "",
237
+ "## Intended Use",
238
+ "",
239
+ "Local AI models generated by IINTS are for simulator research, reproducibility studies, and bench-only demonstrations.",
240
+ "",
241
+ "## Not Intended For",
242
+ "",
243
+ "- real insulin delivery",
244
+ "- diagnosis or treatment",
245
+ "- autonomous therapy without certified medical-device controls",
246
+ "",
247
+ "## Evidence Inputs",
248
+ "",
249
+ f"- Attached runs: `{len(payload['runs'])}`",
250
+ f"- Local AI summary present: `{'yes' if local_ai else 'no'}`",
251
+ "",
252
+ "## Safety Gate",
253
+ "",
254
+ f"- Status: `{gate.get('status', 'not_available')}`",
255
+ f"- Passed: `{gate.get('passed', 'not_available')}`",
256
+ f"- Score: `{gate.get('score', 'not_available')}`",
257
+ "",
258
+ ]
259
+ if gate.get("critical_failures"):
260
+ lines.extend(["### Critical Failures", ""])
261
+ lines.extend(f"- {item}" for item in gate["critical_failures"])
262
+ lines.append("")
263
+ lines.extend(
264
+ [
265
+ "## Promotion Rule",
266
+ "",
267
+ "A model can only move toward hardware bench testing after realism checks, closed-loop evaluation, MDMP/evidence review, and deterministic supervisor gates pass.",
268
+ "",
269
+ ]
270
+ )
271
+ path.write_text("\n".join(lines), encoding="utf-8")
272
+
273
+
274
+ def build_evidence_bundle(
275
+ run_dirs: Iterable[tuple[str, Path]],
276
+ *,
277
+ output_dir: Path,
278
+ title: str = "IINTS Research Evidence Bundle",
279
+ local_ai_dir: Optional[Path] = None,
280
+ pump_bundle_dir: Optional[Path] = None,
281
+ ) -> Dict[str, Any]:
282
+ """Create a compact evidence pack for demos, reviews, and EUCYS-style explanation."""
283
+
284
+ root = output_dir.expanduser().resolve()
285
+ runs_dir = root / "runs"
286
+ root.mkdir(parents=True, exist_ok=True)
287
+
288
+ runs = [_bundle_one_run(label, Path(run_dir), runs_dir).to_dict() for label, run_dir in run_dirs]
289
+ local_ai = _load_optional_json(local_ai_dir, ("LOCAL_AI_RESEARCH_SUMMARY.json", "summary.json"))
290
+ pump_bench = _load_optional_json(pump_bundle_dir, ("manifest.json", "iints_pump_manifest.json"))
291
+
292
+ payload: Dict[str, Any] = {
293
+ "title": title,
294
+ "created_utc": datetime.now(timezone.utc).isoformat(),
295
+ "scope": EVIDENCE_SCOPE,
296
+ "runs": runs,
297
+ "local_ai": local_ai,
298
+ "pump_bench": pump_bench,
299
+ "artifacts": {
300
+ "summary_json": str(root / "evidence_summary.json"),
301
+ "readme_md": str(root / "README.md"),
302
+ "model_card_md": str(root / "MODEL_CARD.md"),
303
+ "run_index_csv": str(root / "run_index.csv"),
304
+ },
305
+ }
306
+
307
+ (root / "evidence_summary.json").write_text(json.dumps(payload, indent=2), encoding="utf-8")
308
+ _write_markdown(root / "README.md", title, payload)
309
+ _write_model_card(root / "MODEL_CARD.md", payload)
310
+
311
+ rows = []
312
+ for run in runs:
313
+ metrics = run.get("metrics", {})
314
+ rows.append(
315
+ {
316
+ "label": run["label"],
317
+ "source_dir": run["source_dir"],
318
+ "bundle_dir": run["bundle_dir"],
319
+ "rows": metrics.get("rows"),
320
+ "mean_glucose_mgdl": metrics.get("mean_glucose_mgdl"),
321
+ "tir_70_180_pct": metrics.get("tir_70_180_pct"),
322
+ "tir_below_70_pct": metrics.get("tir_below_70_pct"),
323
+ "tir_below_54_pct": metrics.get("tir_below_54_pct"),
324
+ "warnings": "; ".join(run.get("warnings", [])),
325
+ }
326
+ )
327
+ pd.DataFrame(rows).to_csv(root / "run_index.csv", index=False)
328
+ return payload