11from pathlib import Path
2+ from typing import Any
23
34import cv2
45import matplotlib .pyplot as plt
@@ -345,7 +346,12 @@ def _get_file_path(file_name: str) -> Path:
345346 return Path (__file__ ).parent / file_name
346347
347348
348- def get_project_red_production_temperature_profile_series (fervo_graph_df_model : pd .Series ) -> pd .Series :
349+ def get_project_red_production_temperature_profile_series (
350+ fervo_graph_df_model : pd .Series ,
351+ ) -> tuple [
352+ pd .Series ,
353+ Any , # interpolator
354+ ]:
349355 input_params : GeophiresInputParameters = ImmutableGeophiresInputParameters (
350356 from_file_path = _get_file_path ('../../tests/examples/Fervo_Project_Red-2026.txt' ),
351357 params = {'Print Output to Console' : 0 },
@@ -372,7 +378,7 @@ def get_project_red_production_temperature_profile_series(fervo_graph_df_model:
372378
373379 geophires_series = pd .Series (data = geophires_interpolated_y , index = fervo_graph_df_model ['Time_Years' ])
374380
375- return geophires_series
381+ return geophires_series , geophires_interpolator
376382
377383
378384def generate_fervo_project_red_2026_docs ():
@@ -396,29 +402,42 @@ def generate_fervo_project_red_2026_docs():
396402 _log .info (f'Wrote production data CSV: { production_csv_path_ } ' )
397403 _log .info (f'Wrote model data CSV: { model_csv_path_ } ' )
398404
399- if not df_actual .empty and not df_model_ .empty :
400- df_steady_state = _calculate_variance_analysis (df_actual , df_model_ )
405+ df_steady_state = _calculate_variance_analysis (df_actual , df_model_ )
401406
402- rmse = float ( np . sqrt (( df_steady_state [ 'Error_C' ] ** 2 ). mean ()))
403- mae = float ( df_steady_state ['Error_C ' ].abs (). mean ())
404- max_error = float ( df_steady_state ['Error_C ' ].abs (). max ())
407+ # Like-for-like comparison metrics
408+ y_true = df_steady_state ['Temperature_C ' ].values
409+ y_fervo = df_steady_state ['Model_Temperature_C ' ].values
405410
406- _log .info (f'--- STATISTICAL ALIGNMENT (Steady-State > { _STEADY_STATE_START_YEARS } Years) ---' )
407- _log .info (f'Root Mean Square Error (RMSE): { rmse :.2f} °C' )
408- _log .info (f'Mean Absolute Error (MAE): { mae :.2f} °C' )
409- _log .info (f'Max Absolute Error: { max_error :.2f} °C' )
411+ # Calculate R^2 and Bias for Fervo
412+ rmse_f = float (np .sqrt ((df_steady_state ['Error_C' ] ** 2 ).mean ()))
413+ bias_f = float ((y_fervo - y_true ).mean ())
414+ ss_res_f = np .sum ((y_true - y_fervo ) ** 2 )
415+ ss_tot = np .sum ((y_true - np .mean (y_true )) ** 2 )
416+ r2_f = 1 - (ss_res_f / ss_tot ) if ss_tot != 0 else 0.0
410417
411- df_steady_state .to_csv (steady_state_csv_path , index = False )
412- _log .info (f'Wrote variance analysis CSV: { steady_state_csv_path } ' )
418+ # Calculate metrics for GEOPHIRES (interpolated at the exact same steady-state timestamps)
419+ geophires_series , geo_interp = get_project_red_production_temperature_profile_series (df_model_ )
420+ # geo_interp = interp1d(geophires_series.index, geophires_series.values, kind='linear', fill_value='extrapolate')
421+ y_geo = geo_interp (df_steady_state ['Time_Years' ])
422+
423+ rmse_g = float (np .sqrt (((y_true - y_geo ) ** 2 ).mean ()))
424+ bias_g = float ((y_geo - y_true ).mean ())
425+ ss_res_g = np .sum ((y_true - y_geo ) ** 2 )
426+ r2_g = 1 - (ss_res_g / ss_tot ) if ss_tot != 0 else 0.0
427+
428+ _log .info (f'--- STATISTICAL ALIGNMENT (Steady-State > { _STEADY_STATE_START_YEARS } Years) ---' )
429+ _log .info (f'FERVO: RMSE={ rmse_f :.2f} °C, R²={ r2_f :.4f} , Bias={ bias_f :.2f} °C' )
430+ _log .info (f'GEOPHIRES: RMSE={ rmse_g :.2f} °C, R²={ r2_g :.4f} , Bias={ bias_g :.2f} °C' )
431+
432+ df_steady_state .to_csv (steady_state_csv_path , index = False )
413433
414434 _generate_production_temperature_comparison_graph (
415435 production_csv_path_ ,
416436 model_csv_path_ ,
417437 steady_state_csv_path ,
418438 generated_graph_path_stem ,
419- geophires_data = get_project_red_production_temperature_profile_series ( df_model_ ) ,
439+ geophires_data = geophires_series ,
420440 )
421- _log .info (f'Wrote regenerated graph: { generated_graph_path_stem } ' )
422441
423442
424443if __name__ == '__main__' :
0 commit comments