This commit is contained in:
NY 2025-03-05 11:18:21 +08:00
parent 938aa3ea8d
commit 60bbbd40d0
3 changed files with 59 additions and 43 deletions

View File

@ -113,7 +113,7 @@ def layout_config(app):
dcc.Tabs(id='tabs', value='line', children=[
dcc.Tab(label='Line Chart', value='line'),
dcc.Tab(label='Heatmap', value='heatmap'),
dcc.Tab(label='Scatter Plot', value='scatter'),
dcc.Tab(label='One Day Heatmap Plot', value='one_day_heatmap'),
]),
html.Div(id='tabs-content'),
], style={'marginLeft': '50px'}),

View File

@ -7,7 +7,7 @@ from dash import dcc
import plotly.graph_objs as go
import pandas as pd
# Callback for updating tabs content (Modified to add Thursday-Friday lines)
@app.callback(
[Output('tabs-content', 'children'),
Output('multi-day-warning', 'children'),
@ -20,7 +20,7 @@ import pandas as pd
)
def render_tab_content(tab, selected_dates, interval, time_zones, days_to_display):
warning = ""
if tab != 'heatmap':
if tab == 'line':
if len(selected_dates) > 10:
selected_dates = selected_dates[:10]
warning = "Maximum of 10 days can be selected. Showing first 10 selected days."
@ -89,43 +89,57 @@ def render_tab_content(tab, selected_dates, interval, time_zones, days_to_displa
yaxis=dict(autorange='reversed')
)
elif tab == 'scatter':
fig = go.Figure()
for date in selected_dates:
day_data = multi_data_raw[multi_data_raw['date'] == date]
if not day_data.empty:
hover_times = [t.strftime('%Y-%m-%d %H:%M:%S EST') for t in day_data['datetime_est']]
fig.add_trace(go.Scatter(
x=day_data['minute_of_day'],
y=[str(date)] * len(day_data),
mode='markers',
name=str(date),
customdata=hover_times,
hovertemplate='%{customdata}<extra></extra>',
marker=dict(size=8)
elif tab == 'one_day_heatmap':
one_day_data = agg_data.groupby('interval_group')['tweet_count'].sum().reset_index()
hours = list(range(24))
intervals_per_hour = 60 // interval
z_values = [[0] * intervals_per_hour for _ in range(24)]
for _, row in one_day_data.iterrows():
minute = row['interval_group']
hour = int(minute // 60) # Convert to integer
interval_idx = int((minute % 60) // interval) # Convert to integer
if hour < 24:
z_values[hour][interval_idx] = row['tweet_count']
x_labels = [f"{i * interval:02d}" for i in range(intervals_per_hour)]
fig = go.Figure(data=go.Heatmap(
z=z_values,
x=x_labels,
y=[f"{h:02d}:00" for h in hours],
colorscale='Viridis',
hoverongaps=False,
hovertemplate='%{y} %{x} EST<br>Tweets: %{z}<extra></extra>'
))
if tab in ['line', 'scatter']:
# Add time zone annotations if selected
if 'PST' in time_zones:
pacific_2am_est = (2 + 3) * 60
pacific_7am_est = (7 + 3) * 60
pacific_2am_est = (2 + 3) * 60 // interval
pacific_7am_est = (7 + 3) * 60 // interval
fig.add_vline(x=pacific_2am_est, line_dash="dash", line_color="blue", annotation_text="CA 2AM PST")
fig.add_vline(x=pacific_7am_est, line_dash="dash", line_color="blue", annotation_text="CA 7AM PST")
if 'CST' in time_zones:
central_2am_est = (2 + 1) * 60
central_7am_est = (7 + 1) * 60
central_2am_est = (2 + 1) * 60 // interval
central_7am_est = (7 + 1) * 60 // interval
fig.add_vline(x=central_2am_est, line_dash="dash", line_color="green", annotation_text="TX 2AM CST")
fig.add_vline(x=central_7am_est, line_dash="dash", line_color="green", annotation_text="TX 7AM CST")
if tab in ['line', 'scatter']:
if tab in ['line', 'one_day_heatmap']:
fig.update_layout(
title=f'{"Line" if tab == "line" else "Scatter"} Tweet Frequency (Interval: {interval} minutes, EST)',
xaxis_title='Eastern Time (HH:MM)',
yaxis_title='Tweet Count' if tab == 'line' else 'Date',
xaxis=dict(range=[0, 1440], tickvals=xticks, ticktext=xtick_labels, tickangle=45),
title=f'{"Line" if tab == "line" else "One-Day Heatmap"} Tweet Frequency (Interval: {interval} minutes, EST, {len(selected_dates)} days)',
xaxis_title='Minutes' if tab == 'one_day_heatmap' else 'Eastern Time (HH:MM)',
yaxis_title='Hour of Day' if tab == 'one_day_heatmap' else 'Tweet Count',
xaxis=dict(
range=[0, 1440] if tab == 'line' else None,
tickvals=xticks if tab == 'line' else None,
ticktext=xtick_labels if tab == 'line' else None,
tickangle=45 if tab == 'line' else 0
),
height=600,
showlegend=True,
yaxis=dict(autorange='reversed') if tab == 'scatter' else None
showlegend=(tab == 'line'),
yaxis=dict(autorange='reversed') if tab == 'one_day_heatmap' else None
)
summary = f"Total tweets for selected dates: {int(tweet_count_total)}"

View File

@ -1,12 +1,14 @@
from pkg.dash.app_init import app
from dash.dependencies import Input, Output
@app.callback(
[Output('date-picker-container', 'style'),
Output('days-display-container', 'style')],
Output('days-display-container', 'style'),
Output('time-zone-checklist', 'style')],
[Input('tabs', 'value')]
)
def toggle_controls_visibility(tab):
if tab == 'heatmap':
return {'display': 'none'}, {'display': 'block'}
return {'display': 'block'}, {'display': 'none'}
if tab == 'heatmap' or tab == 'one_day_heatmap':
return {'display': 'none'}, {'display': 'block'}, {'display': 'none'}
return {'display': 'block'}, {'display': 'none'}, {'display': 'block'}