added minimal report
This commit is contained in:
@@ -1112,9 +1112,17 @@ class ContextGenerator:
|
||||
graphs: Dict[str, str],
|
||||
metric_overrides: Optional[Dict] = None,
|
||||
graph_generator: Optional[Any] = None,
|
||||
report_type: str = "full",
|
||||
) -> Dict[str, Dict]:
|
||||
"""Main method to generate all page contexts
|
||||
|
||||
Args:
|
||||
patient_name: Patient name
|
||||
graphs: Dictionary of graph data
|
||||
metric_overrides: Optional metric overrides
|
||||
graph_generator: Optional graph generator instance
|
||||
report_type: Type of report ("full" or "minimal")
|
||||
|
||||
Returns:
|
||||
Dictionary with keys 'page_1', 'page_2', etc., each containing context data for that page
|
||||
"""
|
||||
@@ -1133,60 +1141,156 @@ class ContextGenerator:
|
||||
|
||||
contexts = {}
|
||||
|
||||
# Define which pages to generate based on report type
|
||||
if report_type == "minimal":
|
||||
# Minimal report only needs pages: 1, 2, 4, 5, 6, 16, 17, 19, 20
|
||||
# But we'll generate contexts for all needed pages and combine 19+20
|
||||
pages_to_generate = [1, 2, 4, 5, 6, 16, 17, 19, 20]
|
||||
else:
|
||||
# Full report needs all pages 1-20
|
||||
pages_to_generate = list(range(1, 21))
|
||||
|
||||
# Page 1
|
||||
contexts["page_1"] = {
|
||||
"name": self.patient_info["name"],
|
||||
"surname": self.patient_info["last_name"],
|
||||
"date": datetime.now().strftime("%B %d, %Y"),
|
||||
}
|
||||
|
||||
# Page 2
|
||||
contexts["page_2"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"test_date": datetime.now().strftime("%B %d, %Y"),
|
||||
}
|
||||
|
||||
# Pages 3, 6 (pages 4 and 5 are handled separately)
|
||||
for i in [0, 3]: # Skip indices 1 and 2 which are pages 4 and 5
|
||||
contexts[f"page_{i + 3}"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": i + 3,
|
||||
if 1 in pages_to_generate:
|
||||
contexts["page_1"] = {
|
||||
"name": self.patient_info["name"],
|
||||
"surname": self.patient_info["last_name"],
|
||||
"date": datetime.now().strftime("%B %d, %Y"),
|
||||
}
|
||||
|
||||
# Page 2
|
||||
if 2 in pages_to_generate:
|
||||
contexts["page_2"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"test_date": datetime.now().strftime("%B %d, %Y"),
|
||||
}
|
||||
|
||||
# Pages 3, 6 (pages 4 and 5 are handled separately)
|
||||
if report_type == "full":
|
||||
for i in [0, 3]: # Skip indices 1 and 2 which are pages 4 and 5
|
||||
contexts[f"page_{i + 3}"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": i + 3,
|
||||
}
|
||||
|
||||
# Page 4 - Nutrition Guidelines with Body Composition
|
||||
contexts["page_4"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 4,
|
||||
"fat_percentage": f"{self.patient_info['fat_percentage']:.1f}",
|
||||
"body_composition_chart": graphs.get("body_composition", ""),
|
||||
"body_fat_chart": graphs.get("body_fat_percent", ""), # Alias for template
|
||||
"body_fat_percent_chart": graphs.get(
|
||||
"body_fat_percent", ""
|
||||
), # Keep for consistency
|
||||
}
|
||||
if 4 in pages_to_generate:
|
||||
contexts["page_4"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 4,
|
||||
"fat_percentage": f"{self.patient_info['fat_percentage']:.1f}",
|
||||
"body_composition_chart": graphs.get("body_composition", ""),
|
||||
"body_fat_chart": graphs.get("body_fat_percent", ""), # Alias for template
|
||||
"body_fat_percent_chart": graphs.get(
|
||||
"body_fat_percent", ""
|
||||
), # Keep for consistency
|
||||
}
|
||||
|
||||
# Page 5 - Resting Metabolic Rate Assessment
|
||||
contexts["page_5"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 5,
|
||||
"metabolism_chart": graphs.get("metabolism_chart", ""),
|
||||
"fuel_source_chart": graphs.get("fuel_source_chart", ""),
|
||||
"resting_calories": rmr_metrics.get("resting_calories", 1500),
|
||||
"neat_calories": rmr_metrics.get("neat_calories", 375),
|
||||
"weight_loss_calories": rmr_metrics.get("weight_loss_calories", 500),
|
||||
"weight_loss_rate": rmr_metrics.get("weight_loss_rate", 1.0),
|
||||
"total_calories": rmr_metrics.get("total_calories", 1375),
|
||||
}
|
||||
if 5 in pages_to_generate:
|
||||
contexts["page_5"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 5,
|
||||
"metabolism_chart": graphs.get("metabolism_chart", ""),
|
||||
"fuel_source_chart": graphs.get("fuel_source_chart", ""),
|
||||
"resting_calories": rmr_metrics.get("resting_calories", 1500),
|
||||
"neat_calories": rmr_metrics.get("neat_calories", 375),
|
||||
"weight_loss_calories": rmr_metrics.get("weight_loss_calories", 500),
|
||||
"weight_loss_rate": rmr_metrics.get("weight_loss_rate", 1.0),
|
||||
"total_calories": rmr_metrics.get("total_calories", 1375),
|
||||
}
|
||||
|
||||
# For minimal reports, also generate resting heart rate table for page_5
|
||||
if report_type == "minimal" and graph_generator:
|
||||
resting_hr_metrics = self._calculate_resting_heart_rate_metrics()
|
||||
rhr_table_info = self._calculate_rhr_table_data(
|
||||
self.patient_info["age"], self.patient_info["gender"]
|
||||
)
|
||||
|
||||
# Get resting heart rate value and determine category
|
||||
rhr_value_str = resting_hr_metrics.get("resting_heart_rate", "0bpm")
|
||||
rhr_value = float(rhr_value_str.replace("bpm", "").strip())
|
||||
|
||||
category = self._determine_rhr_category(
|
||||
rhr_value,
|
||||
self.patient_info["age"],
|
||||
self.patient_info["gender"],
|
||||
)
|
||||
|
||||
gender_label = (
|
||||
"F" if self.patient_info["gender"].lower().startswith("f") else "M"
|
||||
)
|
||||
age_range_label = f"{rhr_table_info['age_range']} ({gender_label})"
|
||||
|
||||
rhr_columns = [
|
||||
"Age",
|
||||
"Poor",
|
||||
"Below Average",
|
||||
"Average",
|
||||
"Above Average",
|
||||
"Good",
|
||||
"Excellent",
|
||||
"Athlete",
|
||||
]
|
||||
rhr_data = [
|
||||
[
|
||||
age_range_label,
|
||||
rhr_table_info["ranges"]["Poor"],
|
||||
rhr_table_info["ranges"]["Below Average"],
|
||||
rhr_table_info["ranges"]["Average"],
|
||||
rhr_table_info["ranges"]["Above Average"],
|
||||
rhr_table_info["ranges"]["Good"],
|
||||
rhr_table_info["ranges"]["Excellent"],
|
||||
rhr_table_info["ranges"]["Athlete"],
|
||||
]
|
||||
]
|
||||
|
||||
contexts["page_5"]["rhr_table"] = (
|
||||
graph_generator.generate_resting_heart_rate_table(
|
||||
data=rhr_data,
|
||||
columns=rhr_columns,
|
||||
rhr_value=rhr_value,
|
||||
category=category,
|
||||
save_as_base64=True,
|
||||
)
|
||||
)
|
||||
|
||||
# Calculate FEV1 percentage for page 7
|
||||
fev1_percentage = 0
|
||||
if spirometry_metrics.get("fvc_best"):
|
||||
fev1_percentage = (
|
||||
pnoe_metrics["peak_vt"] / spirometry_metrics["fvc_best"]
|
||||
) * 100
|
||||
# Page 6 - Meal Plan (needed for both full and minimal)
|
||||
if 6 in pages_to_generate:
|
||||
contexts["page_6"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 6,
|
||||
"deficit_calories": rmr_metrics.get("total_calories", 1600),
|
||||
"deficit_protein": f"{int(rmr_metrics.get('total_calories', 1600) * 0.22 / 4)}g Protein",
|
||||
"deficit_carbs": f"{int(rmr_metrics.get('total_calories', 1600) * 0.39 / 4)}g Carbs",
|
||||
"deficit_fat": f"{int(rmr_metrics.get('total_calories', 1600) * 0.39 / 9)}g Fat",
|
||||
"deficit_fiber": "24g Fibre",
|
||||
"refeed_weekday_calories": int(rmr_metrics.get("total_calories", 1600) * 0.85),
|
||||
"refeed_weekday_protein": f"{int(rmr_metrics.get('total_calories', 1600) * 0.85 * 0.22 / 4)}g Protein",
|
||||
"refeed_weekday_carbs": f"{int(rmr_metrics.get('total_calories', 1600) * 0.85 * 0.39 / 4)}g Carbs",
|
||||
"refeed_weekday_fat": f"{int(rmr_metrics.get('total_calories', 1600) * 0.85 * 0.39 / 9)}g Fat",
|
||||
"refeed_weekday_fiber": "20g Fibre",
|
||||
"refeed_weekend_calories": int(rmr_metrics.get("total_calories", 1600) * 1.375),
|
||||
"refeed_weekend_protein": f"{int(rmr_metrics.get('total_calories', 1600) * 1.375 * 0.22 / 4)}g Protein",
|
||||
"refeed_weekend_carbs": f"{int(rmr_metrics.get('total_calories', 1600) * 1.375 * 0.39 / 4)}g Carbs",
|
||||
"refeed_weekend_fat": f"{int(rmr_metrics.get('total_calories', 1600) * 1.375 * 0.39 / 9)}g Fat",
|
||||
"refeed_weekend_fiber": "33g Fibre",
|
||||
"protein_percentage": "22%",
|
||||
"carbs_percentage": "39%",
|
||||
"fats_percentage": "39%",
|
||||
}
|
||||
|
||||
# Page 7
|
||||
contexts["page_7"] = {
|
||||
# Only generate pages 7-15 and 18 for full reports
|
||||
if report_type == "full":
|
||||
# Calculate FEV1 percentage for page 7
|
||||
fev1_percentage = 0
|
||||
if spirometry_metrics.get("fvc_best"):
|
||||
fev1_percentage = (
|
||||
pnoe_metrics["peak_vt"] / spirometry_metrics["fvc_best"]
|
||||
) * 100
|
||||
|
||||
# Page 7
|
||||
contexts["page_7"] = {
|
||||
"peak_vt": f"{pnoe_metrics['peak_vt']:.2f}",
|
||||
"peak_vt_bpm": f"{int(pnoe_metrics['peak_vt_hr'])}",
|
||||
"fev1_percentage": f"{fev1_percentage:.1f}",
|
||||
@@ -1410,32 +1514,60 @@ class ContextGenerator:
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not generate muscle oxygenation chart: {e}")
|
||||
|
||||
# Pages 14-18 (previously 13-17)
|
||||
for i in range(1, 6):
|
||||
page_num = i + 13
|
||||
contexts[f"page_{page_num}"] = {
|
||||
# Pages 14-18 (previously 13-17)
|
||||
for i in range(1, 6):
|
||||
page_num = i + 13
|
||||
contexts[f"page_{page_num}"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": page_num,
|
||||
}
|
||||
# Add next_testing_date to page 16
|
||||
if page_num == 16:
|
||||
contexts["page_16"]["next_testing_date"] = self.patient_info.get(
|
||||
"next_testing_date", "Contact us for scheduling"
|
||||
)
|
||||
|
||||
# Page 16 - Next Steps (needed for both full and minimal)
|
||||
if 16 in pages_to_generate:
|
||||
contexts["page_16"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": page_num,
|
||||
}
|
||||
# Add next_testing_date to page 16
|
||||
if page_num == 16:
|
||||
contexts["page_16"]["next_testing_date"] = self.patient_info.get(
|
||||
"page_number": 16,
|
||||
"next_testing_date": self.patient_info.get(
|
||||
"next_testing_date", "Contact us for scheduling"
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
# Page 19 - Glossary with Body Fat Percentage Master Chart (previously page 18)
|
||||
contexts["page_19"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 19,
|
||||
"body_fat_percentage_chart": graphs.get(
|
||||
"body_fat_percentage_master_chart", ""
|
||||
),
|
||||
}
|
||||
# Page 17 - Glossary (needed for both full and minimal, but minimal uses different template)
|
||||
if 17 in pages_to_generate:
|
||||
contexts["page_17"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 17,
|
||||
}
|
||||
|
||||
# Page 20 (previously page 19)
|
||||
contexts["page_20"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 20,
|
||||
}
|
||||
# Page 19 - Glossary with Body Fat Percentage Master Chart
|
||||
if 19 in pages_to_generate:
|
||||
contexts["page_19"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 19,
|
||||
"body_fat_percentage_chart": graphs.get(
|
||||
"body_fat_percentage_master_chart", ""
|
||||
),
|
||||
}
|
||||
|
||||
# Page 20 - Resting Heart Rate Table
|
||||
if 20 in pages_to_generate:
|
||||
contexts["page_20"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"page_number": 20,
|
||||
}
|
||||
|
||||
# For minimal reports, create combined context for page_19_20_minimal
|
||||
if report_type == "minimal" and 19 in pages_to_generate and 20 in pages_to_generate:
|
||||
contexts["page_19_20_minimal"] = {
|
||||
"patient_name": self.patient_info["name"],
|
||||
"body_fat_percentage_chart": graphs.get(
|
||||
"body_fat_percentage_master_chart", ""
|
||||
),
|
||||
}
|
||||
|
||||
return contexts
|
||||
|
||||
Reference in New Issue
Block a user