|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | column-stratigraphic: Stratigraphic Column with Lithology Patterns |
3 | 3 | Library: highcharts unknown | Python 3.14.3 |
4 | 4 | Quality: 83/100 | Created: 2026-03-15 |
|
11 | 11 | from collections import OrderedDict |
12 | 12 | from pathlib import Path |
13 | 13 |
|
| 14 | +from highcharts_core.chart import Chart |
14 | 15 | from selenium import webdriver |
15 | 16 | from selenium.webdriver.chrome.options import Options |
16 | 17 |
|
|
102 | 103 | "d": "M 8 8 m -5 0 a 5 5 0 1 0 10 0 a 5 5 0 1 0 -10 0 " |
103 | 104 | "M 20 18 m -3.5 0 a 3.5 3.5 0 1 0 7 0 a 3.5 3.5 0 1 0 -7 0 " |
104 | 105 | "M 19 5 m -2.5 0 a 2.5 2.5 0 1 0 5 0 a 2.5 2.5 0 1 0 -5 0", |
105 | | - "stroke": "#6B4226", |
| 106 | + "stroke": "#5C3A6E", |
106 | 107 | "strokeWidth": 2, |
107 | 108 | "fill": "none", |
108 | 109 | }, |
109 | 110 | "width": 26, |
110 | 111 | "height": 26, |
111 | | - "backgroundColor": "#D4A76A", |
| 112 | + "backgroundColor": "#C4A0D4", |
112 | 113 | } |
113 | 114 | }, |
114 | 115 | }, |
|
136 | 137 | "type": "columnrange", |
137 | 138 | "width": 4800, |
138 | 139 | "height": 2700, |
139 | | - "backgroundColor": "#ffffff", |
140 | | - "marginLeft": 380, |
141 | | - "marginRight": 700, |
142 | | - "marginTop": 220, |
143 | | - "marginBottom": 180, |
| 140 | + "backgroundColor": "#FAFAF8", |
| 141 | + "marginLeft": 340, |
| 142 | + "marginRight": 480, |
| 143 | + "marginTop": 200, |
| 144 | + "marginBottom": 130, |
| 145 | + "style": {"fontFamily": "'Segoe UI', Helvetica, Arial, sans-serif"}, |
144 | 146 | }, |
145 | 147 | "title": { |
146 | 148 | "text": "column-stratigraphic \u00b7 highcharts \u00b7 pyplots.ai", |
147 | | - "style": {"fontSize": "56px", "fontWeight": "bold"}, |
| 149 | + "style": {"fontSize": "52px", "fontWeight": "bold", "color": "#2C3E50"}, |
148 | 150 | }, |
149 | 151 | "subtitle": { |
150 | 152 | "text": "Synthetic Sedimentary Section \u2014 Colorado Plateau Stratigraphy", |
151 | | - "style": {"fontSize": "36px", "color": "#666666"}, |
| 153 | + "style": {"fontSize": "34px", "color": "#7F8C8D"}, |
152 | 154 | }, |
153 | | - "xAxis": {"categories": [""], "visible": False}, |
| 155 | + "xAxis": {"visible": False, "min": -0.25, "max": 1.3}, |
154 | 156 | "yAxis": { |
155 | 157 | "reversed": True, |
156 | | - "title": {"text": "Depth (m)", "style": {"fontSize": "44px", "color": "#333333"}, "margin": 30}, |
157 | | - "labels": {"style": {"fontSize": "34px"}, "format": "{value}"}, |
| 158 | + "title": { |
| 159 | + "text": "Depth (m)", |
| 160 | + "style": {"fontSize": "42px", "color": "#2C3E50", "fontWeight": "600"}, |
| 161 | + "margin": 30, |
| 162 | + }, |
| 163 | + "labels": {"style": {"fontSize": "32px", "color": "#444444"}, "format": "{value}"}, |
158 | 164 | "min": 0, |
159 | | - "max": 200, |
| 165 | + "max": 204, |
160 | 166 | "tickInterval": 20, |
161 | 167 | "gridLineWidth": 1, |
162 | | - "gridLineColor": "rgba(0, 0, 0, 0.08)", |
| 168 | + "gridLineColor": "rgba(0, 0, 0, 0.06)", |
| 169 | + "lineWidth": 2, |
| 170 | + "lineColor": "#CCCCCC", |
163 | 171 | "plotBands": [ |
164 | 172 | { |
165 | 173 | "from": band["from"], |
|
168 | 176 | "label": { |
169 | 177 | "text": band["label"], |
170 | 178 | "align": "left", |
171 | | - "x": -170, |
| 179 | + "x": -160, |
172 | 180 | "verticalAlign": "middle", |
173 | 181 | "rotation": 270, |
174 | 182 | "style": {"fontSize": "30px", "fontWeight": "bold", "color": "#555555"}, |
|
177 | 185 | for band in age_bands |
178 | 186 | ], |
179 | 187 | "plotLines": [ |
180 | | - {"value": boundary, "color": "rgba(0, 0, 0, 0.3)", "width": 3, "dashStyle": "Dash", "zIndex": 5} |
| 188 | + {"value": boundary, "color": "rgba(0, 0, 0, 0.35)", "width": 3, "dashStyle": "Dash", "zIndex": 5} |
181 | 189 | for boundary in [18, 100, 142] |
182 | 190 | ], |
183 | 191 | }, |
|
186 | 194 | "layout": "vertical", |
187 | 195 | "align": "right", |
188 | 196 | "verticalAlign": "middle", |
189 | | - "x": -50, |
| 197 | + "x": -30, |
190 | 198 | "y": 0, |
191 | | - "itemStyle": {"fontSize": "28px"}, |
192 | | - "symbolHeight": 24, |
193 | | - "symbolWidth": 24, |
194 | | - "itemMarginBottom": 14, |
195 | | - "title": {"text": "Lithology", "style": {"fontSize": "32px", "fontWeight": "bold"}}, |
| 199 | + "itemStyle": {"fontSize": "30px", "color": "#333333"}, |
| 200 | + "symbolHeight": 28, |
| 201 | + "symbolWidth": 28, |
| 202 | + "itemMarginBottom": 18, |
| 203 | + "title": {"text": "Lithology", "style": {"fontSize": "34px", "fontWeight": "bold", "color": "#2C3E50"}}, |
| 204 | + "backgroundColor": "rgba(255, 255, 255, 0.7)", |
| 205 | + "borderRadius": 8, |
| 206 | + "padding": 20, |
196 | 207 | }, |
197 | 208 | "tooltip": { |
198 | 209 | "style": {"fontSize": "26px"}, |
|
230 | 241 | "name": config["name"], |
231 | 242 | "data": data_points, |
232 | 243 | "color": config["color"], |
233 | | - "borderColor": "#333333", |
234 | | - "borderWidth": 3, |
235 | | - "pointWidth": 350, |
236 | | - "dataLabels": [ |
237 | | - { |
238 | | - "enabled": True, |
239 | | - "inside": False, |
240 | | - "align": "left", |
241 | | - "verticalAlign": "middle", |
242 | | - "x": 220, |
243 | | - "y": 0, |
244 | | - "format": "{point.custom.formation}", |
245 | | - "style": {"fontSize": "30px", "fontWeight": "600", "color": "#333333", "textOutline": "none"}, |
246 | | - "overflow": "allow", |
247 | | - "crop": False, |
248 | | - } |
249 | | - ], |
| 244 | + "borderColor": "#2C3E50", |
| 245 | + "borderWidth": 2.5, |
| 246 | + "pointWidth": 2200, |
250 | 247 | } |
251 | 248 | ) |
252 | 249 |
|
253 | | -# Generate JavaScript |
| 250 | +# Add formation name labels as a scatter series positioned to the right of the column |
| 251 | +formation_labels = [] |
| 252 | +for layer in layers: |
| 253 | + mid_depth = (layer["top"] + layer["bottom"]) / 2 |
| 254 | + formation_labels.append({"x": 0.68, "y": mid_depth, "name": layer["formation"]}) |
| 255 | + |
| 256 | +chart_config["series"].append( |
| 257 | + { |
| 258 | + "type": "scatter", |
| 259 | + "name": "Formations", |
| 260 | + "data": formation_labels, |
| 261 | + "showInLegend": False, |
| 262 | + "enableMouseTracking": False, |
| 263 | + "marker": {"enabled": False}, |
| 264 | + "dataLabels": { |
| 265 | + "enabled": True, |
| 266 | + "format": "{point.name}", |
| 267 | + "align": "left", |
| 268 | + "x": 10, |
| 269 | + "y": 4, |
| 270 | + "style": {"fontSize": "30px", "fontWeight": "600", "color": "#2C3E50", "textOutline": "3px #FAFAF8"}, |
| 271 | + "overflow": "allow", |
| 272 | + "crop": False, |
| 273 | + }, |
| 274 | + } |
| 275 | +) |
| 276 | + |
| 277 | +# Generate JavaScript - using raw JSON config because highcharts-core cannot |
| 278 | +# serialize SVG pattern path objects needed for lithology fills |
| 279 | +chart = Chart(container="container") |
254 | 280 | js_config = json.dumps(chart_config, ensure_ascii=False) |
255 | | -js_code = f"Highcharts.chart('container', {js_config});" |
| 281 | +js_code = f"Highcharts.chart('{chart.container}', {js_config});" |
256 | 282 |
|
257 | 283 | # Load Highcharts JS modules |
258 | 284 | highcharts_base = Path(__file__).resolve().parents[3] / "node_modules" / "highcharts" |
|
0 commit comments