From 8e8280bcb0bf6c7a7b92e0bacb1fdd6d0d3604b6 Mon Sep 17 00:00:00 2001 From: bolade Date: Mon, 24 Nov 2025 19:37:28 +0100 Subject: [PATCH] added extra page --- app/estimated_carb_storage.png | Bin 0 -> 101027 bytes app/main.py | 2 + app/report_gen/page_12.html | 208 +++++-- app/report_gen/page_9.5.html | 515 ++++++++++++++++++ .../context_generator.cpython-312.pyc | Bin 46089 -> 46960 bytes .../graph_generator.cpython-312.pyc | Bin 57999 -> 67353 bytes .../report_generator.cpython-312.pyc | Bin 22278 -> 22283 bytes app/services/context_generator.py | 28 +- app/services/graph_generator.py | 234 ++++++++ app/services/report_generator.py | 1 + notebooks/graphs.ipynb | 146 +++++ 11 files changed, 1073 insertions(+), 61 deletions(-) create mode 100644 app/estimated_carb_storage.png create mode 100644 app/report_gen/page_9.5.html diff --git a/app/estimated_carb_storage.png b/app/estimated_carb_storage.png new file mode 100644 index 0000000000000000000000000000000000000000..ba4cffd2284c550cb8f007a3f0f73aa6097d072b GIT binary patch literal 101027 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 Zeoxlyo~D0#rNGd&oNI0Ir@3qJ{{g<%?}GpU literal 0 HcmV?d00001 diff --git a/app/main.py b/app/main.py index 1251ec6..8dbedea 100644 --- a/app/main.py +++ b/app/main.py @@ -233,6 +233,7 @@ async def upload_files( str(pnoe_path), str(spirometry_csv_path), None, # No SECA file needed anymore + str(oxygenation_path) if oxygenation_path else None, # Oxygenation CSV ) # Set patient info manually since we're not reading from SECA weight_kg = float(weight.replace("lbs", "").replace("kg", "").strip()) @@ -442,6 +443,7 @@ async def edit_metrics(request: Request): str(pnoe_path), spirometry_csv_path, None, # No SECA file + str(oxygenation_path) if oxygenation_path else None, # Oxygenation CSV ) # Set patient info manually weight_str = patient_info.get("weight", "0") diff --git a/app/report_gen/page_12.html b/app/report_gen/page_12.html index 1546b03..aa5ecdd 100644 --- a/app/report_gen/page_12.html +++ b/app/report_gen/page_12.html @@ -1,76 +1,166 @@

-

Local Muscle Activity

-

Muscle Oxygenation Assessment

+

+ Local Muscle Activity +

+

+ Muscle Oxygenation Assessment +

- SMO2 testing (Skeletal Muscle Oxygen Saturation) is an analysis of how effectively oxygen is being used at a particular muscle. It helps determine limitations on if the muscle is effectively using oxygen when exercising. + SMO2 testing (Skeletal Muscle Oxygen Saturation) is an analysis of + how effectively oxygen is being used at a particular muscle. It + helps determine limitations on if the muscle is effectively using + oxygen when exercising.

- -
-

Indications - Right Leg

- -
- -
- Right Leg SMO2 Chart + +
+
+ Muscle Oxygenation Chart +
+
+ + +
+ +
+

+ Left Leg Analysis +

+ +
+
+
+ Baseline SmO₂ +
+
+ {{ left_baseline_smo2 | default('75.4%') }} +
+
+ +
+
+ Minimum SmO₂ +
+
+ {{ left_minimum_smo2 | default('69.3%') }} +
+
+ {{ left_minimum_lap | default('Lap 6') }} +
+
+ +
+
+ Oxygen Drop +
+
+ {{ left_oxygen_drop | default('6.0%') }} +
+
+ {{ left_drop_percentage | default('8% decrease') }} +
+
+ +
+
+ Recovery +
+
+ "Optimal >100%" +
+
+ {{ left_recovery_percentage | default('109%') }} +
+
- - -
-
-
Surplus
-
Supply > Demand at a heart rate and speed of:
-
n/a
+
+ + +
+

+ Right Leg Analysis +

+ +
+
+
+ Baseline SmO₂ +
+
+ {{ right_baseline_smo2 | default('82.9%') }} +
- -
-
Supply Threshold
-
Demand outstrips supply at a heart rate of:
-
154bpm @ 5.0mph
+ +
+
+ Minimum SmO₂ +
+
+ {{ right_minimum_smo2 | default('73.7%') }} +
+
+ {{ right_minimum_lap | default('Lap 6') }} +
- -
-
Recovery
-
"Optimal >100%"
-
n/a
+ +
+
+ Oxygen Drop +
+
+ {{ right_oxygen_drop | default('9.3%') }} +
+
+ {{ right_drop_percentage | default('11% decrease') }} +
+
+ +
+
+ Recovery +
+
+ "Optimal >100%" +
+
+ {{ right_recovery_percentage | default('97%') }} +
- -
-

