feat: Enhance medical report generation with new features and improved data handling

- Added body fat percentage input and optional muscle oxygenation CSV upload in the upload form.
- Implemented TSI chart generation based on muscle oxygenation data.
- Updated report generation to include metabolism and fuel source charts.
- Refactored context generation to eliminate reliance on SECA data, using patient info directly instead.
- Improved error handling and logging for graph generation processes.
- Enhanced HTML templates for better user experience and functionality.
This commit is contained in:
bolade
2025-11-18 16:57:39 +01:00
parent 83f50882e2
commit 7e985c497e
12 changed files with 1256 additions and 262 deletions
+17 -4
View File
@@ -72,7 +72,7 @@
},
{
"cell_type": "code",
"execution_count": 37,
"execution_count": null,
"id": "99116a35",
"metadata": {},
"outputs": [],
@@ -237,7 +237,7 @@
},
{
"cell_type": "code",
"execution_count": 41,
"execution_count": null,
"id": "470e871e",
"metadata": {},
"outputs": [
@@ -290,7 +290,14 @@
" # --- Chart data and positions ---\n",
" categories = ['Very Slow', 'Slow', 'Average', 'Fast', 'Very Fast']\n",
" positions = [1500, 3000, 4500, 6000, 7500]\n",
" kcal_value = 1386\n",
" # Step 1: Filter resting phase (usually lowest VO2 or MET values)\n",
" rest_phase = df[df['MET'] <= 1.1] # assuming <1.1 MET means rest\n",
"\n",
" # Step 2: Compute resting metabolic rate\n",
" rmr = rest_phase['EE(kcal/day)'].mean()\n",
"\n",
" print(f\"Estimated RMR from data: {rmr:.0f} kcal/day\")\n",
" kcal_value = rmr\n",
" # Position the indicator and highlight based on the kcal value\n",
" # For this example, we'll place it in the 'Very Slow' section.\n",
" indicator_pos = kcal_value\n",
@@ -349,7 +356,13 @@
" fig, ax = plt.subplots(figsize=(10, 2.5))\n",
"\n",
" # --- Chart data and positions ---\n",
" fat_percentage = 33\n",
" rest_phase = df[df['RER'] == 0.9] # filter rest data\n",
" fat_rest = rest_phase['FAT(%)'].mean()\n",
" carb_rest = rest_phase['CARBS(%)'].mean()\n",
"\n",
" print(f\"Resting phase fuel mix: Fats {fat_rest:.1f}%, Carbs {carb_rest:.1f}%\")\n",
"\n",
" fat_percentage = fat_rest\n",
" carb_percentage = 100 - fat_percentage\n",
" optimal_point = 75\n",
"\n",
+3 -9
View File
@@ -18,13 +18,12 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": null,
"id": "da5ac3c1",
"metadata": {},
"outputs": [],
"source": [
"pnoe_df = pd.read_csv('data/pnoe_data.csv', delimiter=';')\n",
"patients_info = pd.read_excel('data/patients_data.xlsx')\n",
"spirometry_df = pd.read_csv('data/spirometry_data.csv')"
]
},
@@ -254,7 +253,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"id": "2fa8ff13",
"metadata": {},
"outputs": [
@@ -270,15 +269,10 @@
}
],
"source": [
"def body_composition_chart(first_name='Keirstyn', last_name='Moran'):\n",
"def body_composition_chart(fat_percentage=22.4, weight_kg=70):\n",
"\n",
" \n",
" #=========================== Body Composition Donut Chart ========================#\n",
" patient_data = patients_info[(patients_info['FirstName'].str.contains(first_name, case=False, na=False)) & \n",
" (patients_info['LastName'].str.contains(last_name, case=False, na=False))]\n",
"# Get the fat mass percentage for Keirstyn\n",
" fat_percentage = patient_data['Adult_FMP'].iloc[0]\n",
" weight_kg = patient_data['Weight'].iloc[0]\n",
" lean_percentage = 100 - fat_percentage\n",
"\n",
"# Create donut chart\n",