openfree commited on
Commit
a6302b0
ยท
verified ยท
1 Parent(s): ea8be35

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -74
app.py CHANGED
@@ -45,104 +45,84 @@ def half_sine(xs, period, amp):
45
  return y
46
 
47
  def build_chart(start: int, end: int):
48
- """Return (Plotly figure, summary string) for the requested year range."""
 
49
  xs = np.linspace(start, end, max(1000, (end - start) * 4))
50
  fig = go.Figure()
51
 
52
- # โ—ผ 1) Draw gradient half-sine โ€˜towersโ€™ (30 layers each, like old matplotlib version)
53
  for period in ORDERED_PERIODS:
54
- base_amp = AMPL[period]
55
- color = COLOR[period]
56
-
57
- # โ”€โ”€ gradient layers (thin, semi-transparent) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
58
  for frac in np.linspace(base_amp / 30, base_amp, 30):
59
- ys = half_sine(xs, period, frac)
60
  fig.add_trace(go.Scatter(
61
- x = xs,
62
- y = ys,
63
- mode = "lines",
64
- line = dict(color=color, width=0.8),
65
- opacity = 0.6,
66
- hoverinfo = "skip",
67
- showlegend = False
68
- ))
69
-
70
- # โ”€โ”€ outer edge line (slightly thicker) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
71
- ys = half_sine(xs, period, base_amp)
72
  fig.add_trace(go.Scatter(
73
- x = xs,
74
- y = ys,
75
- mode = "lines",
76
- line = dict(color=color, width=1.6),
77
- hoverinfo = "skip",
78
- showlegend = False
79
- ))
80
-
81
- # โ—ผ 2) Event markers with bilingual hover text โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
82
  for year, evs in EVENTS.items():
83
  if start <= year <= end:
84
- cycle_name = evs[0]["cycle"]
85
- period = PERIOD_BY_CYCLE.get(cycle_name, 50)
86
- y_val = float(half_sine(np.array([year]), period, AMPL[period]))
87
- txt_en = "<br>".join(e["event_en"] for e in evs)
88
- txt_ko = "<br>".join(e["event_ko"] for e in evs)
89
-
90
  fig.add_trace(go.Scatter(
91
- x = [year], y = [y_val],
92
- mode = "markers",
93
- marker = dict(color="white", size=6),
94
- customdata = [[cycle_name, txt_en, txt_ko]],
95
- hovertemplate = (
 
96
  "Year %{x} โ€ข %{customdata[0]} cycle"
97
  "<br>%{customdata[1]}"
98
  "<br>%{customdata[2]}<extra></extra>"
99
  ),
100
- showlegend = False
101
- ))
102
-
103
- # โ—ผ 3) Cosmetic touches: centre line, 250-yr arrow, background, axes โ”€โ”€โ”€โ”€
104
- # centre alignment marker
105
- fig.add_vline(
106
- x = CENTER,
107
- line_dash = "dash",
108
- line_color = "white",
109
- opacity = 0.6
110
- )
111
-
112
- # 250-year span arrow (โ†”) across the top of chart
113
  arrow_y = AMPL[250] * 1.05
114
  fig.add_annotation(
115
- x = CENTER - 125, y = arrow_y,
116
- ax = CENTER + 125, ay = arrow_y,
117
- xref = "x", yref = "y", axref = "x", ayref = "y",
118
- showarrow = True,
119
- arrowhead = 3,
120
- arrowsize = 1,
121
- arrowwidth = 1.2,
122
- arrowcolor = "white"
123
- )
124
  fig.add_annotation(
125
- x = CENTER, y = arrow_y + 0.15,
126
- text = "250 yr",
127
- showarrow = False,
128
- font = dict(color="white", size=10)
129
- )
130
 
131
- # global styling
132
  fig.update_layout(
133
- template = "plotly_dark",
134
- paper_bgcolor = "black",
135
- plot_bgcolor = "black",
136
- height = 450,
137
- margin = dict(t=30, l=40, r=40, b=40),
138
- hoverlabel = dict(bgcolor="#222", font_size=11)
139
  )
140
  fig.update_xaxes(title="Year", range=[start, end], showgrid=False)
141
- fig.update_yaxes(title="Relative amplitude", showticklabels=False, showgrid=False)
 
142
 
143
- summary = f"Range {start}-{end} | Events plotted: {sum(1 for y in EVENTS if start <= y <= end)}"
 
