• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mantidproject / mantidimaging / 21907488825

11 Feb 2026 01:43PM UTC coverage: 69.085% (-0.2%) from 69.238%
21907488825

Pull #2883

github

web-flow
Merge e472667ed into edae31241
Pull Request #2883: 2549 read geometry data from files

2888 of 4510 branches covered (64.04%)

Branch coverage included in aggregate %.

36 of 66 new or added lines in 3 files covered. (54.55%)

572 existing lines in 13 files now uncovered.

10927 of 15487 relevant lines covered (70.56%)

0.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.91
/mantidimaging/core/fitting/fitting_engine.py
1
# Copyright (C) 2021 ISIS Rutherford Appleton Laboratory UKRI
2
# SPDX - License - Identifier: GPL-3.0-or-later
3
from __future__ import annotations
1✔
4

5
import numpy as np
1✔
6
from scipy.optimize import minimize
1✔
7

8
from mantidimaging.core.fitting.fitting_functions import BaseFittingFunction, FittingRegion
1✔
9

10
BoundType = tuple[float | None, float | None]
1✔
11

12

13
class FittingEngine:
1✔
14

15
    def __init__(self, model: BaseFittingFunction) -> None:
1✔
16
        self.model = model
1✔
17

18
    def set_fitting_model(self, model: BaseFittingFunction) -> None:
1✔
UNCOV
19
        self.model = model
×
20

21
    def get_parameter_names(self) -> list[str]:
1✔
22
        return list(self.model.parameter_names)
1✔
23

24
    def get_init_params_from_roi(self, region: FittingRegion) -> dict[str, float]:
1✔
25
        return self.model.get_init_params_from_roi(region)
1✔
26

27
    def find_best_fit(
1✔
28
        self,
29
        xdata: np.ndarray,
30
        ydata: np.ndarray,
31
        initial_params: list[float],
32
        params_bounds: list[BoundType] | None = None,
33
    ) -> tuple[dict[str, float], float, float]:
34
        """
35
        Fit the model to the given spectrum using unweighted least squares.
36

37
        Returns:
38
            - fit_params: dictionary of parameter names → fitted values
39
            - rss: residual sum of squares (Σ(residual²))
40
            - reduced_rss: rss / degrees of freedom, where DoF = N - p
41

42
        Notes:
43
            Uses the Nelder–Mead minimizer on the unweighted residuals.
44
        """
45

46
        additional_params = self.model.prefitting(xdata, ydata, initial_params)
1✔
47

48
        if additional_params:
1!
UNCOV
49
            params_to_fit = initial_params[:-len(additional_params)] + additional_params
×
50
        else:
51
            params_to_fit = initial_params
1✔
52

53
        def residual_sum_squares(params_subset):
1✔
54
            residuals = self.model.evaluate(xdata, params_subset) - ydata
1✔
55
            return np.sum(residuals**2)
1✔
56

57
        result = minimize(residual_sum_squares, params_to_fit, method="Nelder-Mead", bounds=params_bounds)
1✔
58

59
        all_param_names = self.model.get_parameter_names()
1✔
60
        all_params = list(result.x)
1✔
61
        fit_params = dict(zip(all_param_names, all_params, strict=True))
1✔
62

63
        rss = float(result.fun)
1✔
64
        n_points = ydata.size
1✔
65
        dof = max(n_points - len(all_params), 1)
1✔
66
        reduced_rss = rss / dof
1✔
67

68
        return fit_params, rss, reduced_rss
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc