diff --git a/Dockerfile b/Dockerfile
index 03e5279..9abf256 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,18 +2,25 @@
# https://hub.docker.com/_/python
FROM python:3.11-slim
+# Allow statements and log messages to immediately appear in the Knative logs
+ENV PYTHONUNBUFFERED True
+
RUN apt-get update \
-&& apt-get install gcc -y \
-&& apt-get clean
+ && apt-get install --no-install-recommends -y gcc \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
-ENV APP_HOME /app
-WORKDIR $APP_HOME
+# Install pipenv
+RUN python -m pip install --upgrade pip \
+ && python -m pip install --no-cache-dir "pipenv>=2024.0,<2026.0"
+# Set working directory
+WORKDIR /app
-COPY . ./
+# Copy Pipfile and Pipfile.lock
+COPY Pipfile Pipfile.lock ./
-# Install production dependencies.
-RUN pip install --upgrade pip
-RUN pip install -r requirements.txt
+# Install dependencies
+RUN pipenv sync --deploy --system
EXPOSE 8080
diff --git a/docs/contributing/contributing.md b/docs/contributing/contributing.md
index 3018a69..103d52f 100644
--- a/docs/contributing/contributing.md
+++ b/docs/contributing/contributing.md
@@ -115,9 +115,7 @@ Before submitting a Pull Request, please make sure:
- You have installed project dependencies:
```bash
-npm install
-
-pipenv install -r requirements.txt
+pipenv sync
```
From the root directory, run:
diff --git a/pages/lib/extract_df.py b/pages/lib/extract_df.py
index ded1c78..75b8e06 100644
--- a/pages/lib/extract_df.py
+++ b/pages/lib/extract_df.py
@@ -444,10 +444,8 @@ def create_df(lst, file_name):
def convert_SI_to_IP(df: pd.DataFrame, name: str) -> None:
"""Convert SI to IP based on column name."""
if name not in df.columns:
- print(
- f"[convert_SI_to_IP] Column '{name}' not found in DataFrame. Skipping conversion."
- )
return
+
match name:
case (
Variables.DBT.col_name
diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py
index 36fd2d0..8b93053 100644
--- a/pages/lib/global_scheme.py
+++ b/pages/lib/global_scheme.py
@@ -1,62 +1,56 @@
import plotly.io as pio
-
+import numpy as np
from pages.lib.global_variables import Variables, VariableInfo
-# Colors Dictionary
-blue_red_yellow = ["#00b3ff", "#000082", "#ff0000", "#ffff00"]
-dry_humid = ["#ffe600", "#00c8ff", "#0000ff"]
-sun_colors = [
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
-]
-light_colors = ["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"]
-bright_colors = ["#730a8c", "#0d0db3", "#0f85be", "#0f85be", "#b11421", "#fdf130"]
-wind_speed_color = [
- "#ffffff",
- "#b2f2ff",
- "#33ddff",
- "#00aaff",
- "#0055ff",
- "#0000ff",
- "#aa00ff",
- "#ff00ff",
- "#cc0000",
- "#ffaa00",
-]
-wind_dir_color = ["#0072dd", "#00c420", "#eded00", "#be00d5", "#0072dd"]
-cloud_colors = [
- "#7ec9f3",
- "#e6eae9",
- "#c2c2c2",
-]
-utci_categories_color = [
- # Let first 10% (0.1) of the values have color rgb(0, 0, 0)
- [0, "#2B2977"],
- [0.0555, "#2B2977"],
- [0.0555, "#38429B"],
- [0.0555 + 0.111 * 1, "#38429B"],
- [0.0555 + 0.111 * 1, "#4253A4"],
- [0.0555 + 0.111 * 2, "#4253A4"],
- [0.0555 + 0.111 * 2, "#4B62AD"],
- [0.0555 + 0.111 * 3, "#4B62AD"],
- [0.0555 + 0.111 * 3, "#68B8E7"],
- [0.0555 + 0.111 * 4, "#68B8E7"],
- [0.0555 + 0.111 * 4, "#53B848"],
- [0.0555 + 0.111 * 5, "#53B848"],
- [0.0555 + 0.111 * 5, "#EE8522"],
- [0.0555 + 0.111 * 6, "#EE8522"],
- [0.0555 + 0.111 * 6, "#EA2C24"],
- [0.0555 + 0.111 * 7, "#EA2C24"],
- [0.0555 + 0.111 * 7, "#B12224"],
- [0.0555 + 0.111 * 8, "#B12224"],
- [0.0555 + 0.111 * 8, "#751613"],
- [1.0, "#751613"],
-]
+WIND_ROSE_BINS = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf]
+
+
+def _stepped_colorscale_from_bins(bins, colors):
+ """
+ Build a stepped colorscale from bin edges and colors.
+
+ Args:
+ bins: sequence/list of N+1 bin edges (ascending). The last edge may be np.inf.
+ colors: sequence/list of N colors, one per interval.
+
+ Returns:
+ List of (position, color) tuples for a Plotly colorscale with positions in [0, 1].
+ """
+ if len(bins) != len(colors) + 1:
+ raise ValueError(
+ f"Expected {len(colors) + 1} bin edges for {len(colors)} colors, "
+ f"got {len(bins)}"
+ )
+
+ if any(b2 < b1 for b1, b2 in zip(bins, bins[1:])):
+ raise ValueError("bins must be in non-decreasing order")
+
+ finite_edges = [b for b in bins if np.isfinite(b)]
+ if not finite_edges:
+ raise ValueError("All bin edges are non-finite; cannot build colorscale.")
+
+ vmin, vmax = finite_edges[0], finite_edges[-1]
+ span = (vmax - vmin) or 1.0
+
+ cs = []
+ for i, c in enumerate(colors):
+ left_edge, right_edge = bins[i], bins[i + 1]
+
+ left = 0.0 if not np.isfinite(left_edge) else (left_edge - vmin) / span
+ right = 1.0 if not np.isfinite(right_edge) else (right_edge - vmin) / span
+
+ left = max(0.0, min(1.0, float(left)))
+ right = max(0.0, min(1.0, float(right)))
+
+ cs.append((left, c))
+ cs.append((right, c))
+
+ return cs
+
+
+wind_speed_colorscale_rose = _stepped_colorscale_from_bins(
+ WIND_ROSE_BINS, Variables.WIND_SPEED.color
+)
# containers
container_row_center_full = "container-row row-center"
diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py
index baf12b8..b2a3a17 100644
--- a/pages/lib/global_variables.py
+++ b/pages/lib/global_variables.py
@@ -1,6 +1,54 @@
from dataclasses import dataclass
from typing import Optional, List, Any
+from enum import Enum
from config import UnitSystem
+from plotly.colors import sequential as pseq
+
+
+class ColorPalettes(Enum):
+ # Palettes
+ BLUE_RED_YELLOW = ["#00b3ff", "#000082", "#ff0000", "#ffff00"]
+ DRY_HUMID = ["#ffe600", "#00c8ff", "#0000ff"]
+ SUN_COLORS = [
+ "#293a59",
+ "#960c2c",
+ "#ff0000",
+ "#ff7b00",
+ "#fffc00",
+ "#ffff7b",
+ "#ffffff",
+ ]
+ LIGHT_COLORS = ["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"]
+ SKY_COVER_TRI = ["#08306b", "#7ec9f3", "#e6eae9"]
+
+ # Unit conversions
+ PA_TO_PSI = 0.000145038
+ WHM2_TO_BTU_FT2 = 0.3169983306
+ LUX_TO_FC = 0.0929
+
+ # UTCI category colorscale
+ UTCI_CATEGORIES_SCALE = [
+ [0, "#2B2977"],
+ [0.0555, "#2B2977"],
+ [0.0555, "#38429B"],
+ [0.1665, "#38429B"],
+ [0.1665, "#4253A4"],
+ [0.2775, "#4253A4"],
+ [0.2775, "#4B62AD"],
+ [0.3885, "#4B62AD"],
+ [0.3885, "#68B8E7"],
+ [0.4995, "#68B8E7"],
+ [0.4995, "#53B848"],
+ [0.6105, "#53B848"],
+ [0.6105, "#EE8522"],
+ [0.7215, "#EE8522"],
+ [0.7215, "#EA2C24"],
+ [0.8325, "#EA2C24"],
+ [0.8325, "#B12224"],
+ [0.9435, "#B12224"],
+ [0.9435, "#751613"],
+ [1.0, "#751613"],
+ ]
@dataclass
@@ -101,7 +149,7 @@ class Variables:
name="Dry bulb temperature",
unit="°C",
range=[-40, 50],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-40, 122]),
)
DPT = VariableInfo(
@@ -109,7 +157,7 @@ class Variables:
name="Dew point temperature",
unit="°C",
range=[-50, 35],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-58, 95]),
)
RH = VariableInfo(
@@ -117,7 +165,7 @@ class Variables:
name="Relative humidity",
unit="%",
range=[0, 100],
- color=["#ffe600", "#00c8ff", "#0000ff"],
+ color=ColorPalettes.DRY_HUMID.value,
)
P_ATM = VariableInfo(
@@ -137,7 +185,13 @@ class Variables:
"#cc0000",
"#ffaa00",
],
- IP=IP(unit="Psi", range=[95000 * 0.000145038, 105000 * 0.000145038]),
+ IP=IP(
+ unit="Psi",
+ range=[
+ 95000 * ColorPalettes.PA_TO_PSI.value,
+ 105000 * ColorPalettes.PA_TO_PSI.value,
+ ],
+ ),
)
# ==================== Radiation Related Variables ====================
@@ -146,80 +200,55 @@ class Variables:
name="Extraterrestrial horizontal irradiation",
unit="Wh/m2",
range=[0, 1200],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
- IP=IP(unit="Btu/ft2", range=[0, 1200 * 0.3169983306]),
+ color=ColorPalettes.SUN_COLORS.value,
+ IP=IP(
+ unit="Btu/ft2",
+ range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value],
+ ),
)
HOR_IR_RAD = VariableInfo(
col_name="hor_ir_rad",
name="Horizontal infrared radiation",
unit="Wh/m2",
range=[0, 500],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
- IP=IP(unit="Btu/ft2", range=[0, 500 * 0.3169983306]),
+ color=ColorPalettes.SUN_COLORS.value,
+ IP=IP(
+ unit="Btu/ft2",
+ range=[0, 500 * ColorPalettes.WHM2_TO_BTU_FT2.value],
+ ),
)
GLOB_HOR_RAD = VariableInfo(
col_name="glob_hor_rad",
name="Global horizontal radiation",
unit="Wh/m2",
range=[0, 1200],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
- IP=IP(unit="Btu/ft2", range=[0, 1200 * 0.3169983306]),
+ color=ColorPalettes.SUN_COLORS.value,
+ IP=IP(
+ unit="Btu/ft2",
+ range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value],
+ ),
)
DIR_NOR_RAD = VariableInfo(
col_name="dir_nor_rad",
name="Direct normal radiation",
unit="Wh/m2",
range=[0, 1200],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
- IP=IP(unit="Btu/ft2", range=[0, 1200 * 0.3169983306]),
+ color=ColorPalettes.SUN_COLORS.value,
+ IP=IP(
+ unit="Btu/ft2",
+ range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value],
+ ),
)
DIF_HOR_RAD = VariableInfo(
col_name="dif_hor_rad",
name="Diffuse horizontal radiation",
unit="Wh/m2",
range=[0, 1200],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
- IP=IP(unit="Btu/ft2", range=[0, 1200 * 0.3169983306]),
+ color=ColorPalettes.SUN_COLORS.value,
+ IP=IP(
+ unit="Btu/ft2",
+ range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value],
+ ),
)
# ==================== Lighting Related Variables ====================
@@ -228,24 +257,24 @@ class Variables:
name="Global horizontal illuminance",
unit="lux",
range=[0, 120000],
- color=["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"],
- IP=IP(unit="fc", range=[0, 120000 * 0.0929]),
+ color=ColorPalettes.LIGHT_COLORS.value,
+ IP=IP(unit="fc", range=[0, 120000 * ColorPalettes.LUX_TO_FC.value]),
)
DIR_NOR_ILL = VariableInfo(
col_name="dir_nor_ill",
name="Direct normal illuminance",
unit="lux",
range=[0, 120000],
- color=["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"],
- IP=IP(unit="fc", range=[0, 120000 * 0.0929]),
+ color=ColorPalettes.LIGHT_COLORS.value,
+ IP=IP(unit="fc", range=[0, 120000 * ColorPalettes.LUX_TO_FC.value]),
)
DIF_HOR_ILL = VariableInfo(
col_name="dif_hor_ill",
name="Diffuse horizontal illuminance",
unit="lux",
range=[0, 120000],
- color=["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"],
- IP=IP(unit="fc", range=[0, 120000 * 0.0929]),
+ color=ColorPalettes.LIGHT_COLORS.value,
+ IP=IP(unit="fc", range=[0, 120000 * ColorPalettes.LUX_TO_FC.value]),
)
ZLUMI = VariableInfo(
@@ -263,7 +292,7 @@ class Variables:
name="Wind direction",
unit="°deg",
range=[0, 360],
- color=["#0072dd", "#00c420", "#eded00", "#be00d5", "#0072dd"],
+ color=list(pseq.Viridis),
)
WIND_SPEED = VariableInfo(
col_name="wind_speed",
@@ -271,16 +300,16 @@ class Variables:
unit="m/s",
range=[0, 20],
color=[
- "#D3D3D3",
- "#b2f2ff",
- "#33ddff",
- "#00aaff",
- "#0055ff",
- "#0000ff",
- "#aa00ff",
- "#ff00ff",
- "#cc0000",
- "#ffaa00",
+ "#feffff",
+ "#dcf0fc",
+ "#c2defe",
+ "#b8cafd",
+ "#beb1f5",
+ "#d093df",
+ "#e272bb",
+ "#eb4f8b",
+ "#e52d51",
+ "#d0210e",
],
IP=IP(unit="fpm", range=[0, 20 * 196.85039370078738]),
)
@@ -290,33 +319,21 @@ class Variables:
name="Total sky cover",
unit="tenths",
range=[0, 10],
- color=[
- "#7ec9f3",
- "#e6eae9",
- "#c2c2c2",
- ],
+ color=ColorPalettes.SKY_COVER_TRI.value,
)
OPAQUE_SKY_COVER = VariableInfo(
col_name="Oskycover",
name="Opaque sky cover",
unit="tenths",
range=[0, 10],
- color=[
- "#7ec9f3",
- "#e6eae9",
- "#c2c2c2",
- ],
+ color=ColorPalettes.SKY_COVER_TRI.value,
)
VIS = VariableInfo(
col_name="Vis",
name="Visibility",
unit="km",
range=[0, 100],
- color=[
- "#7ec9f3",
- "#e6eae9",
- "#c2c2c2",
- ],
+ color=ColorPalettes.SKY_COVER_TRI.value,
IP=IP(unit="miles", range=[0, 100 * 0.6215]),
)
@@ -326,90 +343,42 @@ class Variables:
name="Apparent zenith",
unit="°deg",
range=[0, 180],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
ZENITH = VariableInfo(
col_name="zenith",
name="Zenith",
unit="°deg",
range=[0, 180],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
APPARENT_ELEVATION = VariableInfo(
col_name="apparent_elevation",
name="Apparent elevation",
unit="°deg",
range=[-90, 90],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
ELEVATION = VariableInfo(
col_name="elevation",
name="Elevation",
unit="°deg",
range=[-90, 90],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
AZIMUTH = VariableInfo(
col_name="azimuth",
name="Azimuth",
unit="°deg",
range=[0, 360],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
EQUATION_OF_TIME = VariableInfo(
col_name="equation_of_time",
name="Equation of time",
unit="°deg",
range=[-20, 20],
- color=[
- "#293a59",
- "#960c2c",
- "#ff0000",
- "#ff7b00",
- "#fffc00",
- "#ffff7b",
- "#ffffff",
- ],
+ color=ColorPalettes.SUN_COLORS.value,
)
# ==================== UTCI Comfort Related Variables ====================
@@ -418,7 +387,7 @@ class Variables:
name="UTCI: Sun & Wind",
unit="°C",
range=[-70, 70],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-94, 158]),
)
UTCI_NO_SUN_WIND = VariableInfo(
@@ -426,7 +395,7 @@ class Variables:
name="UTCI: no Sun & Wind",
unit="°C",
range=[-70, 70],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-94, 158]),
)
UTCI_SUN_NO_WIND = VariableInfo(
@@ -434,7 +403,7 @@ class Variables:
name="UTCI: Sun & no Wind",
unit="°C",
range=[-70, 70],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-94, 158]),
)
UTCI_NO_SUN_NO_WIND = VariableInfo(
@@ -442,7 +411,7 @@ class Variables:
name="UTCI: no Sun & no Wind",
unit="°C",
range=[-70, 70],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-94, 158]),
)
@@ -451,112 +420,28 @@ class Variables:
name="UTCI: Sun & Wind : categories",
unit="Thermal stress",
range=[-5, 4],
- color=[
- [0, "#2B2977"],
- [0.0555, "#2B2977"],
- [0.0555, "#38429B"],
- [0.1665, "#38429B"],
- [0.1665, "#4253A4"],
- [0.2775, "#4253A4"],
- [0.2775, "#4B62AD"],
- [0.3885, "#4B62AD"],
- [0.3885, "#68B8E7"],
- [0.4995, "#68B8E7"],
- [0.4995, "#53B848"],
- [0.6105, "#53B848"],
- [0.6105, "#EE8522"],
- [0.7215, "#EE8522"],
- [0.7215, "#EA2C24"],
- [0.8325, "#EA2C24"],
- [0.8325, "#B12224"],
- [0.9435, "#B12224"],
- [0.9435, "#751613"],
- [1.0, "#751613"],
- ],
+ color=ColorPalettes.UTCI_CATEGORIES_SCALE.value,
)
UTCI_NOSUN_WIND_CATEGORIES = VariableInfo(
col_name="utci_noSun_Wind_categories",
name="UTCI: no Sun & Wind : categories",
unit="Thermal stress",
range=[-5, 4],
- color=[
- [0, "#2B2977"],
- [0.0555, "#2B2977"],
- [0.0555, "#38429B"],
- [0.1665, "#38429B"],
- [0.1665, "#4253A4"],
- [0.2775, "#4253A4"],
- [0.2775, "#4B62AD"],
- [0.3885, "#4B62AD"],
- [0.3885, "#68B8E7"],
- [0.4995, "#68B8E7"],
- [0.4995, "#53B848"],
- [0.6105, "#53B848"],
- [0.6105, "#EE8522"],
- [0.7215, "#EE8522"],
- [0.7215, "#EA2C24"],
- [0.8325, "#EA2C24"],
- [0.8325, "#B12224"],
- [0.9435, "#B12224"],
- [0.9435, "#751613"],
- [1.0, "#751613"],
- ],
+ color=ColorPalettes.UTCI_CATEGORIES_SCALE.value,
)
UTCI_SUN_NOWIND_CATEGORIES = VariableInfo(
col_name="utci_Sun_noWind_categories",
name="UTCI: Sun & no Wind : categories",
unit="Thermal stress",
range=[-5, 4],
- color=[
- [0, "#2B2977"],
- [0.0555, "#2B2977"],
- [0.0555, "#38429B"],
- [0.1665, "#38429B"],
- [0.1665, "#4253A4"],
- [0.2775, "#4253A4"],
- [0.2775, "#4B62AD"],
- [0.3885, "#4B62AD"],
- [0.3885, "#68B8E7"],
- [0.4995, "#68B8E7"],
- [0.4995, "#53B848"],
- [0.6105, "#53B848"],
- [0.6105, "#EE8522"],
- [0.7215, "#EE8522"],
- [0.7215, "#EA2C24"],
- [0.8325, "#EA2C24"],
- [0.8325, "#B12224"],
- [0.9435, "#B12224"],
- [0.9435, "#751613"],
- [1.0, "#751613"],
- ],
+ color=ColorPalettes.UTCI_CATEGORIES_SCALE.value,
)
UTCI_NOSUN_NOWIND_CATEGORIES = VariableInfo(
col_name="utci_noSun_noWind_categories",
name="UTCI: no Sun & no Wind : categories",
unit="Thermal stress",
range=[-5, 4],
- color=[
- [0, "#2B2977"],
- [0.0555, "#2B2977"],
- [0.0555, "#38429B"],
- [0.1665, "#38429B"],
- [0.1665, "#4253A4"],
- [0.2775, "#4253A4"],
- [0.2775, "#4B62AD"],
- [0.3885, "#4B62AD"],
- [0.3885, "#68B8E7"],
- [0.4995, "#68B8E7"],
- [0.4995, "#53B848"],
- [0.6105, "#53B848"],
- [0.6105, "#EE8522"],
- [0.7215, "#EE8522"],
- [0.7215, "#EA2C24"],
- [0.8325, "#EA2C24"],
- [0.8325, "#B12224"],
- [0.9435, "#B12224"],
- [0.9435, "#751613"],
- [1.0, "#751613"],
- ],
+ color=ColorPalettes.UTCI_CATEGORIES_SCALE.value,
)
# ==================== Additional Meteorological Data ====================
@@ -565,7 +450,7 @@ class Variables:
name="Vapor partial pressure",
unit="Pa",
range=[0, 5000],
- color=["#ffe600", "#00c8ff", "#0000ff"],
+ color=ColorPalettes.DRY_HUMID.value,
IP=IP(unit="Psi", range=[0, 5000 * 0.000145038]),
)
P_SAT = VariableInfo(
@@ -580,7 +465,7 @@ class Variables:
name="Absolute humidity",
unit="g water/kg dry air",
range=[0, 0.03 * 1000],
- color=["#ffe600", "#00c8ff", "#0000ff"],
+ color=ColorPalettes.DRY_HUMID.value,
IP=IP(unit="lb water/klb dry air", range=[0, 0.03 * 1000]),
)
T_WB = VariableInfo(
@@ -588,7 +473,7 @@ class Variables:
name="Wet bulb temperature",
unit="°C",
range=[-40, 50],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-40, 122]),
)
T_DP = VariableInfo(
@@ -596,7 +481,7 @@ class Variables:
name="Dew point temperature",
unit="°C",
range=[-40, 50],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="°F", range=[-40, 122]),
)
EH = VariableInfo(
@@ -604,7 +489,7 @@ class Variables:
name="Enthalpy",
unit="J/kg dry air",
range=[0, 110000],
- color=["#00b3ff", "#000082", "#ff0000", "#ffff00"],
+ color=ColorPalettes.BLUE_RED_YELLOW.value,
IP=IP(unit="Btu/lb dry air", range=[0, 110000 * 0.000429923]),
)
diff --git a/pages/lib/template_graphs.py b/pages/lib/template_graphs.py
index 4dcc499..1fb189d 100644
--- a/pages/lib/template_graphs.py
+++ b/pages/lib/template_graphs.py
@@ -6,7 +6,7 @@
from config import UnitSystem
from pages.lib.utils import get_max_min_value
import dash_bootstrap_components as dbc
-from .global_scheme import month_lst, template, tight_margins
+from .global_scheme import month_lst, template, tight_margins, WIND_ROSE_BINS
from pages.lib.global_variables import Variables, VariableInfo
from .utils import code_timer, determine_month_and_hour_filter
@@ -430,6 +430,12 @@ def heatmap_with_filter(
)
)
+ if var == Variables.WIND_SPEED.col_name:
+ spd_bins = list(WIND_ROSE_BINS)
+ if si_ip == UnitSystem.IP:
+ spd_bins = convert_bins(spd_bins)
+ fig.update_traces(zmin=0, zmax=spd_bins[-2])
+
fig.update_xaxes(dtick="M1", tickformat="%b", ticklabelmode="period")
fig.update_yaxes(title_text="Hour")
@@ -492,6 +498,12 @@ def heatmap(df, var, global_local, si_ip):
)
)
+ if var == Variables.WIND_SPEED.col_name:
+ spd_bins = list(WIND_ROSE_BINS)
+ if si_ip == UnitSystem.IP:
+ spd_bins = convert_bins(spd_bins)
+ fig.update_traces(zmin=0, zmax=spd_bins[-2])
+
fig.update_xaxes(dtick="M1", tickformat="%b", ticklabelmode="period")
fig.update_yaxes(title_text="Hour")
@@ -551,7 +563,7 @@ def wind_rose(df, title, month, hour, labels, si_ip):
spd_colors = wind_speed_variable.get_color()
spd_unit = wind_speed_variable.get_unit(si_ip)
- spd_bins = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf]
+ spd_bins = WIND_ROSE_BINS
if si_ip == UnitSystem.IP:
spd_bins = convert_bins(spd_bins)
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 14cdb68..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-ansi2html==1.9.2
-black==25.1.0
-blinker==1.9.0
-bump2version==1.0.1
-cachelib==0.9.0
-certifi==2025.7.14
-charset-normalizer==3.4.2
-cleanpy==0.5.1
-click==8.2.1
-dash==3.2.0
-dash-bootstrap-components==1.2.0
-dash-core-components==2.0.0
-dash-extensions==1.0.7
-dash-html-components==2.0.0
-dash-iconify==0.1.2
-dash-mantine-components==2.2.1
-dash-table==5.0.0
-dataclass-wizard==0.22.3
-EditorConfig==0.17.1
-Flask==2.3.3
-Flask-Caching==2.0.2
-h5py==3.14.0
-idna==3.10
-importlib_metadata==8.7.0
-iniconfig==2.1.0
-itsdangerous==2.2.0
-Jinja2==3.1.6
-jsbeautifier==1.15.4
-llvmlite==0.44.0
-MarkupSafe==3.0.2
-more-itertools==9.1.0
-mypy_extensions==1.1.0
-narwhals==2.0.1
-nest-asyncio==1.6.0
-numba==0.61.2
-numpy==1.26.3
-packaging==25.0
-pandas==2.2.0
-pathspec==0.12.1
-platformdirs==4.3.8
-plotly==5.18.0
-pluggy==1.6.0
-pvlib==0.9.1
-Pygments==2.19.2
-pytest==8.4.1
-pythermalcomfort==2.9.1
-python-dateutil==2.9.0.post0
-pytz==2025.2
-requests==2.32.4
-retrying==1.4.1
-ruff==0.12.7
-scipy==1.12.0
-six==1.17.0
-tenacity==9.1.2
-typing_extensions==4.14.1
-tzdata==2025.2
-urllib3==2.5.0
-Werkzeug==3.0.6
-zipp==3.23.0