@@ -9,6 +9,7 @@ struct ParametricFitWorkerInput {
99 normalization : Option < ParametricNormalization > ,
1010 optimizer_config : OptimizerConfig ,
1111 loss_metric : OptimizationLossMetric ,
12+ metric_quantization : MetricQuantization ,
1213 cancel_flag : Arc < AtomicBool > ,
1314}
1415
@@ -48,47 +49,27 @@ impl CurveFitApp {
4849 points : & Points ,
4950 params : & CurveParams ,
5051 ) {
51- let points_slice = points. as_slice ( ) ;
52- let sample_count = points_slice. len ( ) as f64 ;
53- let y_mean = points_slice. iter ( ) . map ( |point| point. y ( ) ) . sum :: < f64 > ( ) / sample_count;
52+ let metrics = calculate_iteration_metrics_with_quantization (
53+ points,
54+ params,
55+ self . fit_loss_metric ,
56+ self . fit_metric_quantization ,
57+ ) ;
58+ self . result_metrics = Some ( ExtendedMetrics {
59+ mse : metrics. mse ,
60+ rmse : metrics. rmse ,
61+ mae : metrics. mae ,
62+ r2 : metrics. r2 ,
63+ max_abs_error : metrics. max_abs_error ,
64+ } ) ;
5465
55- let mut sse = 0.0 ;
56- let mut sae = 0.0 ;
57- let mut max_abs_error = 0.0_f64 ;
5866 self . residual_plot_points . clear ( ) ;
59- self . residual_plot_points . reserve ( points_slice . len ( ) ) ;
60- for point in points_slice {
67+ self . residual_plot_points . reserve ( points . len ( ) ) ;
68+ for point in points . as_slice ( ) {
6169 let residual = params. evaluate ( point. x ( ) ) - point. y ( ) ;
62- let abs_residual = residual. abs ( ) ;
63- sse += residual * residual;
64- sae += abs_residual;
65- max_abs_error = max_abs_error. max ( abs_residual) ;
6670 self . residual_plot_points
6771 . push ( PlotPoint :: new ( point. x ( ) , residual) ) ;
6872 }
69-
70- let sst = points_slice
71- . iter ( )
72- . map ( |point| {
73- let centered = point. y ( ) - y_mean;
74- centered * centered
75- } )
76- . sum :: < f64 > ( ) ;
77- let mse = sse / sample_count;
78- let rmse = mse. sqrt ( ) ;
79- let mae = sae / sample_count;
80- let r2 = if sst <= 1e-15 {
81- if sse <= 1e-15 { 1.0 } else { 0.0 }
82- } else {
83- 1.0 - sse / sst
84- } ;
85- self . result_metrics = Some ( ExtendedMetrics {
86- mse,
87- rmse,
88- mae,
89- r2,
90- max_abs_error,
91- } ) ;
9273 }
9374
9475 pub ( super ) fn update_spline_result_metrics ( & mut self , result : & SplineResult ) {
@@ -171,10 +152,11 @@ impl CurveFitApp {
171152 if !self . discard_fit_worker_updates {
172153 if let Some ( points) = fit_points. as_ref ( ) {
173154 self . update_parametric_result_metrics ( points, & result. params ) ;
174- let metrics = calculate_iteration_metrics (
155+ let metrics = calculate_iteration_metrics_with_quantization (
175156 points,
176157 & result. params ,
177158 self . fit_loss_metric ,
159+ self . fit_metric_quantization ,
178160 ) ;
179161 self . iteration_diagnostics . append (
180162 result. iterations ,
@@ -195,14 +177,13 @@ impl CurveFitApp {
195177 keep_receiver = false ;
196178 break ;
197179 }
198- Ok ( FitWorkerMessage :: SplineFinished ( result) ) => {
180+ Ok ( FitWorkerMessage :: SplineFinished { result, metrics } ) => {
199181 self . fit_in_progress = false ;
200182 if !self . discard_fit_worker_updates {
201183 let knot_y = result. knots . iter ( ) . map ( |knot| knot[ 1 ] ) . collect :: < Vec < _ > > ( ) ;
202184 let spline_plot_curve =
203185 Self :: plot_points_from_pairs ( result. curve . iter ( ) . copied ( ) ) ;
204186 self . update_spline_result_metrics ( & result) ;
205- let metrics = result. iteration_metrics_snapshot ( self . fit_loss_metric ) ;
206187 self . iteration_diagnostics . append_spline (
207188 result. iterations ,
208189 metrics,
@@ -343,7 +324,12 @@ impl CurveFitApp {
343324 params
344325 } ;
345326 let metrics = if let Some ( points) = self . active_fit_points . as_ref ( ) {
346- calculate_iteration_metrics ( points, & params, self . fit_loss_metric )
327+ calculate_iteration_metrics_with_quantization (
328+ points,
329+ & params,
330+ self . fit_loss_metric ,
331+ self . fit_metric_quantization ,
332+ )
347333 } else {
348334 metrics
349335 } ;
@@ -367,14 +353,19 @@ impl CurveFitApp {
367353 }
368354 let fit_points = self . active_fit_points . take ( ) ;
369355 if let Some ( points) = fit_points. as_ref ( ) {
370- let ( mse, rmse) = calculate_metrics ( points, & result. params ) ;
356+ let ( mse, rmse) = calculate_metrics_with_quantization (
357+ points,
358+ & result. params ,
359+ self . fit_metric_quantization ,
360+ ) ;
371361 result. mse = mse;
372362 result. rmse = rmse;
373363 self . update_parametric_result_metrics ( points, & result. params ) ;
374- let metrics = calculate_iteration_metrics (
364+ let metrics = calculate_iteration_metrics_with_quantization (
375365 points,
376366 & result. params ,
377367 self . fit_loss_metric ,
368+ self . fit_metric_quantization ,
378369 ) ;
379370 self . iteration_diagnostics . append (
380371 result. iterations ,
@@ -421,13 +412,12 @@ impl CurveFitApp {
421412 self . upsert_spline_replay_frame ( iteration, Self :: plot_points_from_pairs ( curve) ) ;
422413 self . status = Some ( StatusMessage :: FittingInProgress ) ;
423414 }
424- Ok ( IncrementalSplineFitStep :: Finished ( result) ) => {
415+ Ok ( IncrementalSplineFitStep :: Finished { result, metrics } ) => {
425416 self . fit_in_progress = false ;
426417 let knot_y = result. knots . iter ( ) . map ( |knot| knot[ 1 ] ) . collect :: < Vec < _ > > ( ) ;
427418 let spline_plot_curve =
428419 Self :: plot_points_from_pairs ( result. curve . iter ( ) . copied ( ) ) ;
429420 self . update_spline_result_metrics ( & result) ;
430- let metrics = result. iteration_metrics_snapshot ( self . fit_loss_metric ) ;
431421 self . iteration_diagnostics
432422 . append_spline ( result. iterations , metrics, & knot_y) ;
433423 self . upsert_spline_replay_frame ( result. iterations , spline_plot_curve) ;
@@ -464,6 +454,7 @@ impl CurveFitApp {
464454 normalization,
465455 optimizer_config,
466456 loss_metric,
457+ metric_quantization,
467458 cancel_flag,
468459 } = input;
469460 let ( tx, rx) = mpsc:: channel ( ) ;
@@ -477,12 +468,14 @@ impl CurveFitApp {
477468 let progress_cancel = cancel_flag. clone ( ) ;
478469 let progress_points = Arc :: new ( display_points) ;
479470 let callback_points = Arc :: clone ( & progress_points) ;
480- let result = fit_curve_with_progress_and_optimizer_config_and_loss_metric (
471+ let result =
472+ fit_curve_with_progress_and_optimizer_config_and_loss_metric_and_metric_quantization (
481473 & optimization_points,
482474 family,
483475 optimization_initial_params,
484476 & optimizer_config,
485477 loss_metric,
478+ metric_quantization,
486479 move |iteration, params| {
487480 if progress_cancel. load ( Ordering :: Relaxed ) {
488481 return false ;
@@ -496,10 +489,11 @@ impl CurveFitApp {
496489 } else {
497490 params
498491 } ;
499- let metrics = calculate_iteration_metrics (
492+ let metrics = calculate_iteration_metrics_with_quantization (
500493 callback_points. as_ref ( ) ,
501494 & params,
502495 loss_metric,
496+ metric_quantization,
503497 ) ;
504498 let _ = iter_tx. send ( FitWorkerMessage :: Iteration {
505499 iteration,
@@ -524,7 +518,11 @@ impl CurveFitApp {
524518 } else {
525519 result. params
526520 } ;
527- let ( mse, rmse) = calculate_metrics ( progress_points. as_ref ( ) , & params) ;
521+ let ( mse, rmse) = calculate_metrics_with_quantization (
522+ progress_points. as_ref ( ) ,
523+ & params,
524+ metric_quantization,
525+ ) ;
528526 let _ = tx. send ( FitWorkerMessage :: Finished ( FitResult {
529527 family : result. family ,
530528 params,
@@ -554,6 +552,7 @@ impl CurveFitApp {
554552 cancel_flag : Arc < AtomicBool > ,
555553 ) {
556554 let loss_metric = self . fit_loss_metric ;
555+ let metric_quantization = self . fit_metric_quantization ;
557556 let ( tx, rx) = mpsc:: channel ( ) ;
558557 self . fit_worker_rx = Some ( rx) ;
559558 self . fit_cancel_flag = Some ( cancel_flag. clone ( ) ) ;
@@ -569,6 +568,7 @@ impl CurveFitApp {
569568 & optimizer_config,
570569 Some ( initial_knot_y. as_slice ( ) ) ,
571570 loss_metric,
571+ metric_quantization,
572572 ) {
573573 Ok ( runner) => runner,
574574 Err ( error) => {
@@ -597,8 +597,8 @@ impl CurveFitApp {
597597 curve,
598598 } ) ;
599599 }
600- Ok ( IncrementalSplineFitStep :: Finished ( result) ) => {
601- let _ = tx. send ( FitWorkerMessage :: SplineFinished ( result) ) ;
600+ Ok ( IncrementalSplineFitStep :: Finished { result, metrics } ) => {
601+ let _ = tx. send ( FitWorkerMessage :: SplineFinished { result, metrics } ) ;
602602 break ;
603603 }
604604 Ok ( IncrementalSplineFitStep :: Cancelled ) | Err ( FitError :: Cancelled ) => {
@@ -635,6 +635,14 @@ impl CurveFitApp {
635635 } ;
636636 let loss_metric = self . optimization_loss_metric ;
637637 self . fit_loss_metric = loss_metric;
638+ let metric_quantization = match self . selected_metric_quantization ( ) {
639+ Ok ( metric_quantization) => metric_quantization,
640+ Err ( error) => {
641+ self . status = Some ( StatusMessage :: Error ( error) ) ;
642+ return ;
643+ }
644+ } ;
645+ self . fit_metric_quantization = metric_quantization;
638646
639647 let selected_model = self . resolved_model ( ) ;
640648 if let Some ( spline_family) = selected_model. spline_family ( ) {
@@ -687,6 +695,7 @@ impl CurveFitApp {
687695 & optimizer_config,
688696 Some ( initial_knot_y. as_slice ( ) ) ,
689697 loss_metric,
698+ metric_quantization,
690699 ) {
691700 Ok ( runner) => {
692701 self . wasm_fit_job =
@@ -753,8 +762,12 @@ impl CurveFitApp {
753762 // Очищаем предыдущий успешный результат только когда новый запуск уже валиден.
754763 self . clear_fit_outputs ( ) ;
755764 self . active_fit_points = Some ( points. clone ( ) ) ;
756- self . iteration_diagnostics
757- . initialize ( & points, & initial_params, loss_metric) ;
765+ self . iteration_diagnostics . initialize (
766+ & points,
767+ & initial_params,
768+ loss_metric,
769+ metric_quantization,
770+ ) ;
758771 self . upsert_parametric_replay_frame ( 0 , initial_params. clone ( ) ) ;
759772 self . status = Some ( StatusMessage :: FittingInProgress ) ;
760773
@@ -769,18 +782,20 @@ impl CurveFitApp {
769782 normalization,
770783 optimizer_config,
771784 loss_metric,
785+ metric_quantization,
772786 cancel_flag,
773787 } ) ;
774788 }
775789
776790 #[ cfg( target_arch = "wasm32" ) ]
777791 {
778- match IncrementalFitRunner :: new_with_optimizer_config_and_loss_metric (
792+ match IncrementalFitRunner :: new_with_optimizer_config_and_loss_metric_and_metric_quantization (
779793 & optimization_points,
780794 family,
781795 optimization_initial_params,
782796 & optimizer_config,
783797 loss_metric,
798+ metric_quantization,
784799 ) {
785800 Ok ( runner) => {
786801 self . wasm_fit_job = Some ( WasmFitJob :: Deferred ( WasmFitRunner :: Parametric {
0 commit comments