Skip to content

Commit 2c3ab8f

Browse files
rename to plot
1 parent 869ac71 commit 2c3ab8f

1 file changed

Lines changed: 226 additions & 0 deletions

File tree

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# Generate Plot from Picture
2+
3+
Upload an image of a plot and ask Claude Code to recreate it!
4+
5+
![Claude Logo](../assets/images/claude-logo.svg)
6+
7+
## Input
8+
9+
Upload the image below to Claude Code.
10+
11+
![Distribution of Electricity Plot - Input](../assets/images/examples/distribution-of-electricity-input.png)
12+
13+
Then ask Claude to recreate it using the HoloViz ecosystem:
14+
15+
```text
16+
Please study the attached image carefully including styling, labels, grids, annotations, titles etc. Then plan how to recreate it using the HoloViz ecosystem. Please hide the bokeh logo and autohide the bokeh tools. The tools should only be shown when I hover over the plot.
17+
```
18+
19+
When the plan is ready, ask Claude to implement it:
20+
21+
```text
22+
Please implement the plan.
23+
```
24+
25+
## Result
26+
27+
Not perfect, but a really good starting point.
28+
29+
![Distribution of Electricity Plot - Output](../assets/images/examples/distribution-of-electricity-output.png)
30+
31+
<details><summary>Code</summary>
32+
33+
```python
34+
import numpy as np
35+
import pandas as pd
36+
import holoviews as hv
37+
from holoviews import opts
38+
39+
# Configure HoloViews with Bokeh backend, hide logo
40+
hv.extension('bokeh', logo=False)
41+
42+
43+
def generate_electricity_data():
44+
"""
45+
Generate synthetic 24-hour electricity consumption data.
46+
Returns DataFrame with 96 data points (15-minute intervals).
47+
"""
48+
# Create time range: 00:00 to 23:45 in 15-minute intervals
49+
times = pd.date_range('2024-01-01 00:00', '2024-01-01 23:45', freq='15min')
50+
51+
# Create realistic consumption pattern
52+
hours = np.arange(0, 24, 0.25) # 96 points
53+
54+
# Base consumption pattern
55+
consumption = np.zeros(96)
56+
57+
# Overnight low (00:00-06:00): ~250-300W
58+
consumption[:24] = 270 + np.random.normal(0, 10, 24)
59+
60+
# Morning rise (06:00-07:30): gradual increase
61+
consumption[24:30] = np.linspace(280, 450, 6) + np.random.normal(0, 10, 6)
62+
63+
# Morning peak (07:30-08:00): ~540W
64+
consumption[30:32] = 540 + np.random.normal(0, 15, 2)
65+
66+
# Morning decline (08:00-10:30): gradual decrease
67+
consumption[32:42] = np.linspace(520, 400, 10) + np.random.normal(0, 15, 10)
68+
69+
# Daytime plateau (10:30-17:30): ~380-420W
70+
consumption[42:70] = 400 + np.random.normal(0, 15, 28)
71+
72+
# Evening rise (17:30-20:00): steep increase to peak
73+
consumption[70:80] = np.linspace(400, 800, 10) + np.random.normal(0, 20, 10)
74+
75+
# Evening peak (20:00-20:30): ~800W
76+
consumption[80:82] = 800 + np.random.normal(0, 15, 2)
77+
78+
# Evening decline (20:30-23:45): gradual decrease
79+
consumption[82:] = np.linspace(780, 400, 14) + np.random.normal(0, 20, 14)
80+
81+
# Ensure no negative values
82+
consumption = np.maximum(consumption, 0)
83+
84+
df = pd.DataFrame({
85+
'time': times,
86+
'consumption': consumption
87+
})
88+
89+
return df
90+
91+
92+
def create_plot():
93+
"""
94+
Create the electricity distribution visualization with all elements.
95+
"""
96+
# Generate data
97+
df = generate_electricity_data()
98+
99+
# Define peak periods for coloring
100+
# Morning peak: ~07:00-10:30 (indices 28-42)
101+
# Evening peak: ~17:30-21:30 (indices 70-86)
102+
103+
# Create VSpan elements for shaded pink regions
104+
morning_vspan = hv.VSpan(
105+
pd.Timestamp('2024-01-01 07:00'),
106+
pd.Timestamp('2024-01-01 10:30')
107+
).opts(
108+
color='#ffcccc',
109+
alpha=0.3
110+
)
111+
112+
evening_vspan = hv.VSpan(
113+
pd.Timestamp('2024-01-01 17:30'),
114+
pd.Timestamp('2024-01-01 21:30')
115+
).opts(
116+
color='#ffcccc',
117+
alpha=0.3
118+
)
119+
120+
# Create colored line segments
121+
# Define segments: [start_idx, end_idx, color]
122+
segments = [
123+
(0, 28, '#2ca02c'), # Green: 00:00-07:00
124+
(28, 42, '#d62728'), # Red: 07:00-10:30 (morning peak)
125+
(42, 70, '#2ca02c'), # Green: 10:30-17:30
126+
(70, 86, '#d62728'), # Red: 17:30-21:30 (evening peak)
127+
(86, 96, '#2ca02c'), # Green: 21:30-23:45
128+
]
129+
130+
# Create curve and scatter overlays for each segment
131+
plot_elements = []
132+
133+
for start_idx, end_idx, color in segments:
134+
segment_df = df.iloc[start_idx:end_idx]
135+
136+
# Create curve (line)
137+
curve = hv.Curve(
138+
segment_df,
139+
kdims=['time'],
140+
vdims=['consumption']
141+
).opts(
142+
color=color,
143+
line_width=2
144+
)
145+
146+
# Create scatter (markers)
147+
scatter = hv.Scatter(
148+
segment_df,
149+
kdims=['time'],
150+
vdims=['consumption']
151+
).opts(
152+
color=color,
153+
size=7,
154+
marker='o'
155+
)
156+
157+
plot_elements.append(curve * scatter)
158+
159+
# Combine all line segments
160+
line_plot = plot_elements[0]
161+
for element in plot_elements[1:]:
162+
line_plot = line_plot * element
163+
164+
# Create text annotations
165+
text_morning = hv.Text(
166+
pd.Timestamp('2024-01-01 08:45'),
167+
820,
168+
'Morning Peak'
169+
).opts(
170+
text_font_size='12pt',
171+
text_align='center'
172+
)
173+
174+
text_fake = hv.Text(
175+
pd.Timestamp('2024-01-01 12:00'),
176+
820,
177+
'Fake Data'
178+
).opts(
179+
text_font_size='12pt',
180+
text_align='center'
181+
)
182+
183+
text_evening = hv.Text(
184+
pd.Timestamp('2024-01-01 19:30'),
185+
820,
186+
'Evening Peak'
187+
).opts(
188+
text_font_size='12pt',
189+
text_align='center'
190+
)
191+
192+
# Combine all elements: VSpans at back, then lines, then text on top
193+
final_plot = (
194+
morning_vspan * evening_vspan *
195+
line_plot *
196+
text_morning * text_fake * text_evening
197+
)
198+
199+
# Apply global plot options
200+
final_plot = final_plot.opts(
201+
opts.Overlay(
202+
width=1200,
203+
height=600,
204+
title='Distribution of Electricity',
205+
xlabel='',
206+
ylabel='W',
207+
ylim=(0, 850),
208+
show_grid=True,
209+
toolbar='above',
210+
active_tools=['pan', 'wheel_zoom'],
211+
backend_opts={'toolbar.autohide': True}
212+
)
213+
)
214+
215+
return final_plot
216+
217+
218+
# Create and display the plot
219+
create_plot()
220+
```
221+
222+
</details>
223+
224+
## Credits
225+
226+
The original plot is from [ECharts Examples](https://echarts.apache.org/examples/en/index.html).

0 commit comments

Comments
 (0)