From e3591e0823bbd8ff2e1447eceafbe745d91b23ad Mon Sep 17 00:00:00 2001
From: Alexandre <44178713+alexbelgium@users.noreply.github.com>
Date: Wed, 30 Oct 2024 13:25:54 +0100
Subject: [PATCH] Full annotated code
---
scripts/dynamic_plot.py | 115 ++++++++++++++++++++++++----------------
1 file changed, 68 insertions(+), 47 deletions(-)
diff --git a/scripts/dynamic_plot.py b/scripts/dynamic_plot.py
index dd256aadd..9f3fd9aa6 100644
--- a/scripts/dynamic_plot.py
+++ b/scripts/dynamic_plot.py
@@ -4,19 +4,36 @@
import numpy as np
from datetime import datetime
import os
-from utils.helpers import get_settings # Import to access COLOR_SCHEME
-
-# Define custom colorscales for light and dark modes
-COLOR_SCALES = {
- "light": [
- [0.0, '#E0F2E9'], [0.2, '#A3D8A1'], [0.4, '#70BD70'],
- [0.6, '#46A846'], [0.8, '#2E7D2E'], [1.0, '#004D00']
- ],
- "dark": [
- [0.0, '#F0F0F0'], [0.2, '#BDBDBD'], [0.4, '#969696'],
- [0.6, '#737373'], [0.8, '#525252'], [1.0, '#252525']
- ]
-}
+from utils.helpers import get_settings # Import if needed for other settings
+
+# Fetch color scheme setting and choose corresponding colorscale and text color
+conf = get_settings()
+color_scheme = conf.get('COLOR_SCHEME', 'light')
+
+if color_scheme == 'dark':
+ PLOT_BGCOLOR='#F0F0F0'
+ PAPER_BGCOLOR='#7F7F7F'
+ CUSTOM_COLOR_SCALE = [
+ [0.0, PLOT_BGCOLOR],
+ [0.2, '#BDBDBD'],
+ [0.4, '#969696'],
+ [0.6, '#737373'],
+ [0.8, '#525252'],
+ [1.0, '#252525']
+ ]
+else:
+ PLOT_BGCOLOR='#FFFFFF'
+ PAPER_BGCOLOR='#7BC58A'
+ CUSTOM_COLOR_SCALE = [
+ [0.0, PLOT_BGCOLOR],
+ [0.1, '#E0F2E9'],
+ [0.2, '#A3D8A1'],
+ [0.4, '#70BD70'],
+ [0.6, '#46A846'],
+ [0.8, '#2E7D2E'],
+ [1.0, '#004D00']
+ ]
+
ALL_HOURS = list(range(24))
@@ -28,9 +45,9 @@ def normalize_logarithmic(arr):
return np.log(arr / min_val) / np.log(np.max(arr) / min_val) if np.max(arr) > min_val else arr - min_val
-def determine_text_color(z, threshold=0.5):
- """Determines text color (black or white) based on normalized value of z."""
- return np.where(z > threshold, 'white', 'black')
+def determine_text_color(z, threshold=0.8):
+ """Determines text color (darkgrey or white) based on normalized value of z."""
+ return np.where(z == 0, PLOT_BGCOLOR, np.where(z > threshold, PLOT_BGCOLOR, '#1A1A1A'))
def add_annotations(fig, text_array, text_colors, col, row, species_list, all_hours, annotations):
@@ -41,7 +58,7 @@ def add_annotations(fig, text_array, text_colors, col, row, species_list, all_ho
if current_text:
annotations.append(dict(
x=0, y=species, text=current_text, showarrow=False,
- font=dict(color=current_color, size=10),
+ font=dict(color=current_color, size=12),
xref=f'x{col}', yref=f'y{col}', xanchor='center', yanchor='middle'
))
elif col == 3: # Multi-column heatmap
@@ -51,7 +68,7 @@ def add_annotations(fig, text_array, text_colors, col, row, species_list, all_ho
if current_text:
annotations.append(dict(
x=hour, y=species, text=current_text, showarrow=False,
- font=dict(color=current_color, size=10),
+ font=dict(color=current_color, size=12),
xref='x3', yref='y3', xanchor='center', yanchor='middle'
))
@@ -74,11 +91,6 @@ def create_plotly_heatmap(df_birds, now):
Conf=('Confidence', 'max')
).reset_index().fillna({'Conf': 0, 'Count': 0})
- # Fetch color scheme setting and choose corresponding colorscale and text color
- conf = get_settings()
- color_scheme = conf.get('COLOR_SCHEME', 'light')
- color_scale = COLOR_SCALES.get(color_scheme, COLOR_SCALES["light"])
-
# Summarize data for heatmap axes
df_birds_summary = plot_dataframe.groupby('Com_Name').agg(
Count=('Count', 'sum'),
@@ -89,58 +101,70 @@ def create_plotly_heatmap(df_birds, now):
species_list = df_birds_summary['Com_Name'].tolist()
# Normalize values and prepare text annotations
- z_confidence = normalize_logarithmic(df_birds_summary['Conf'].values.reshape(-1, 1) * 100)
- text_confidence = np.char.add(np.round(df_birds_summary['Conf'].values).astype(int).astype(str), ' %')
+ z_confidence = normalize_logarithmic(df_birds_summary['Conf'].values.reshape(-1, 1)) * 100
+ text_confidence = np.char.add((df_birds_summary['Conf'].values * 100).round().astype(int).astype(str), ' %')
z_detections = normalize_logarithmic(df_birds_summary['Count'].values.reshape(-1, 1))
text_detections = df_birds_summary['Count'].astype(str).values # Use actual counts for annotations
- text_color_detections = determine_text_color(z_detections, threshold=0.5, color_scheme=color_scheme)
+ text_color_detections = determine_text_color(z_detections, threshold=0.5) # Removed color_scheme
df_hourly = plot_dataframe.pivot_table(index='Com_Name', columns='Hour', values='Count', aggfunc='sum').fillna(0)
df_hourly = df_hourly.reindex(species_list).fillna(0).reindex(columns=ALL_HOURS, fill_value=0)
z_hourly = normalize_logarithmic(df_hourly.values)
text_hourly = df_hourly.astype(int).astype(str).values # Use actual counts for hourly annotations
- text_color_hourly = determine_text_color(z_hourly, threshold=0.5, color_scheme=color_scheme)
+ text_color_hourly = determine_text_color(z_hourly, threshold=0.5) # Removed color_scheme
# Create subplots
fig = make_subplots(rows=1, cols=3, shared_yaxes=True, column_widths=[0.1, 0.1, 0.7], horizontal_spacing=0.02)
- # Heatmap Traces
+ # Prepare structured customdata arrays for each heatmap trace
+ custom_data_confidence = np.array([{'confidence': conf * 100} for conf in df_birds_summary['Conf'].values]).reshape(-1, 1)
+ custom_data_count = np.array([{'count': count} for count in df_birds_summary['Count'].values]).reshape(-1, 1)
+
+ # Add traces with updated customdata structure and hovertemplate
fig.add_trace(go.Heatmap(
- z=z_confidence, customdata=df_birds_summary['Conf'].values, x=['Confidence'], y=species_list,
- colorscale=color_scale, showscale=False, hovertemplate='Species: %{y}
Max Confidence: %{customdata:.0f}%',
+ z=z_confidence, customdata=custom_data_confidence, x=['Confidence'], y=species_list,
+ colorscale=CUSTOM_COLOR_SCALE, showscale=False,
+ hovertemplate='Species: %{y}
Max Confidence: %{customdata.confidence:.0f}%',
xgap=1, ygap=1, zmin=0, zmax=1
), row=1, col=1)
-
+
fig.add_trace(go.Heatmap(
- z=z_detections, customdata=df_birds_summary['Count'].values, x=['Count'], y=species_list,
- colorscale=color_scale, showscale=False, hovertemplate='Species: %{y}
Total Counts: %{customdata}',
+ z=z_detections, customdata=custom_data_count, x=['Count'], y=species_list,
+ colorscale=CUSTOM_COLOR_SCALE, showscale=False,
+ hovertemplate='Species: %{y}
Total Counts: %{customdata.count}',
xgap=1, ygap=1, zmin=0, zmax=1
), row=1, col=2)
fig.add_trace(go.Heatmap(
z=z_hourly, customdata=df_hourly.values, x=ALL_HOURS, y=species_list,
- colorscale=color_scale, showscale=False, hovertemplate='Species: %{y}
Hour: %{x}
Detections: %{customdata}',
+ colorscale=CUSTOM_COLOR_SCALE, showscale=False, hovertemplate='Species: %{y}
Hour: %{x}
Detections: %{customdata}',
xgap=1, ygap=1, zmin=0, zmax=1
), row=1, col=3)
# Annotations
annotations = []
- add_annotations(fig, text_confidence.reshape(-1, 1), determine_text_color(z_confidence, threshold=0.5, color_scheme=color_scheme), col=1, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
- add_annotations(fig, text_detections.reshape(-1, 1), text_color_detections, col=2, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
- add_annotations(fig, text_hourly, text_color_hourly, col=3, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
+ add_annotations(fig, text_confidence.reshape(-1, 1), determine_text_color(z_confidence, threshold=0.5),
+ col=1, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
+ add_annotations(fig, text_detections.reshape(-1, 1), text_color_detections,
+ col=2, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
+ add_annotations(fig, text_hourly, text_color_hourly,
+ col=3, row=1, species_list=species_list, all_hours=ALL_HOURS, annotations=annotations)
fig.update_layout(annotations=annotations)
# Layout configuration
fig.update_layout(
- title=dict(text=f"{main_title}
{subtitle}", x=0.5, y=0.97, xanchor='center', yanchor='top', font=dict(size=24)),
+ title=dict(text=f"{main_title}
{subtitle}",
+ x=0.5, y=0.97, xanchor='center', yanchor='top', font=dict(size=24)),
autosize=True, height=max(600, len(species_list) * 25 + 100),
- yaxis=dict(autorange='reversed', tickfont=dict(size=10), showticklabels=True, ticklabelstandoff=15, fixedrange=True),
- xaxis1=dict(title='Max confidence', showticklabels=False, title_font=dict(size=10), fixedrange=True),
- xaxis2=dict(title='Total counts', showticklabels=False, title_font=dict(size=10), fixedrange=True),
- xaxis3=dict(title='Hour', tickfont=dict(size=10), tickmode='linear', dtick=1, fixedrange=True),
- margin=dict(l=20, r=20, t=80, b=80), clickmode='event+select',
- plot_bgcolor='#CCCCCC', paper_bgcolor='#7F7F7F', font=dict(size=10), dragmode=False
+ yaxis=dict(autorange='reversed', tickfont=dict(size=12), showticklabels=True, ticklabelstandoff=15, fixedrange=True),
+ xaxis1=dict(title='Max Confidence', showticklabels=False, title_font=dict(size=12), fixedrange=True),
+ xaxis2=dict(title='Total Counts', showticklabels=False, title_font=dict(size=12), fixedrange=True),
+ xaxis3=dict(title='Hour', tickfont=dict(size=12), tickmode='linear', dtick=1, fixedrange=True),
+ margin=dict(l=20, r=20, t=80, b=80), clickmode='event+select',
+ plot_bgcolor=PAPER_BGCOLOR,
+ paper_bgcolor=PAPER_BGCOLOR,
+ font=dict(size=12, color='#000000'), dragmode=False
)
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
@@ -197,6 +221,3 @@ def create_plotly_heatmap(df_birds, now):
os.makedirs(output_dir, exist_ok=True)
with open(os.path.join(output_dir, 'interactive_daily_plot.html'), 'w') as f:
f.write(html_str)
-
- # Clear figure to reset layout and prevent issues in future runs
- fig.clear()