Skip to content

Commit ef1621e

Browse files
authored
chore: Update python, major deps, fix plotting (#234)
1 parent 375f259 commit ef1621e

File tree

9 files changed

+381
-322
lines changed

9 files changed

+381
-322
lines changed

.github/workflows/analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
- name: Setup Python
5757
uses: actions/setup-python@v5
5858
with:
59-
python-version: "3.12"
59+
python-version: "3.13"
6060
- name: Install requirements
6161
run: |
6262
pip install .

frontend/Dockerfile.app

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### BUILDER IMAGE ###
22
# syntax=docker/dockerfile:1
3-
FROM python:3.12-slim AS BUILDER
3+
FROM python:3.13-slim AS BUILDER
44

55
# set environment variables
66
ENV LANG=C.UTF-8
@@ -23,7 +23,7 @@ COPY rctool/ ./rctool
2323
RUN pip install . --no-cache-dir
2424

2525
### APP IMAGE ###
26-
FROM python:3.12-slim AS APP
26+
FROM python:3.13-slim AS APP
2727
WORKDIR /app
2828

2929
# set environment variables

frontend/Dockerfile.nginx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### BUILDER IMAGE ###
22
# syntax=docker/dockerfile:1
3-
FROM python:3.12-slim AS BUILDER
3+
FROM python:3.13-slim AS BUILDER
44
WORKDIR /app
55

66
# set environment variables

frontend/poetry.lock

Lines changed: 274 additions & 250 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ authors = [
88
readme = "README.md"
99

1010
[tool.poetry.dependencies]
11-
python = ">=3.12,<3.13"
11+
python = ">=3.13,<3.14"
1212
django = "^5.0.3"
1313
scikit-learn = "^1.4.1"
1414
scipy = "^1.12.0"
@@ -19,7 +19,7 @@ matplotlib = "^3.8.3"
1919
gunicorn = "^23.0.0"
2020
pip = "^24.0"
2121
setuptools = "^75.0.0"
22-
numpy = ">1.26.0,<2.0.0"
22+
numpy = "^2.2.2"
2323

2424
[build-system]
2525
requires = ["poetry-core"]

frontend/rctool/functions/fit_linear_model.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ def fit_linear_model(df, offset, label, weighted=None, intersect_points=None, *a
3737
params.add(constraint_name, expr=constraint_expression)
3838

3939
result = plm.fit(df_data["Q"], params, x=df_data["H0"])
40-
41-
unw_const = result.best_values["amplitude"]
42-
unw_exp = result.best_values["exponent"]
40+
41+
unw_const = float(result.best_values["amplitude"])
42+
unw_exp = float(result.best_values["exponent"])
4343
unw_best = result.best_fit
4444

4545
unw_residual = list(
@@ -57,8 +57,8 @@ def fit_linear_model(df, offset, label, weighted=None, intersect_points=None, *a
5757

5858
# try weighting
5959
result = plm.fit(df_data["Q"], params, x=df_data["H0"], weights=df_data["W"])
60-
wgt_const = result.best_values["amplitude"]
61-
wgt_exp = result.best_values["exponent"]
60+
wgt_const = float(result.best_values["amplitude"])
61+
wgt_exp = float(result.best_values["exponent"])
6262
wgt_best = result.best_fit
6363
wgt_sigs = result.eval_uncertainty(sigma=2)
6464
wgt_residual = list(
@@ -111,7 +111,7 @@ def fit_linear_model(df, offset, label, weighted=None, intersect_points=None, *a
111111
"mape": wgt_mape,
112112
}
113113
wgt_data = [
114-
[a, b, c] for a, b, c in zip(df_data["H"].tolist(), wgt_best, wgt_residual)
114+
[float(a), float(b), float(c)] for a, b, c in zip(df_data["H"].tolist(), wgt_best, wgt_residual)
115115
]
116116
mdl_data = [{"label": label, "data": wgt_data}]
117117
else:
@@ -126,7 +126,7 @@ def fit_linear_model(df, offset, label, weighted=None, intersect_points=None, *a
126126
"mape": unw_mape,
127127
}
128128
unw_data = [
129-
[a, b, c] for a, b, c in zip(df_data["H"].tolist(), unw_best, unw_residual)
129+
[float(a), float(b), float(c)] for a, b, c in zip(df_data["H"].tolist(), unw_best, unw_residual)
130130
]
131131
mdl_data = [{"label": label, "data": unw_data}]
132132

frontend/rctool/templates/rctool/rctool/develop/rctool_develop_js.html

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,14 @@
195195
var fieldDataFiltered = rawFieldData.filter(item => ( item[0] >= segmentData[0][0] && item[0] <= segmentData[1][0]));
196196

197197

198-
// 3.2 Calculate model data from new rc equation, collect and prepaire output
198+
// 3.2 Calculate model data from new rc equation, collect and prepare output
199199
var stage = fieldDataFiltered.map( item => (item[0]));
200200
var q_field = fieldDataFiltered.map( item => (item[1]));
201201
var q_model = stage.map(s => C * (s - offset) ** slope);
202202
// Calculate statistical parameters; residuals
203203
var newResiduals = fieldDataFiltered.map(item => ( 100 * (C * (item[0] - offset) ** slope - item[1]) / item[1] ) );
204204

205-
// Collect and prepaire output
205+
// Collect and prepare output
206206
var newSegData = [];
207207
for (let t = 0; t < q_model.length; t++) {
208208
newSegData.push([stage[t], q_model[t], newResiduals[t]]);
@@ -214,7 +214,13 @@
214214
});
215215

216216
// 3.3 Update residualData
217-
residualData[idx+1].data = newSegData;
217+
try {
218+
residualData[idx+1].data = newSegData;
219+
} catch {
220+
// this is likely a manual segment, skip it
221+
continue
222+
}
223+
218224
// add boundary points to segment data (for plotting on rcChart)
219225
newSegData.unshift([segmentData[0][0], segmentData[0][1], 0]);
220226
newSegData.push([segmentData[1][0], segmentData[1][1], 0]);
@@ -361,6 +367,13 @@
361367
offset_thisline = offsetData[rc_trueidx]
362368
param = rcDict.parameters[rc_trueidx]
363369

370+
// in case a manual segment is defined, skip it
371+
if (param == undefined) {
372+
// TODO: this breaks interpolation for the manual segment
373+
// FIX: get parameters from the correct data, rcDict shouldn't be used here
374+
continue
375+
}
376+
364377
// create an array that will be used to calculate the line point positions
365378
const arr = [];
366379
for (let i = 0; i < 1; i += 1/interpolation_points)
@@ -987,13 +1000,13 @@
9871000
// Get filtered field data within segment bounds (used with to calculate RMSE and residuals)
9881001
var rawFieldData = rcData[0]['data'];
9891002
var fieldDataFiltered = rawFieldData.filter(item => ( item[0] >= compStartBounds && item[0] <= compEndBounds));
990-
// Calculate model data from new rc equation, collect and prepaire output
1003+
// Calculate model data from new rc equation, collect and prepare output
9911004
var stage = fieldDataFiltered.map( item => (item[0]));
9921005
var q_field_compare = fieldDataFiltered.map( item => (item[1]));
9931006
var q_model_compare = stage.map(s => compConst * (s - compOffset) ** compExp);
9941007
// Calculate statistical parameters; residuals
995-
var compResiduals = fieldDataFiltered.map(item => ( 100 * (compConst * (item[0] - compOffset) ** compExp - item[1]) / item[1] ) );
996-
// Collect and prepaire output
1008+
var compResiduals = fieldDataFiltered.map(item => ( -100 * (compConst * (item[0] - compOffset) ** compExp - item[1]) / item[1] ) );
1009+
// Collect and prepare output
9971010
var compData = [];
9981011
for (let t = 0; t < q_model_compare.length; t++) {
9991012
compData.push([stage[t], q_model_compare[t], compResiduals[t]]);
@@ -1007,12 +1020,22 @@
10071020
compRcData = [...compData];
10081021
compRcData.unshift([lowerH, lowerQ, 0])
10091022
compRcData.push([upperH, upperQ, 0])
1023+
1024+
// 2.9 interpolate data for residual chart
1025+
var stageInterpolated = [];
1026+
for (let i = 0; i < interpolation_points; i++) {
1027+
stageInterpolated.push(lowerH + i * (upperH - lowerH) / interpolation_points);
1028+
}
1029+
var q_model_interpolated = stageInterpolated.map(s => compConst * (s - compOffset) ** compExp);
1030+
10101031
// 3. Calculate statistical parameters; RMSE
10111032
stats_compare = calculate_stats(q_field_compare, q_model_compare)
10121033

1013-
// 4. Prepaire output
1014-
var compChartData = compRcData.map(item => ({ x: item[1], y: item[0] }));
1034+
// 4. Prepare output
1035+
var compChartData = stageInterpolated.map((item, index) => ({ x: q_model_interpolated[index], y: item }));
10151036
var compResChartData = compData.map(item => ({ x: item[2], y: item[0] }));
1037+
// 4.1 Sort by x value
1038+
compChartData.sort((a, b) => a.x - b.x);
10161039

10171040
// 5. If data is calculated, plot on RC chart and residual chart
10181041
if (compChartData.length > 1) {
@@ -1201,6 +1224,11 @@
12011224
// prevent dragging
12021225
return false
12031226
}
1227+
1228+
// prevent dragging of manually added comparison curves
1229+
if (dataset.backgroundColor === '#DDCC77') {
1230+
return false
1231+
}
12041232

12051233
// hide interpolation line for current RC curve:
12061234
var datasetLabel = dataset.label

frontend/rctool/tests.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,4 @@ def test_export_rc_data_form(self):
196196
)
197197
# check if the output is a pdf:
198198
assert response_output.status_code == 200
199-
assert response_output["Content-Type"] == "application/pdf"
200-
201-
def test_numpy_version(self):
202-
# numpy version has to be 1 to avoid formatting problems with float numbers output by numpy. Would take a lot of refactoring otherwise...
203-
np_version = np.__version__.split(".")[0]
204-
print(f"numpy version: {np_version}")
205-
assert np_version == "1"
199+
assert response_output["Content-Type"] == "application/pdf"

0 commit comments

Comments
 (0)