feat: Enhance context generation with new table images for VO2 Max and Heart Rate Zones

- Added functionality to generate VO2 Max and Heart Rate Zones tables in the context_generator.py.
- Integrated graph_generator to create table images with specified data and styles.
- Updated report_generator.py to pass graph_generator to context generation.
- Introduced a new method in graph_generator.py to generate table images with customizable options.
- Created test scripts for Page 5 (RMR and NEAT calculations) and Page 6 (Meal Plan calculations) using actual patient data.
- Updated Jupyter notebook metadata for better environment identification.
This commit is contained in:
bolade
2025-11-21 11:38:43 +01:00
parent 9d51b006c0
commit 47f0c6f3fb
8 changed files with 825 additions and 294 deletions
+157 -1
View File
@@ -6,7 +6,7 @@ of the medical report. It performs analysis on Pnoe, Spirometry, and SECA data.
"""
from datetime import datetime
from typing import Dict, Optional, Tuple
from typing import Any, Dict, Optional, Tuple
import pandas as pd
@@ -626,6 +626,7 @@ class ContextGenerator:
patient_name: str,
graphs: Dict[str, str],
metric_overrides: Optional[Dict] = None,
graph_generator: Optional[Any] = None,
) -> Dict[str, Dict]:
"""Main method to generate all page contexts
@@ -720,6 +721,127 @@ class ContextGenerator:
"vo2_pulse_chart": graphs.get("vo2_pulse", ""),
}
if graph_generator:
# VO2 Max Table
vo2_max_columns = [
"Age (F)",
"Very Poor",
"Poor",
"Fair",
"Good",
"Excellent",
"Superior",
]
vo2_max_data = [
[
contexts["page_8"]["age_range"],
"19.0-24.1",
"24.1-28.2",
"28.2-32.2",
"32.2-35.7",
"35.7-45.8",
"45.8+",
]
]
vo2_max_colors = [
[
"#b2ebf2",
"#f5f5f5",
"#f5f5f5",
"#f5f5f5",
"#f5f5f5",
"#f5f5f5",
"#f5f5f5",
]
]
contexts["page_8"]["vo2_max_table"] = graph_generator.generate_table_image(
data=vo2_max_data,
columns=vo2_max_columns,
cell_colors=vo2_max_colors,
header_color="#4dd0e1",
save_as_base64=True,
)
# Heart Rate Zones Table
hr_zones_columns = ["Zone 1", "Zone 2", "Zone 3", "Zone 4", "Zone 5"]
hr_zones_data = [
[
"Improves health and recovery capacity",
"Improves endurance and fat burning",
"Improves Aerobic fitness",
"Improves maximum performance capacity",
"Develops maximum performance and speed",
],
[
"55-65% of Max Heart Rate",
"65-75% of Max Heart Rate",
"80-85% of Max Heart Rate",
"85-88% of Max Heart Rate",
"90% of Max Heart Rate",
],
[
pnoe_metrics.get("zone1_bpm", "81-96bpm"),
pnoe_metrics.get("zone2_bpm", "96-100bpm"),
pnoe_metrics.get("zone3_bpm", "100-178bpm"),
pnoe_metrics.get("zone4_bpm", "178-188bpm"),
pnoe_metrics.get("zone5_bpm", "188-198bpm"),
],
[
"3.5mph\n2% Incline",
"3.5-4.0mph\n2% Incline",
"4.0-6.5mph\n2% Incline",
"6.5-7.0mph\n2% Incline",
"7.0-8.0mph\n2% Incline",
],
[
"10:39min/km Pace",
"10:39-9:19min/km Pace",
"9:19-5:44min/km Pace",
"5:44-5:20min/km Pace",
"5:20-4:40min/km Pace",
],
[
"Avg:\n4.4kcals/minute",
"Avg:\n5.9kcals/minute",
"Avg:\n9.4kcals/minute",
"Avg:\n12.5kcals/minute",
"Avg:\n12.8kcals/minute",
],
[
"Avg: 0.4g/min\nCarb Utilization",
"Avg: 0.6g/min\nCarb Utilization",
"Avg: 1.9g/min\nCarb Utilization",
"Avg: 2.9g/min\nCarb Utilization",
"Avg: 3.1g/min\nCarb Utilization",
],
[
"Avg: 27 breaths\nIdeal: 15-20",
"Avg: 28 breaths\nIdeal: 20-25",
"Avg: 31 breaths\nIdeal: 25-30",
"Avg: 42 breaths\nIdeal: 30-35",
"Avg: 51 breaths\nIdeal: 40+",
],
]
hr_zones_colors = [
["#ffffff"] * 5,
["#ffffff"] * 5,
["#ffcdd2", "#ffcdd2", "#fff9c4", "#c8e6c9", "#c8e6c9"],
["#ffffff"] * 5,
["#ffffff"] * 5,
["#ffffff"] * 5,
["#ffffff"] * 5,
["#ffcdd2", "#ffcdd2", "#fff9c4", "#c8e6c9", "#c8e6c9"],
]
contexts["page_8"]["hr_zones_table"] = graph_generator.generate_table_image(
data=hr_zones_data,
columns=hr_zones_columns,
cell_colors=hr_zones_colors,
header_color="#4dd0e1",
save_as_base64=True,
)
# Page 9
contexts["page_9"] = {
"fat_max_value": f"{pnoe_metrics['fat_max_value']:.2f}",
@@ -752,6 +874,40 @@ class ContextGenerator:
**resting_hr_metrics,
}
if graph_generator:
# Page 11 Resting Heart Rate Table
rhr_columns = [
"Age (F)",
"Poor",
"Below Average",
"Average",
"Above Average",
"Good",
"Excellent",
"Athlete",
]
rhr_data = [
[
contexts["page_11"]["hr_age_range"],
contexts["page_11"]["hr_poor"],
contexts["page_11"]["hr_below_avg"],
contexts["page_11"]["hr_average"],
contexts["page_11"]["hr_above_avg"],
contexts["page_11"]["hr_good"],
contexts["page_11"]["hr_excellent"],
contexts["page_11"]["hr_athlete"],
]
]
rhr_colors = [["#b2ebf2"] + ["#f5f5f5"] * 7]
contexts["page_11"]["rhr_table"] = graph_generator.generate_table_image(
data=rhr_data,
columns=rhr_columns,
cell_colors=rhr_colors,
header_color="#4dd0e1",
save_as_base64=True,
)
# Pages 12-17
for i in range(6):
contexts[f"page_{i + 12}"] = {