From 60bbbd40d0fa0ff698c2ce55ff5d2b18fdea9f8a Mon Sep 17 00:00:00 2001 From: NY Date: Wed, 5 Mar 2025 11:18:21 +0800 Subject: [PATCH] fix --- pkg/dash/app_html.py | 2 +- pkg/dash/func/render.py | 90 ++++++++++++++++++++++++----------------- pkg/dash/func/ui.py | 10 +++-- 3 files changed, 59 insertions(+), 43 deletions(-) diff --git a/pkg/dash/app_html.py b/pkg/dash/app_html.py index 79a06f6..a555414 100644 --- a/pkg/dash/app_html.py +++ b/pkg/dash/app_html.py @@ -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'}), diff --git a/pkg/dash/func/render.py b/pkg/dash/func/render.py index 03a9a7d..f7b9c08 100644 --- a/pkg/dash/func/render.py +++ b/pkg/dash/func/render.py @@ -2,12 +2,12 @@ from datetime import datetime, timedelta from dash.dependencies import Input, Output from pkg.dash.app_init import app from pkg.config import render_data -from pkg.tool import aggregate_data,generate_xticks,minutes_to_time +from pkg.tool import aggregate_data, generate_xticks, minutes_to_time 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." @@ -81,52 +81,66 @@ def render_tab_content(tab, selected_dates, interval, time_zones, days_to_displa xref="x", yref="paper" ) - fig.update_layout( - title=f'Tweet Heatmap (Interval: {interval} minutes, EST, {len(selected_dates)} days)', - xaxis_title='Time of Day (HH:MM EST)', - yaxis_title='Date', - height=max(400, len(selected_dates) * 20), - yaxis=dict(autorange='reversed') - ) + fig.update_layout( + title=f'Tweet Heatmap (Interval: {interval} minutes, EST, {len(selected_dates)} days)', + xaxis_title='Time of Day (HH:MM EST)', + yaxis_title='Date', + height=max(400, len(selected_dates) * 20), + 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}', - marker=dict(size=8) - )) + elif tab == 'one_day_heatmap': + one_day_data = agg_data.groupby('interval_group')['tweet_count'].sum().reset_index() - if tab in ['line', 'scatter']: + 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
Tweets: %{z}' + )) + + # 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)}" - return dcc.Graph(figure=fig), warning, summary + return dcc.Graph(figure=fig), warning, summary \ No newline at end of file diff --git a/pkg/dash/func/ui.py b/pkg/dash/func/ui.py index c4b19cb..f447ff0 100644 --- a/pkg/dash/func/ui.py +++ b/pkg/dash/func/ui.py @@ -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'} \ No newline at end of file + if tab == 'heatmap' or tab == 'one_day_heatmap': + return {'display': 'none'}, {'display': 'block'}, {'display': 'none'} + return {'display': 'block'}, {'display': 'none'}, {'display': 'block'}