waterdb / plotting_style_guide.md
github-actions[bot]
Deploy from GitHub Actions
e9832fd

A newer version of the Streamlit SDK is available: 1.57.0

Upgrade

State of the Bay Plotting Style Guide

This guide ensures consistency across all data visualizations in the State of the Bay project.

1. Layout and Sizing

Figure Dimensions

  • Standard plots: figsize=(12, 8)
  • Panel/faceted plots: figsize=(15, 2.5 * n_panels)
  • Use plt.tight_layout() for proper spacing
  • Arrange multi-panel plots vertically for better comparison

2. Colors and Visual Elements

Color Palette

  • Use predefined COLOR_SCALE for consistency
  • Grey tones:
    GREY30 = "#4d4d4d"  # Dark grey for titles
    GREY40 = "#666666"  # Medium grey for axes and labels
    
  • Use alpha transparency (0.5-0.7) for overlays

Line Styles

  • Trend lines: dashed (--), red, alpha=0.7, linewidth=1.5
  • Grid lines: light grey, alpha=0.15

3. Axes and Spines

Spine Configuration

# Remove unnecessary spines
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)

# Style bottom spine
ax.spines["bottom"].set_color(GREY40)
ax.spines["bottom"].set_linewidth(0.5)

# Remove tick marks but keep labels
ax.tick_params(axis="both", which="both", length=0, colors=GREY40)

4. Grid Lines

Configuration

ax.grid(True, axis="y", alpha=0.15, linestyle="-", color="gray")

5. Text Elements

Typography

  • Main titles: centered, size 12
  • Panel titles: size 10, color=GREY30, pad=10
  • Axis labels: size 10, color=GREY40

Statistics and Annotations

ax.text(
    0.02, 0.98,
    stats_text,
    transform=ax.transAxes,
    verticalalignment="top",
    fontsize=8,
    bbox=dict(facecolor="white", alpha=0.8, edgecolor="none")
)

6. Data Visualization

Line Charts

  • Include confidence intervals (shaded regions)
  • Solid lines for main trends
  • Consistent line thickness

Box Plots

boxplot_props = {
    "patch_artist": True,
    "medianprops": dict(color="black"),
    "flierprops": dict(
        marker="o",
        markerfacecolor=color_scale[idx],
        alpha=0.5,
        markersize=4
    ),
    "boxprops": dict(facecolor=color_scale[idx], alpha=0.6),
    "widths": 0.6
}

7. Scales and Ranges

Automatic Log Scaling

use_log_scale = parameter in [
    "Turbidity",
    "Fecal Coliform (MPN)",
    "Total Nitrogen",
    "Total Phosphorus",
]

Best Practices

  • Add padding to axis limits
  • Use consistent y-axis ranges across comparison panels
  • Handle edge cases gracefully

8. Function Structure

Return Values

def plot_function(df: pd.DataFrame, parameter: str) -> tuple[Figure, pd.DataFrame, pd.DataFrame]:
    """
    Create a visualization.

    Parameters:
    -----------
    df : pd.DataFrame
        Input dataframe
    parameter : str
        Parameter to plot

    Returns:
    --------
    tuple[Figure, pd.DataFrame, pd.DataFrame]
        - Figure: Matplotlib figure
        - DataFrame: Raw data used in plot
        - DataFrame: Processed data points
    """
    # ... plotting code ...
    return fig, raw_data, plot_data

9. Error Handling

Guidelines

  • Handle missing data gracefully
  • Include data validation
  • Provide appropriate fallbacks for edge cases
  • Log warnings for potential issues

10. Optional Features

Configurable Elements

def plot_function(
    df: pd.DataFrame,
    parameter: str,
    show_sem: bool = True,
    show_trend: bool = True,
    panel_chart: bool = False,
    color_scale: list[str] = COLOR_SCALE,
) -> tuple[Figure, pd.DataFrame, pd.DataFrame]:
    """..."""

Common Options

  • show_sem: Toggle standard error margins
  • show_trend: Toggle trend lines and statistics
  • panel_chart: Toggle between single and multi-panel layouts
  • color_scale: Override default color palette