144
  return fig, summary
145
 
 
146
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
147
  # 4. GPT chat helper
148
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
45
  return y
46
 
47
  def build_chart(start: int, end: int):
48
+ """Return (Plotly figure, summary string) for the requested year range,
49
+ plus a transparent hover-trace so the cursor always shows โ€˜Year ####โ€™. """
50
  xs = np.linspace(start, end, max(1000, (end - start) * 4))
51
  fig = go.Figure()
52
 
53
+ # 1) Gradient half-sine towers
54
  for period in ORDERED_PERIODS:
55
+ base_amp, color = AMPL[period], COLOR[period]
 
 
 
56
  for frac in np.linspace(base_amp / 30, base_amp, 30):
 
57
  fig.add_trace(go.Scatter(
58
+ x=xs, y=half_sine(xs, period, frac),
59
+ mode="lines",
60
+ line=dict(color=color, width=0.8),
61
+ opacity=0.6,
62
+ hoverinfo="skip", showlegend=False))
 
 
 
 
 
 
63
  fig.add_trace(go.Scatter(
64
+ x=xs, y=half_sine(xs, period, base_amp),
65
+ mode="lines",
66
+ line=dict(color=color, width=1.6),
67
+ hoverinfo="skip", showlegend=False))
68
+
69
+ # 2) Event markers (bilingual hover)
 
 
 
70
  for year, evs in EVENTS.items():
71
  if start <= year <= end:
72
+ cyc = evs[0]["cycle"]; period = PERIOD_BY_CYCLE[cyc]
73
+ y_val = float(half_sine(np.array([year]), period, AMPL[period]))
 
 
 
 
74
  fig.add_trace(go.Scatter(
75
+ x=[year], y=[y_val], mode="markers",
76
+ marker=dict(color="white", size=6),
77
+ customdata=[[cyc,
78
+ "<br>".join(e["event_en"] for e in evs),
79
+ "<br>".join(e["event_ko"] for e in evs)]],
80
+ hovertemplate=(
81
  "Year %{x} โ€ข %{customdata[0]} cycle"
82
  "<br>%{customdata[1]}"
83
  "<br>%{customdata[2]}<extra></extra>"
84
  ),
85
+ showlegend=False))
86
+
87
+ # 3) Transparent hover-trace so any x shows โ€˜Year ####โ€™
88
+ fig.add_trace(go.Scatter(
89
+ x=xs,
90
+ y=np.full_like(xs, -0.05), # just below baseline
91
+ mode="lines",
92
+ line=dict(color="rgba(0,0,0,0)", width=1), # invisible
93
+ hovertemplate="Year %{x:.0f}<extra></extra>",
94
+ showlegend=False))
95
+
96
+ # 4) Cosmetic touches: centre line & 250-yr arrow
97
+ fig.add_vline(x=CENTER, line_dash="dash", line_color="white", opacity=0.6)
98
  arrow_y = AMPL[250] * 1.05
99
  fig.add_annotation(
100
+ x=CENTER-125, y=arrow_y, ax=CENTER+125, ay=arrow_y,
101
+ xref="x", yref="y", axref="x", ayref="y",
102
+ showarrow=True, arrowhead=3, arrowsize=1,
103
+ arrowwidth=1.2, arrowcolor="white")
 
 
 
 
 
104
  fig.add_annotation(
105
+ x=CENTER, y=arrow_y+0.15, text="250 yr",
106
+ showarrow=False, font=dict(color="white", size=10))
 
 
 
107
 
108
+ # 5) Layout
109
  fig.update_layout(
110
+ template="plotly_dark",
111
+ paper_bgcolor="black", plot_bgcolor="black",
112
+ height=450,
113
+ margin=dict(t=30, l=40, r=40, b=40),
114
+ hoverlabel=dict(bgcolor="#222", font_size=11),
115
+ hovermode="x" # โ† unified x-hover
116
  )
117
  fig.update_xaxes(title="Year", range=[start, end], showgrid=False)
118
+ fig.update_yaxes(title="Relative amplitude",
119
+ showticklabels=False, showgrid=False)
120
 
121
+ summary = f"Range {start}-{end} | Events plotted: " \
122
+ f"{sum(1 for y in EVENTS if start <= y <= end)}"
123
  return fig, summary
124
 
125
+
126
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
127
  # 4. GPT chat helper
128
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€