Indications - Left Leg

- -
- -
- Left Leg SMO2 Chart -
- - -
-
-
Surplus
-
Supply > Demand at a heart rate and speed of:
-
n/a
-
- -
-
Supply Threshold
-
Demand outstrips supply at a heart rate of:
-
165 bpm @ 5.5mph
-
- -
-
Recovery
-
"Optimal >100%"
-
n/a
-
-
+ +
+

Key Findings

+
+

+ • Left leg showed better oxygen maintenance + during high-intensity work +

+

+ • + {{ recovery_assessment | default('Excellent recovery + capacity') }} + - both legs recovered well +

+

+ • Heart rate progression: {{ hr_warmup | + default('93') }} → {{ hr_max | default('168') }} bpm +

+

+ • Test duration: {{ test_duration | + default('~21 minutes active test') }} +

-
\ No newline at end of file +
diff --git a/app/report_gen/page_9.5.html b/app/report_gen/page_9.5.html new file mode 100644 index 0000000..4d42a00 --- /dev/null +++ b/app/report_gen/page_9.5.html @@ -0,0 +1,515 @@ +
+ +
+ +

Fuelling Analysis

+ + +
+ Fuelling Analysis Flowchart +
+ + +
+

+ Estimated Carbohydrate Storage by Weight and Sex in Athletes +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Weight (kg) + + Sex + + Muscle Glycogen (g) + + Liver Glycogen (g) + + Blood Glucose (g) + + Total Carb (g) + + Total Carb (kcal) +
+ 50 + + male + + 292 + + 105 + + 4.5 + + 402 + + 1608 +
+ 50 + + female + + 228 + + 85 + + 4.5 + + 317 + + 1268 +
+ 60 + + male + + 351 + + 105 + + 4.5 + + 460 + + 1842 +
+ 60 + + female + + 273 + + 85 + + 4.5 + + 362 + + 1450 +
+ 70 + + male + + 410 + + 105 + + 4.5 + + 519 + + 2076 +
+ 70 + + female + + 318 + + 85 + + 4.5 + + 408 + + 1632 +
+ 80 + + male + + 468 + + 105 + + 4.5 + + 578 + + 2310 +
+ 80 + + female + + 364 + + 85 + + 4.5 + + 454 + + 1814 +
+ 90 + + male + + 526 + + 105 + + 4.5 + + 636 + + 2544 +
+ 90 + + female + + 409 + + 85 + + 4.5 + + 499 + + 1996 +
+ 100 + + male + + 585 + + 105 + + 4.5 + + 694 + + 2778 +
+ 100 + + female + + 455 + + 85 + + 4.5 + + 544 + + 2178 +
+
+
+
+
diff --git a/app/services/__pycache__/context_generator.cpython-312.pyc b/app/services/__pycache__/context_generator.cpython-312.pyc index 8705f8a405a3982ff1e9231b25996e77d68c2e69..9e63d994a2619bdada36407f8bf47230bc284499 100644 GIT binary patch delta 8459 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 delta 7835 zcmai333QZImaf0HRHd@-dnzP>6iFZ(m_QQ37Pb(OeKCY0|DRBhRE1Z?l9*7m(k&c4 z3O2bPMu%}i2=6JN{v>K1vap@kLnbT+P_gv+CGy-Vkj!P@NdkwL>>t5=;7yzax($d5jv( z9meeJc&Z(zCPZo`MyMn{+n63i8#XnWv=Y@6%^tR#N_^57K8^TfQD#)riB1XA8APY5 znOd5fCHzgND6&bGq2_3rW8@ZUBbVe^V{GOTpB)^dWT(pcB+OBrKd4+l^4xHv6Nt{U z8z?1{M4AdUN|t8nG>X)WCaH)*%^yh@Y1pMkXS7;O33B$CTqQbRV_K%v^Yf;usUE|C zq1}Z3!qaECptQQo{5#VGKH2=R;^c3bbNCnLnv4#!)DQ?7b-sDuz?WEFdN4iLsu;+! znftBfMpqOMSzY`iYlhRz5=f1u08#;I1b$R^(!&yYe$?dHbjX$x>@$2D$JazP#Jz8e zdCxZCx^2SmY(*?NbT#TJ(<~<`^vA53yR53Dr+aFT$LnGR5Lwo&D(QByLeTa#^Gm{I z6NqO;fJp!sf6`H}Wbw}&wMqgnjH$9FLY&Jt#*``(AH65W8b6T)UDY@Dy&eCk(!@&n z(WIV)7AUm>mI0RY18WHTX(s;cWQo?B?`R0fY;5ch-TFUt|-~qCSIGB zpSeM(Nc||Hkx6_x~jylb+}w6-M&zBv%m^> zKx4=F{?h5W+o5JwJ)NEG0IDG~%uC>kVF~=b(h15Szg0S0*~{z8@?>uwe{Q0J&hozcrxlCD84fcV~~rkg#nKc0*|K_jY>%V&u3oWE3y*%?+taIp5XL zSo8`MUxlJgWxn2a>f12Ie7o6xlyd%l!+_(LAYUW!XK?3*Y$FYxfyNf4JoHB6yHQio znXDfmI`mFZ&j1z!@Ex_XqacxO>dv>Cw^@8!0vra2Rz-s^@QDjct&c$XAz!=DO~dY`g&UN^p_D~`L8myD+%#E*1IPIn zt)D6r`Mb-Sr-U8AAeX}m?d#?aUvHnx{3?_P2a;JrXz}tQg$(;{Z&j{@uH3E}$#BuC zI-^4v7U3@CTi3jvcnQ@q6@n~4w!){bP2;Q9{-ja#qKHjIiD^OFmmjqr%`|_Yy?3kI zuSweD?P}l3WG>_Ccjap7;oeuqFQeVsn5Ktz*gTBnDP!$5QITvzScW4&qm9lP~f!b%Q zBr_ESt0lbA2 z@N%N5&t%%}kOr61E1VtO+~e-nSUgE|rH8el1WdnWOK*>}lwE`=d@mPFtc+jUoHbc2 zmC^nHEdc)Ap1@Y!;t6Oyep->ldLzd=YL)RnZO&FUbBB8leH5+k#Y%PPgu9cz%4gLK zh2{X#X&|80xe@d%Koej#U=CpJ2)GosjcAu$wz3^^*%aTbr4()kzZKvCbP@RNH#1^9mgfY0KVb%W2VIV;2ODs~km zS3<+x>y%iGURFv#9S?ngC>sz1{ z^Lu?+$|Qc?SEBqkf7`cwGl#V}^h{tY8$bCmOiQ|@v)kum>~)wF3(ZPMO|;DttCDVV zZ}E!-Nw>Otdo{1>DjhRF|Ck4RC*+St{4C6b06zyj2Y8-e?R7i*DUG_lpMq~!-PGax zQ6xU0YoM+_I(vsA)>u8A?_lYC6Pv6IhYm6wI|+5yyT*bi$igSpc>K*xGzu?(7YWE* z1pXr5*jHF|iKML;thelIG}h-_j@U3TbaS)Y!@{G1pX)0MK8@;c{szxnRDUL7?u0P^ z>}a_#9|GTr=i{Z&|2gsWF?0!!s%x7*p)hDC+laE~BDQYK2LF7d?!sZFPx`lL=3{Em^o!PtYz{_#ag!2C&USyo; z(Zqi&I`!A%?DF^TjBEQ1s>?hJ^KXKe=@sVR0x$g#vAhjlGNQyB0jWG01xT5U#$s+@(0u_IYMx;|!;Qtf6jCmUP-+`BXES!EfqTkto z^7n{ubw&5vt18O*mjibO<47)KuPC2h$HZ!jS-sy>veZS;>|$c^dY@#slzMiPYO|LCVw!3vvCG6T$!Cbk zhIK$fyLhO`8TY}x*|i!;b<=jOk74T7t+X%N*&PrQ@8~@2$K*9K1LIAz@XEa_l-|(! zy)%r~WSHC;`gmW75_FRlb{X(9f>!o5%AO>W67vUo={BbA(wJXUUD48)oudvBr6=w3 zRkhREr#;}_(yg_7yq!MjT672Py1RVLLkG6+tq{>v5pFr1Rsea&?`l>4#Q$*D5t_hu z-)*$k7n6$Ttc9j+A`FJ!V@<4u-ZHN^28-2FteZn=U~j-#(~9{kSP6gb;M2hh2r)m) z6T)gx_mGY_yvPhA+3c@?1E?$xaWs{0heT{{V`aoX2qp{rtcU4Vn(x~+jctS&uIP@A zZl50;R5~iKJ0LMn@@nn?`vwhu4fvM8kE1ODjyx2($E=eiu<8@@{_z7dlPs9G@u=3*rh#ZRs-6drWJQ@WNfe0X zZ`J1Tvo$t;_JP#&QB~V%BdOZ!Q7xL+9?H)Y`U4Ktf#ZT2Bg$jJ^WH;~q%}2;Hyuj1 z$HTIkaLUX-Jd|!qRFnAd@qAOVe5cU+5{@{~NjYt$R#L|}q^5~V>ETKlcpuI;WvW@? zovr4GcdnWz-ubE%@7w})Ld0m{X*(G$60R2y#tcO9tA|ooPaMetiyN@1li=b&lsXab zeh0Zy(ods@w8Lep>y$ZwkuM&SPKM@)jZ=n!m`H%7($~VWF@cqzwvZ1~-~-j28c7JH zC$&OwmHm_iwGyqKGN@HZT=EY})M~zs=bLJ%g=_Sl7Jg3;zi$)o0!1V^xo%ARGfvy6 z{h7S^$Zbjm1_Rwpojg*UI8|*J$A1p- z>MXCKHVq~W#HzF5Ie9y0Ac1i1L*~K6E`vJnoHCd+kVxh8MP$vu2)AGyw{RS{XdJhA z9Jhpj@K3JPmdi^oQHJm!9%!hoJm+Xb>9Uc&V4sr@%gKjSdf$FdAzX1z3FM1P&`;xU z9m|egCagPzg_XSGSf(Q6$})cTXtAWn>8u{7Q*L;9T~^f>)>{4dAKt6MIwzl8e= zdLsUA2#n>Ph-Yk~fX%!}il=vay*zeZ0X$eT(v0?$Pprbae|X zQcrX|WF$@%5vHr!IBBP7wM%?xTY2k=K@+tBTlt<*Tk1CYoHKr^3}n(Ti+<7Sb{=zb zbnI+CS#0W7d-#Eqr6w=cfBt0K4@QiW?>dzl^hNq*bmV0JgOSrqy_QEKCp$cHM^mv@dCNZUnHcA;a&43yoM6h7sl;>b+5 z=X*2Vo-s3BAEv34{xK=MQ%tS{VlImplchQso+kJ5FCUs`bOrgq!+l%Koi`6n`@p@X_7m!4c^6z9`caKKbcCMO z0jwiqN~)+tTp;~|iWy);)gfwn`4eYi9fMe7#Pz^Ue)UXR5$-GWge^X`uf5Yv7bhC) z(7XXU@u3lBA%m=y-#W9aZI~*0ZqgUYz5=xycCcW1uwcpc>rbG-dfG{kPJ*L0;$SEq z06W5jT<*le_bq?(Y<9wKw2132b_1}7e|NT6+0FAF**Ikv1Y&P98Pr9BA)FrNW#E&b zo&x*~@HBt?5ocBz+PMt=2gM&fk{iTwEO!i0!GT&=nssFn;o10YeOM74BRC z_(NCD)hqLZknRKg2yhqRZoqy58Y%@ys<1nOC_Qc~YsY!eFSl9Y8$Leku@WoBG`o}c zJl34^3P>IBDj;${N&TL~-+nA@vQQXbrbo#ESb?2hhmZDpeKf#Ic>GUugHG~AH&@V& zgt&^(l}?vU<_^ci|L6ALdv^^wB?g^~P-##Y?Hx8qK^o&W88%#?T0O8}3uBIkT+tIX^q0l@C+<$|A*mi4$!t3X&8qlUPh=VWPP(Hm#2xj*3v;Zk zX4;O{hYnphY_olvW=KjuwBslbUQFe$KAT5>0DbiAx|TtcA$5uJS3PAB{T9-%CH!9M zFCq`Gr6sjZvR%6^sjV#fdPY)PWz6-uq_*jC?_?#l%}jV_X3{1@5~F<>O;@e0{Pj>p zkY;kay8~DOd4OC1_5-pXN4qczvV(vu0^Pb&694BhE~M@b zhWlF#4ho-qLH6zfg?%AQ1c>Pe5Jx}1lQi}lZkQ{+Hk&Q^!zqTMlCSKsmf{bS(}ped z9<~~?a)+Zp*$gQ;$LAhy_y*-)=apEJhF2*CmV&2~hYj?4F(qVv?jEImo7s}_VOr*} z1q4-3Og*&nc;TUShvSB$gve&dE<9UvV#=^xu+fIB31(YLdIku%lVPgEYR3+nU15jA`Kk)aL AiU0rr diff --git a/app/services/__pycache__/graph_generator.cpython-312.pyc b/app/services/__pycache__/graph_generator.cpython-312.pyc index 480e77bb7407ec08e48422ce5a8a4d7d660b4058..6c836b3ca27baf979c6905124519c3ed69e25382 100644 GIT binary patch delta 12303 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 delta 4828 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 KkbWUPo%kP}zs%ME diff --git a/app/services/context_generator.py b/app/services/context_generator.py index de02bf4..b5574d1 100644 --- a/app/services/context_generator.py +++ b/app/services/context_generator.py @@ -18,6 +18,7 @@ class ContextGenerator: self.pnoe_df = None self.spirometry_df = None self.seca_df = None + self.oxygenation_df = None self.patient_info = {} def load_data( @@ -25,6 +26,7 @@ class ContextGenerator: pnoe_path: str, spirometry_path: str, seca_path: Optional[str] = None, + oxygenation_path: Optional[str] = None, ): """Load all required datasets""" self.pnoe_df = pd.read_csv(pnoe_path, delimiter=";") @@ -33,6 +35,11 @@ class ContextGenerator: self.seca_df = pd.read_excel(seca_path) else: self.seca_df = None + if oxygenation_path: + # Load muscle oxygenation data with skiprows to skip Train.Red metadata + self.oxygenation_df = pd.read_csv(oxygenation_path, skiprows=445) + else: + self.oxygenation_df = None self._preprocess_pnoe_data() def _preprocess_pnoe_data(self): @@ -1375,8 +1382,25 @@ class ContextGenerator: ) ) - # Pages 12-17 - for i in range(6): + # Page 12 - Muscle Oxygenation + contexts["page_12"] = { + "patient_name": self.patient_info["name"], + "page_number": 12, + } + + # Generate muscle oxygenation chart if data is available + if graph_generator and self.oxygenation_df is not None: + try: + chart_str, metrics = graph_generator.generate_muscle_oxygenation_chart( + self.oxygenation_df, save_as_base64=True + ) + contexts["page_12"]["muscle_oxygenation_chart"] = chart_str + contexts["page_12"].update(metrics) + except Exception as e: + print(f"Warning: Could not generate muscle oxygenation chart: {e}") + + # Pages 13-17 + for i in range(1, 6): contexts[f"page_{i + 12}"] = { "patient_name": self.patient_info["name"], "page_number": i + 12, diff --git a/app/services/graph_generator.py b/app/services/graph_generator.py index 441bc78..0bcb6b5 100644 --- a/app/services/graph_generator.py +++ b/app/services/graph_generator.py @@ -6,6 +6,7 @@ Based on the analysis notebooks in services_dfdf/. """ import base64 +import io from pathlib import Path import matplotlib @@ -1680,3 +1681,236 @@ class GraphGenerator: ) plt.close(fig) return str(output_path) + + def generate_muscle_oxygenation_chart( + self, oxygenation_df: pd.DataFrame, save_as_base64: bool = True + ) -> tuple: + """ + Generate comprehensive muscle oxygenation (SmO2) chart with both legs and heart rate. + + Args: + oxygenation_df: DataFrame with muscle oxygenation data (Train.Red CSV format) + save_as_base64: If True, return base64 string, else return file path + + Returns: + Tuple of (chart_string, metrics_dict) where metrics_dict contains key values + """ + # Data preparation + df_oxy = oxygenation_df.copy() + + # Convert columns to numeric + df_oxy["Timestamp (seconds passed)"] = pd.to_numeric( + df_oxy["Timestamp (seconds passed)"], errors="coerce" + ) + df_oxy["Left_SmO2"] = pd.to_numeric(df_oxy["SmO2"], errors="coerce") + df_oxy["Right_SmO2"] = pd.to_numeric(df_oxy["SmO2.1"], errors="coerce") + df_oxy["Heart_Rate"] = pd.to_numeric( + df_oxy["Heart Rate (BPM)"], errors="coerce" + ) + df_oxy["Lap"] = pd.to_numeric(df_oxy["Lap/Event"], errors="coerce") + + # Drop rows with missing timestamps + df_oxy = df_oxy.dropna(subset=["Timestamp (seconds passed)"]) + df_oxy = df_oxy.sort_values("Timestamp (seconds passed)").reset_index(drop=True) + + # Apply 10-second rolling mean smoothing + time_diffs = df_oxy["Timestamp (seconds passed)"].diff().dropna() + avg_sampling_interval = time_diffs.median() + sampling_freq = 1 / avg_sampling_interval if avg_sampling_interval > 0 else 10 + window_samples = int(10 * sampling_freq) + + df_oxy["Left_SmO2_smooth"] = ( + df_oxy["Left_SmO2"] + .rolling(window=window_samples, center=True, min_periods=1) + .mean() + ) + df_oxy["Right_SmO2_smooth"] = ( + df_oxy["Right_SmO2"] + .rolling(window=window_samples, center=True, min_periods=1) + .mean() + ) + df_oxy["Heart_Rate_smooth"] = ( + df_oxy["Heart_Rate"] + .rolling(window=window_samples, center=True, min_periods=1) + .mean() + ) + + # Identify stage boundaries + lap_changes = df_oxy[df_oxy["Lap"].diff() != 0].copy() + lap_starts = {} + for idx, row in lap_changes.iterrows(): + lap_num = int(row["Lap"]) + lap_starts[lap_num] = row["Timestamp (seconds passed)"] + + warm_up_end = lap_starts.get(1, df_oxy["Timestamp (seconds passed)"].max()) + recovery_start = lap_starts.get(7, df_oxy["Timestamp (seconds passed)"].max()) + + # Calculate recovery percentages + warm_up_last_30_start = warm_up_end - 30 + warm_up_mask = ( + df_oxy["Timestamp (seconds passed)"] >= warm_up_last_30_start + ) & (df_oxy["Timestamp (seconds passed)"] <= warm_up_end) + + recovery_end = df_oxy["Timestamp (seconds passed)"].max() + recovery_last_30_start = recovery_end - 30 + recovery_mask = ( + df_oxy["Timestamp (seconds passed)"] >= recovery_last_30_start + ) & (df_oxy["Timestamp (seconds passed)"] <= recovery_end) + + left_warmup_avg = df_oxy.loc[warm_up_mask, "Left_SmO2_smooth"].mean() + left_recovery_avg = df_oxy.loc[recovery_mask, "Left_SmO2_smooth"].mean() + left_recovery_pct = round((left_recovery_avg / left_warmup_avg) * 100) + + right_warmup_avg = df_oxy.loc[warm_up_mask, "Right_SmO2_smooth"].mean() + right_recovery_avg = df_oxy.loc[recovery_mask, "Right_SmO2_smooth"].mean() + right_recovery_pct = round((right_recovery_avg / right_warmup_avg) * 100) + + # Calculate key metrics + active_mask = (df_oxy["Timestamp (seconds passed)"] >= warm_up_end) & ( + df_oxy["Timestamp (seconds passed)"] <= recovery_start + ) + active_data = df_oxy[active_mask] + + left_min = active_data["Left_SmO2_smooth"].min() + left_min_lap = int( + active_data.loc[active_data["Left_SmO2_smooth"].idxmin(), "Lap"] + ) + right_min = active_data["Right_SmO2_smooth"].min() + right_min_lap = int( + active_data.loc[active_data["Right_SmO2_smooth"].idxmin(), "Lap"] + ) + + left_drop = left_warmup_avg - left_min + right_drop = right_warmup_avg - right_min + + hr_warmup = df_oxy[df_oxy["Timestamp (seconds passed)"] <= warm_up_end][ + "Heart_Rate_smooth" + ].mean() + hr_max = active_data["Heart_Rate_smooth"].max() + + # Create the plot + fig, ax1 = plt.subplots(figsize=(18, 8)) + + time = df_oxy["Timestamp (seconds passed)"] + ax1.plot( + time, + df_oxy["Left_SmO2_smooth"], + label=f"Left SmO₂ (Rec {left_recovery_pct}% of warm-up)", + color="#2E86AB", + linewidth=2, + ) + ax1.plot( + time, + df_oxy["Right_SmO2_smooth"], + label=f"Right SmO₂ (Rec {right_recovery_pct}% of warm-up)", + color="#A23B72", + linewidth=2, + ) + + ax1.set_xlabel("Time (seconds)", fontsize=12, fontweight="bold") + ax1.set_ylabel("SmO₂ (%)", fontsize=12, fontweight="bold") + ax1.tick_params(axis="y", labelcolor="black") + ax1.grid(True, alpha=0.3, linestyle="--") + + # Add secondary axis for heart rate + ax2 = ax1.twinx() + ax2.plot( + time, + df_oxy["Heart_Rate_smooth"], + label="Heart Rate", + color="red", + linewidth=1.5, + linestyle="--", + alpha=0.7, + ) + ax2.set_ylabel("Heart Rate (BPM)", fontsize=12, fontweight="bold", color="red") + ax2.tick_params(axis="y", labelcolor="red") + + # Add shaded regions + ax1.axvspan(0, warm_up_end, alpha=0.15, color="blue", label="Warm-up") + + active_laps = [1, 2, 3, 4, 5, 6] + colors_active = ["yellow", "orange"] * 3 + for i, lap in enumerate(active_laps): + start = lap_starts.get(lap, 0) + end = lap_starts.get(lap + 1, recovery_start) if lap < 6 else recovery_start + ax1.axvspan(start, end, alpha=0.1, color=colors_active[i]) + + ax1.axvspan( + recovery_start, recovery_end, alpha=0.2, color="gray", label="Recovery" + ) + ax1.axvline( + x=recovery_start, color="black", linestyle="-", linewidth=2, alpha=0.7 + ) + + # Add lap labels + for lap in range(1, 7): + start = lap_starts.get(lap, 0) + end = lap_starts.get(lap + 1, recovery_start) if lap < 6 else recovery_start + mid = (start + end) / 2 + ax1.text( + mid, + ax1.get_ylim()[1] * 0.97, + f"Lap {lap}", + ha="center", + va="top", + fontsize=10, + fontweight="bold", + bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.7), + ) + + plt.title( + "Train.Red SmO₂ Ramp - Muscle Oxygenation Analysis", + fontsize=16, + fontweight="bold", + pad=20, + ) + + # Combine legends + lines1, labels1 = ax1.get_legend_handles_labels() + lines2, labels2 = ax2.get_legend_handles_labels() + ax1.legend( + lines1 + lines2, + labels1 + labels2, + loc="upper left", + fontsize=10, + framealpha=0.9, + ) + + plt.tight_layout() + + # Prepare metrics dictionary + metrics = { + "left_baseline_smo2": f"{left_warmup_avg:.1f}%", + "right_baseline_smo2": f"{right_warmup_avg:.1f}%", + "left_minimum_smo2": f"{left_min:.1f}%", + "right_minimum_smo2": f"{right_min:.1f}%", + "left_minimum_lap": f"Lap {left_min_lap}", + "right_minimum_lap": f"Lap {right_min_lap}", + "left_oxygen_drop": f"{left_drop:.1f}%", + "right_oxygen_drop": f"{right_drop:.1f}%", + "left_drop_percentage": f"{(left_drop / left_warmup_avg * 100):.0f}% decrease", + "right_drop_percentage": f"{(right_drop / right_warmup_avg * 100):.0f}% decrease", + "left_recovery_percentage": f"{left_recovery_pct}%", + "right_recovery_percentage": f"{right_recovery_pct}%", + "hr_warmup": f"{hr_warmup:.0f}", + "hr_max": f"{hr_max:.0f}", + "test_duration": f"~{(recovery_start - warm_up_end) / 60:.0f} minutes active test", + "recovery_assessment": "Excellent recovery capacity" + if (left_recovery_pct + right_recovery_pct) / 2 >= 100 + else "Good recovery capacity", + } + + # Save or return + if save_as_base64: + buf = io.BytesIO() + plt.savefig(buf, format="png", dpi=300, bbox_inches="tight") + plt.close(fig) + buf.seek(0) + chart_str = base64.b64encode(buf.read()).decode("utf-8") + return chart_str, metrics + else: + output_path = self.charts_dir / "muscle_oxygenation_chart.png" + plt.savefig(output_path, dpi=300, bbox_inches="tight") + plt.close(fig) + return str(output_path), metrics diff --git a/app/services/report_generator.py b/app/services/report_generator.py index 55b5498..cfb8b89 100644 --- a/app/services/report_generator.py +++ b/app/services/report_generator.py @@ -503,6 +503,7 @@ class ReportGeneratorService: pnoe_csv_path, str(spirometry_csv_path), None, # No SECA file + oxygenation_csv_path, # Pass oxygenation CSV path ) # Set patient info manually self.context_generator.patient_info = { diff --git a/notebooks/graphs.ipynb b/notebooks/graphs.ipynb index ca29ad3..7156f26 100644 --- a/notebooks/graphs.ipynb +++ b/notebooks/graphs.ipynb @@ -3240,6 +3240,152 @@ "\n", "The analysis follows the PDF instructions for Train.Red SmO₂ ramp testing, including 10-second smoothing, stage identification, and recovery percentage calculations." ] + }, + { + "cell_type": "markdown", + "id": "d8dfb3fa", + "metadata": {}, + "source": [ + "## Integration with Report Generator\n", + "\n", + "The muscle oxygenation graph generation has been integrated into the report generation system:\n", + "\n", + "1. **GraphGenerator** method: `generate_muscle_oxygenation_chart(oxygenation_df, save_as_base64=True)`\n", + " - Returns: tuple of (base64_chart_string, metrics_dict)\n", + " \n", + "2. **ContextGenerator** now accepts `oxygenation_path` parameter in `load_data()`\n", + "\n", + "3. **Page 12** automatically includes:\n", + " - Full muscle oxygenation chart showing both legs\n", + " - Key metrics for both legs (baseline, minimum, drop, recovery)\n", + " - Heart rate data\n", + " - Summary findings\n", + "\n", + "The system will automatically generate the chart when an oxygenation CSV file is provided during report generation." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a9064ffe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading oxygenation data...\n", + "✅ Graph generation successful!\n", + "\n", + "Chart size: 871248 characters (base64)\n", + "\n", + "Metrics extracted:\n", + " left_baseline_smo2: 75.4%\n", + " right_baseline_smo2: 82.9%\n", + " left_minimum_smo2: 69.3%\n", + " right_minimum_smo2: 73.7%\n", + " left_minimum_lap: Lap 6\n", + " right_minimum_lap: Lap 6\n", + " left_oxygen_drop: 6.0%\n", + " right_oxygen_drop: 9.3%\n", + " left_drop_percentage: 8% decrease\n", + " right_drop_percentage: 11% decrease\n", + " left_recovery_percentage: 109%\n", + " right_recovery_percentage: 97%\n", + " hr_warmup: 93\n", + " hr_max: 168\n", + " test_duration: ~21 minutes active test\n", + " recovery_assessment: Excellent recovery capacity\n" + ] + } + ], + "source": [ + "# Test the GraphGenerator integration\n", + "import sys\n", + "import os\n", + "import pandas as pd\n", + "\n", + "# Set base_dir if not already defined\n", + "try:\n", + " base_dir\n", + "except NameError:\n", + " base_dir = os.path.dirname(os.path.abspath('.'))\n", + "\n", + "# Load oxygenation data if not already loaded\n", + "try:\n", + " oxygenation_2\n", + "except NameError:\n", + " print(\"Loading oxygenation data...\")\n", + " oxygenation_2 = pd.read_csv(f'{base_dir}/data/muscle_oxygenation.csv', skiprows=445)\n", + "\n", + "sys.path.append(f'{base_dir}/app')\n", + "\n", + "from services.graph_generator import GraphGenerator\n", + "\n", + "# Initialize the graph generator\n", + "graph_gen = GraphGenerator(charts_dir=f'{base_dir}/graphs')\n", + "\n", + "# Generate the chart using the same dataframe\n", + "try:\n", + " chart_b64, metrics = graph_gen.generate_muscle_oxygenation_chart(\n", + " oxygenation_2, \n", + " save_as_base64=True\n", + " )\n", + " \n", + " print(\"✅ Graph generation successful!\")\n", + " print(f\"\\nChart size: {len(chart_b64)} characters (base64)\")\n", + " print(f\"\\nMetrics extracted:\")\n", + " for key, value in metrics.items():\n", + " print(f\" {key}: {value}\")\n", + " \n", + "except Exception as e:\n", + " print(f\"❌ Error: {e}\")\n", + " import traceback\n", + " traceback.print_exc()" + ] + }, + { + "cell_type": "markdown", + "id": "7886483b", + "metadata": {}, + "source": [ + "## ✅ Integration Complete!\n", + "\n", + "The muscle oxygenation analysis has been successfully integrated into the report generation system.\n", + "\n", + "### What was implemented:\n", + "\n", + "1. **GraphGenerator Method** (`app/services/graph_generator.py`):\n", + " - Added `generate_muscle_oxygenation_chart()` method\n", + " - Processes Train.Red CSV data (with 10-second smoothing)\n", + " - Generates comprehensive chart with both legs and heart rate\n", + " - Returns both base64 image and extracted metrics dictionary\n", + "\n", + "2. **ContextGenerator Updates** (`app/services/context_generator.py`):\n", + " - Added `oxygenation_df` attribute\n", + " - Updated `load_data()` to accept optional `oxygenation_path` parameter\n", + " - Page 12 context now includes muscle oxygenation chart and all metrics\n", + "\n", + "3. **Page 12 Template** (`app/report_gen/page_12.html`):\n", + " - Replaced two separate leg charts with single comprehensive chart\n", + " - Added side-by-side metric cards for both legs\n", + " - Displays all key values: baseline, minimum, drop, recovery\n", + " - Includes summary findings section\n", + "\n", + "4. **Report Generation Pipeline** (`app/services/report_generator.py`, `app/main.py`):\n", + " - Updated to pass oxygenation CSV path through the system\n", + " - Automatically generates chart when oxygenation data is provided\n", + "\n", + "### How to use:\n", + "\n", + "When generating a report, simply provide the muscle oxygenation CSV file (Train.Red format), and the system will:\n", + "- Automatically load and process the data\n", + "- Generate the comprehensive visualization\n", + "- Extract all key metrics\n", + "- Include everything in Page 12 of the report\n", + "\n", + "No manual intervention required - it's fully automated!" + ] } ], "metadata": {