Skip to content

Commit 7063ad4

Browse files
Merge pull request #44 from ISISComputingGroup/fixes_linear_fitting
Fixes issues found with linear fitting guess function
2 parents e031857 + 33bfa13 commit 7063ad4

File tree

4 files changed

+31
-41
lines changed

4 files changed

+31
-41
lines changed

doc/fitting/fitting.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ See the following example on how to define these.
111111

112112
import lmfit
113113

114-
def model(x: float, m: float, c: float) -> float:
114+
def model(x: float, c1: float, c0: float) -> float:
115115

116-
return m * x + c # y = mx + c
116+
return c1 * x + c0 # y = mx + c
117117

118118
def guess(x: npt.NDArray[np.float64], y: npt.NDArray[np.float64]) -> dict[str, lmfit.Parameter]:
119119

@@ -125,12 +125,12 @@ def guess(x: npt.NDArray[np.float64], y: npt.NDArray[np.float64]) -> dict[str, l
125125
numerator = sum(x * y) - sum(x) * sum(y)
126126
denominator = sum(x**2) - sum(x) ** 2
127127

128-
m = numerator / denominator
129-
c = (sum(y) - m * sum(x)) / len(x)
128+
c1 = numerator / denominator
129+
c0 = (sum(y) - c1 * sum(x)) / len(x)
130130

131131
init_guess = {
132-
"m": lmfit.Parameter("m", m), # gradient
133-
"c": lmfit.Parameter("c", c), # y - intercept
132+
"c1": lmfit.Parameter("c1", c1), # gradient
133+
"c0": lmfit.Parameter("c0", c0), # y - intercept
134134
}
135135

136136
return init_guess
@@ -155,9 +155,9 @@ This means that aslong as the parameters returned from the guess function match
155155
import lmfit
156156
from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear
157157

158-
def different_model(x: float, m: float, c: float) -> float:
158+
def different_model(x: float, c1: float, c0: float) -> float:
159159

160-
return m * x + c ** 2 # y = mx + (c ** 2)
160+
return c1 * x + c0 ** 2 # y = mx + (c ** 2)
161161

162162

163163
fit_method = FitMethod(different_model, Linear.guess())
@@ -176,11 +176,11 @@ from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear
176176
# This Guessing. function isn't very good because it's return values don't change on the data already collected in the Bluesky run
177177
# It always guesses that the linear function is y = x
178178

179-
def different_guess(x: float, m: float, c: float) -> float:
179+
def different_guess(x: float, c1: float, c0: float) -> float:
180180

181181
init_guess = {
182-
"m": lmfit.Parameter("m", 1), # gradient
183-
"c": lmfit.Parameter("c", 0), # y - intercept
182+
"c1": lmfit.Parameter("c1", 1), # gradient
183+
"c0": lmfit.Parameter("c0", 0), # y - intercept
184184
}
185185

186186
return init_guess

doc/fitting/standard_fits.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
## Linear
44

5-
- `m` - Gradient
6-
- `c` - (y) Intercept
5+
- `c1` - Gradient
6+
- `c0` - (y) Intercept
77

88
```{math}
9-
y = mx + c
9+
y = c_1x + c_0
1010
```
1111

1212
## Polynomial
1313

14-
- `a` ... `d` - Polynomial coefficients
14+
- `cn` ... `c0` - Polynomial coefficients
1515

1616
For a polynomial degree `n`:
1717
```{math}
18-
y = ax^n + bx^n-1 + ... + cx^1 + d
18+
y = c_{n}x^n + c_{n-1}x^n-1 + ... + c_1 * x^1 + c_0
1919
```
2020

2121
## Gaussian

src/ibex_bluesky_core/callbacks/fitting/fitting_utils.py

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ class Linear(Fit):
179179
def model(cls, *args: int) -> lmfit.Model:
180180
"""Linear Model."""
181181

182-
def model(x: npt.NDArray[np.float64], m: float, c: float) -> npt.NDArray[np.float64]:
183-
return m * x + c
182+
def model(x: npt.NDArray[np.float64], c1: float, c0: float) -> npt.NDArray[np.float64]:
183+
return c1 * x + c0
184184

185185
return lmfit.Model(model)
186186

@@ -189,25 +189,8 @@ def guess(
189189
cls, *args: int
190190
) -> Callable[[npt.NDArray[np.float64], npt.NDArray[np.float64]], dict[str, lmfit.Parameter]]:
191191
"""Linear Guessing."""
192-
193-
def guess(
194-
x: npt.NDArray[np.float64], y: npt.NDArray[np.float64]
195-
) -> dict[str, lmfit.Parameter]:
196-
# Linear Regression
197-
numerator = sum(x * y) - sum(x) * sum(y)
198-
denominator = sum(x**2) - sum(x) ** 2
199-
200-
m = numerator / denominator
201-
c = (sum(y) - m * sum(x)) / len(x)
202-
203-
init_guess = {
204-
"m": lmfit.Parameter("m", m),
205-
"c": lmfit.Parameter("c", c),
206-
}
207-
208-
return init_guess
209-
210-
return guess
192+
return Polynomial.guess(1)
193+
# Uses polynomial guessing with a degree of 1
211194

212195

213196
class Polynomial(Fit):

tests/callbacks/fitting/test_fitting_methods.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def test_linear_model(self):
219219
grad = 3
220220
y_intercept = 2
221221

222-
outp = Linear.model().func(x, m=grad, c=y_intercept)
222+
outp = Linear.model().func(x, c1=grad, c0=y_intercept)
223223

224224
# Check for constant gradient of grad
225225
outp_m = np.diff(outp)
@@ -234,19 +234,26 @@ def test_gradient_guess(self):
234234
y = np.array([-1.0, 0.0, 1.0])
235235
outp = Linear.guess()(x, y)
236236

237-
assert pytest.approx(outp["m"]) == 1.0
237+
assert pytest.approx(outp["c1"]) == 1.0
238238

239239
y = np.array([-2.0, 0.0, 2.0])
240240
outp1 = Linear.guess()(x, y)
241241
# check with a graph with steeper gradient
242-
assert outp["m"] < outp1["m"]
242+
assert outp["c1"] < outp1["c1"]
243243

244244
def test_y_intercept_guess(self):
245245
x = np.array([-1.0, 0.0, 1.0])
246246
y = np.array([-1.0, 0.0, 1.0])
247247
outp = Linear.guess()(x, y)
248248

249-
assert pytest.approx(outp["c"]) == 0.0
249+
assert pytest.approx(outp["c0"]) == 0.0
250+
251+
def test_zero_gradient_guess(self):
252+
x = np.array([-1.0, 0.0, 1.0])
253+
y = np.array([0.0, 0.0, 0.0])
254+
outp = Linear.guess()(x, y)
255+
256+
assert pytest.approx(outp["c1"]) == 0.0
250257

251258

252259
class TestPolynomial:

0 commit comments

Comments
 (0)