Skip to content

Commit b0156b3

Browse files
feat(highcharts): implement sn-curve-basic (#7525)
## Implementation: `sn-curve-basic` - python/highcharts Implements the **python/highcharts** version of `sn-curve-basic`. **File:** `plots/sn-curve-basic/implementations/python/highcharts.py` **Parent Issue:** #3826 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/26168794164)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 004f38d commit b0156b3

2 files changed

Lines changed: 123 additions & 102 deletions

File tree

plots/sn-curve-basic/implementations/python/highcharts.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" anyplot.ai
22
sn-curve-basic: S-N Curve (Wöhler Curve)
33
Library: highcharts unknown | Python 3.13.13
4-
Quality: 87/100 | Updated: 2026-05-20
4+
Quality: 89/100 | Updated: 2026-05-20
55
"""
66

77
import os
@@ -15,6 +15,7 @@
1515
from highcharts_core.options import HighchartsOptions
1616
from highcharts_core.options.series.area import LineSeries
1717
from highcharts_core.options.series.scatter import ScatterSeries
18+
from PIL import Image
1819
from selenium import webdriver
1920
from selenium.webdriver.chrome.options import Options
2021

@@ -73,10 +74,11 @@
7374
"height": 1800,
7475
"backgroundColor": PAGE_BG,
7576
"style": {"fontFamily": "Arial, sans-serif", "color": INK},
76-
"marginBottom": 120,
77+
"marginBottom": 140,
7778
"marginLeft": 150,
7879
"marginRight": 80,
7980
"marginTop": 100,
81+
"plotBorderWidth": 0,
8082
}
8183

8284
chart.options.title = {
@@ -92,7 +94,7 @@
9294
"color": "rgba(213,94,0,0.07)",
9395
"label": {
9496
"text": "Low-Cycle Fatigue",
95-
"style": {"fontSize": "32px", "color": INK_SOFT},
97+
"style": {"fontSize": "36px", "color": INK_SOFT},
9698
"align": "center",
9799
"verticalAlign": "top",
98100
"y": 30,
@@ -104,7 +106,7 @@
104106
"color": "rgba(0,114,178,0.05)",
105107
"label": {
106108
"text": "High-Cycle Fatigue",
107-
"style": {"fontSize": "32px", "color": INK_SOFT},
109+
"style": {"fontSize": "36px", "color": INK_SOFT},
108110
"align": "center",
109111
"verticalAlign": "top",
110112
"y": 30,
@@ -116,7 +118,7 @@
116118
"color": "rgba(0,158,115,0.06)",
117119
"label": {
118120
"text": "Infinite Life",
119-
"style": {"fontSize": "32px", "color": INK_SOFT},
121+
"style": {"fontSize": "36px", "color": INK_SOFT},
120122
"align": "center",
121123
"verticalAlign": "top",
122124
"y": 30,
@@ -151,40 +153,40 @@
151153
"plotLines": [
152154
{
153155
"value": ultimate_strength,
154-
"color": "#E53935",
156+
"color": "#CC79A7",
155157
"width": 4,
156158
"dashStyle": "Dash",
157159
"label": {
158160
"text": f"Ultimate Strength ({ultimate_strength} MPa)",
159-
"align": "right",
160-
"style": {"fontSize": "34px", "color": "#E53935", "fontWeight": "bold"},
161-
"x": -10,
161+
"align": "left",
162+
"style": {"fontSize": "34px", "color": "#CC79A7", "fontWeight": "bold"},
163+
"x": 10,
162164
},
163165
"zIndex": 3,
164166
},
165167
{
166168
"value": yield_strength,
167-
"color": "#FB8C00",
169+
"color": "#E69F00",
168170
"width": 4,
169171
"dashStyle": "Dash",
170172
"label": {
171173
"text": f"Yield Strength ({yield_strength} MPa)",
172-
"align": "right",
173-
"style": {"fontSize": "34px", "color": "#FB8C00", "fontWeight": "bold"},
174-
"x": -10,
174+
"align": "left",
175+
"style": {"fontSize": "34px", "color": "#E69F00", "fontWeight": "bold"},
176+
"x": 10,
175177
},
176178
"zIndex": 3,
177179
},
178180
{
179181
"value": endurance_limit,
180-
"color": "#43A047",
182+
"color": "#56B4E9",
181183
"width": 4,
182184
"dashStyle": "Dash",
183185
"label": {
184186
"text": f"Endurance Limit ({endurance_limit} MPa)",
185-
"align": "right",
186-
"style": {"fontSize": "34px", "color": "#43A047", "fontWeight": "bold"},
187-
"x": -10,
187+
"align": "left",
188+
"style": {"fontSize": "34px", "color": "#56B4E9", "fontWeight": "bold"},
189+
"x": 10,
188190
},
189191
"zIndex": 3,
190192
},
@@ -201,7 +203,7 @@
201203
"verticalAlign": "top",
202204
"layout": "vertical",
203205
"x": -60,
204-
"y": 100,
206+
"y": 140,
205207
}
206208

207209
chart.options.plot_options = {
@@ -253,16 +255,28 @@
253255
temp_path = f.name
254256

255257
chrome_options = Options()
256-
chrome_options.add_argument("--headless")
258+
chrome_options.add_argument("--headless=new")
257259
chrome_options.add_argument("--no-sandbox")
258260
chrome_options.add_argument("--disable-dev-shm-usage")
259261
chrome_options.add_argument("--disable-gpu")
262+
chrome_options.add_argument("--hide-scrollbars")
260263
chrome_options.add_argument("--window-size=3200,1800")
261264

262265
driver = webdriver.Chrome(options=chrome_options)
266+
# CDP override makes the viewport authoritative; --window-size alone is eaten by Chrome chrome
267+
driver.execute_cdp_cmd(
268+
"Emulation.setDeviceMetricsOverride", {"width": 3200, "height": 1800, "deviceScaleFactor": 1, "mobile": False}
269+
)
263270
driver.get(f"file://{temp_path}")
264271
time.sleep(5)
265272
driver.save_screenshot(f"plot-{THEME}.png")
266273
driver.quit()
267274

268275
Path(temp_path).unlink()
276+
277+
# PIL safety net: pin to exact 3200×1800 in case of ±1-2 px rounding
278+
_img = Image.open(f"plot-{THEME}.png").convert("RGB")
279+
if _img.size != (3200, 1800):
280+
_norm = Image.new("RGB", (3200, 1800), PAGE_BG)
281+
_norm.paste(_img, ((3200 - _img.size[0]) // 2, (1800 - _img.size[1]) // 2))
282+
_norm.save(f"plot-{THEME}.png")

0 commit comments

Comments
 (0)