From 176ca08271aef63d063addf91d4f4e08698e0009 Mon Sep 17 00:00:00 2001 From: FengW01 Date: Wed, 15 Oct 2025 14:09:03 +1100 Subject: [PATCH 1/9] chore(a11y): update color schemes for color-blind assessment #110 --- pages/lib/global_scheme.py | 20 +++++--------------- pages/lib/global_variables.py | 24 +++++++----------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index 36fd2d0..606b871 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -1,5 +1,6 @@ import plotly.io as pio - +import colorcet as cc +from plotly.colors import sequential as pseq from pages.lib.global_variables import Variables, VariableInfo # Colors Dictionary @@ -16,23 +17,12 @@ ] 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"] +wind_speed_color = list(cc.CET_L19) +wind_dir_color = list(pseq.Viridis) cloud_colors = [ + "#08306b", "#7ec9f3", "#e6eae9", - "#c2c2c2", ] utci_categories_color = [ # Let first 10% (0.1) of the values have color rgb(0, 0, 0) diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index baf12b8..b8e467b 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -1,7 +1,8 @@ from dataclasses import dataclass from typing import Optional, List, Any from config import UnitSystem - +import colorcet as cc +from plotly.colors import sequential as pseq @dataclass class IP: @@ -263,25 +264,14 @@ 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", name="Wind speed", unit="m/s", range=[0, 20], - color=[ - "#D3D3D3", - "#b2f2ff", - "#33ddff", - "#00aaff", - "#0055ff", - "#0000ff", - "#aa00ff", - "#ff00ff", - "#cc0000", - "#ffaa00", - ], + color=list(cc.CET_L19), IP=IP(unit="fpm", range=[0, 20 * 196.85039370078738]), ) @@ -291,9 +281,9 @@ class Variables: unit="tenths", range=[0, 10], color=[ + "#08306b", "#7ec9f3", "#e6eae9", - "#c2c2c2", ], ) OPAQUE_SKY_COVER = VariableInfo( @@ -302,9 +292,9 @@ class Variables: unit="tenths", range=[0, 10], color=[ + "#08306b", "#7ec9f3", "#e6eae9", - "#c2c2c2", ], ) VIS = VariableInfo( @@ -313,9 +303,9 @@ class Variables: unit="km", range=[0, 100], color=[ + "#08306b", "#7ec9f3", "#e6eae9", - "#c2c2c2", ], IP=IP(unit="miles", range=[0, 100 * 0.6215]), ) From cb79f39b6dc67e59f7254305dfc2be20e7d05802 Mon Sep 17 00:00:00 2001 From: FengW01 Date: Wed, 15 Oct 2025 15:23:34 +1100 Subject: [PATCH 2/9] chore(a11y): update color schemes for color-blind assessment #110 --- pages/lib/global_scheme.py | 2 +- pages/lib/global_variables.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index 606b871..f301ddf 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -17,7 +17,7 @@ ] light_colors = ["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"] bright_colors = ["#730a8c", "#0d0db3", "#0f85be", "#0f85be", "#b11421", "#fdf130"] -wind_speed_color = list(cc.CET_L19) +wind_speed_color = [cc.CET_L19[int(round(i*(len(cc.CET_L19)-1)/(9)))] for i in range(10)] wind_dir_color = list(pseq.Viridis) cloud_colors = [ "#08306b", diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index b8e467b..e29344c 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -271,7 +271,7 @@ class Variables: name="Wind speed", unit="m/s", range=[0, 20], - color=list(cc.CET_L19), + color=[cc.CET_L19[int(round(i*(len(cc.CET_L19)-1)/(9)))] for i in range(10)], IP=IP(unit="fpm", range=[0, 20 * 196.85039370078738]), ) From 1e502cd1fdd43be8c0f16766fa8f670b25c243e7 Mon Sep 17 00:00:00 2001 From: FengW01 Date: Mon, 20 Oct 2025 17:20:09 +1100 Subject: [PATCH 3/9] fix(color): unify wind speed color scale across all charts --- pages/lib/global_scheme.py | 24 +++++++++++++++++++++++- pages/lib/template_graphs.py | 12 ++++++++++++ requirements.txt | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index f301ddf..775c8f8 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -17,7 +17,29 @@ ] light_colors = ["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"] bright_colors = ["#730a8c", "#0d0db3", "#0f85be", "#0f85be", "#b11421", "#fdf130"] -wind_speed_color = [cc.CET_L19[int(round(i*(len(cc.CET_L19)-1)/(9)))] for i in range(10)] +wind_speed_color = [ + cc.CET_L19[int(round(i * (len(cc.CET_L19) - 1) / (9)))] for i in range(10) +] + +WIND_ROSE_BINS = [0.0, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7] + + +def _stepped_colorscale_from_bins(bins, colors): + vmin, vmax = bins[0], bins[-1] + span = (vmax - vmin) or 1.0 + cs = [] + for i, c in enumerate(colors): + left = (bins[i] - vmin) / span + right = ((bins[i + 1] if i + 1 < len(bins) else vmax) - vmin) / span + cs.append((left, c)) + cs.append((right, c)) + return cs + + +wind_speed_colorscale_rose = _stepped_colorscale_from_bins( + WIND_ROSE_BINS, wind_speed_color +) + wind_dir_color = list(pseq.Viridis) cloud_colors = [ "#08306b", diff --git a/pages/lib/template_graphs.py b/pages/lib/template_graphs.py index 4dcc499..8477d5f 100644 --- a/pages/lib/template_graphs.py +++ b/pages/lib/template_graphs.py @@ -430,6 +430,12 @@ def heatmap_with_filter( ) ) + if var == Variables.WIND_SPEED.col_name: + spd_bins = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf] + 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 = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf] + 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") diff --git a/requirements.txt b/requirements.txt index 14cdb68..aca379e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ certifi==2025.7.14 charset-normalizer==3.4.2 cleanpy==0.5.1 click==8.2.1 +colorcet>=3.0.1,<4 dash==3.2.0 dash-bootstrap-components==1.2.0 dash-core-components==2.0.0 From b4a51cb0b1cf72edc538bc00e53daf6446d43ff9 Mon Sep 17 00:00:00 2001 From: FengW01 Date: Wed, 22 Oct 2025 12:53:13 +1100 Subject: [PATCH 4/9] chore(deps): add colorcet to Pipfile; refactor(global_variables): remove duplicate code --- Pipfile | 1 + Pipfile.lock | 11 +- pages/lib/global_scheme.py | 4 +- pages/lib/global_variables.py | 320 ++++++++++------------------------ pages/lib/template_graphs.py | 6 +- 5 files changed, 110 insertions(+), 232 deletions(-) diff --git a/Pipfile b/Pipfile index 0c01f3d..210142c 100644 --- a/Pipfile +++ b/Pipfile @@ -16,6 +16,7 @@ pandas = "==2.2.0" numpy = "==1.26.3" dash-iconify = "*" scipy = "==1.12.0" +colorcet = "<4,>=3.0.1" [dev-packages] cleanpy = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 8e475b6..ce60fca 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4f09fe1d5fd82b15503fd3b0c1606e5e6139df983488fdc78c72555daf01e167" + "sha256": "79b1a6efc301bcc68eb75b61790df1ac8051751236f6b505086c26572d4d3458" }, "pipfile-spec": 6, "requires": { @@ -133,6 +133,15 @@ "markers": "python_version >= '3.10'", "version": "==8.2.1" }, + "colorcet": { + "hashes": [ + "sha256:2921b3cd81a2288aaf2d63dbc0ce3c26dcd882e8c389cc505d6886bf7aa9a4eb", + "sha256:2a7d59cc8d0f7938eeedd08aad3152b5319b4ba3bcb7a612398cc17a384cb296" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==3.1.0" + }, "dash": { "hashes": [ "sha256:4c1819588d83bed2cbcf5807daa5c2380c8c85789a6935a733f018f04ad8a6a2", diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index 775c8f8..ab2ade5 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -1,5 +1,6 @@ import plotly.io as pio import colorcet as cc +import numpy as np from plotly.colors import sequential as pseq from pages.lib.global_variables import Variables, VariableInfo @@ -17,11 +18,12 @@ ] light_colors = ["#4d6daa", "#a0beed", "#f1e969", "#eb7d05", "#d81600"] bright_colors = ["#730a8c", "#0d0db3", "#0f85be", "#0f85be", "#b11421", "#fdf130"] +# Take 10 colors at equal intervals (including both ends) wind_speed_color = [ cc.CET_L19[int(round(i * (len(cc.CET_L19) - 1) / (9)))] for i in range(10) ] -WIND_ROSE_BINS = [0.0, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7] +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): diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index e29344c..5a101cf 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -4,6 +4,56 @@ import colorcet as cc from plotly.colors import sequential as pseq +# ---------- Shared palettes & conversion constants ---------- +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"] + +# Evenly sample 10 colors (including both endpoints) from CET_L19 +CET_L19_10 = [ + cc.CET_L19[int(round(i * (len(cc.CET_L19) - 1) / (9)))] for i in range(10) +] + +# Unit conversions +PA_TO_PSI = 0.000145038 +WHM2_TO_BTUFT2 = 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 class IP: """Metadata for the Imperial Units (IP)""" @@ -102,7 +152,7 @@ class Variables: name="Dry bulb temperature", unit="°C", range=[-40, 50], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-40, 122]), ) DPT = VariableInfo( @@ -110,7 +160,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-50, 35], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-58, 95]), ) RH = VariableInfo( @@ -118,7 +168,7 @@ class Variables: name="Relative humidity", unit="%", range=[0, 100], - color=["#ffe600", "#00c8ff", "#0000ff"], + color=DRY_HUMID, ) P_ATM = VariableInfo( @@ -138,7 +188,7 @@ class Variables: "#cc0000", "#ffaa00", ], - IP=IP(unit="Psi", range=[95000 * 0.000145038, 105000 * 0.000145038]), + IP=IP(unit="Psi", range=[95000 * PA_TO_PSI, 105000 * PA_TO_PSI]), ) # ==================== Radiation Related Variables ==================== @@ -147,80 +197,40 @@ 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=SUN_COLORS, + IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), ) 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=SUN_COLORS, + IP=IP(unit="Btu/ft2", range=[0, 500 * WHM2_TO_BTUFT2]), ) 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=SUN_COLORS, + IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), ) 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=SUN_COLORS, + IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), ) 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=SUN_COLORS, + IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), ) # ==================== Lighting Related Variables ==================== @@ -229,24 +239,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=LIGHT_COLORS, + IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), ) 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=LIGHT_COLORS, + IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), ) 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=LIGHT_COLORS, + IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), ) ZLUMI = VariableInfo( @@ -271,7 +281,7 @@ class Variables: name="Wind speed", unit="m/s", range=[0, 20], - color=[cc.CET_L19[int(round(i*(len(cc.CET_L19)-1)/(9)))] for i in range(10)], + color=CET_L19_10, IP=IP(unit="fpm", range=[0, 20 * 196.85039370078738]), ) @@ -280,33 +290,21 @@ class Variables: name="Total sky cover", unit="tenths", range=[0, 10], - color=[ - "#08306b", - "#7ec9f3", - "#e6eae9", - ], + color=SKY_COVER_TRI, ) OPAQUE_SKY_COVER = VariableInfo( col_name="Oskycover", name="Opaque sky cover", unit="tenths", range=[0, 10], - color=[ - "#08306b", - "#7ec9f3", - "#e6eae9", - ], + color=SKY_COVER_TRI, ) VIS = VariableInfo( col_name="Vis", name="Visibility", unit="km", range=[0, 100], - color=[ - "#08306b", - "#7ec9f3", - "#e6eae9", - ], + color=SKY_COVER_TRI, IP=IP(unit="miles", range=[0, 100 * 0.6215]), ) @@ -316,90 +314,42 @@ class Variables: name="Apparent zenith", unit="°deg", range=[0, 180], - color=[ - "#293a59", - "#960c2c", - "#ff0000", - "#ff7b00", - "#fffc00", - "#ffff7b", - "#ffffff", - ], + color=SUN_COLORS, ) ZENITH = VariableInfo( col_name="zenith", name="Zenith", unit="°deg", range=[0, 180], - color=[ - "#293a59", - "#960c2c", - "#ff0000", - "#ff7b00", - "#fffc00", - "#ffff7b", - "#ffffff", - ], + color=SUN_COLORS, ) APPARENT_ELEVATION = VariableInfo( col_name="apparent_elevation", name="Apparent elevation", unit="°deg", range=[-90, 90], - color=[ - "#293a59", - "#960c2c", - "#ff0000", - "#ff7b00", - "#fffc00", - "#ffff7b", - "#ffffff", - ], + color=SUN_COLORS, ) ELEVATION = VariableInfo( col_name="elevation", name="Elevation", unit="°deg", range=[-90, 90], - color=[ - "#293a59", - "#960c2c", - "#ff0000", - "#ff7b00", - "#fffc00", - "#ffff7b", - "#ffffff", - ], + color=SUN_COLORS, ) AZIMUTH = VariableInfo( col_name="azimuth", name="Azimuth", unit="°deg", range=[0, 360], - color=[ - "#293a59", - "#960c2c", - "#ff0000", - "#ff7b00", - "#fffc00", - "#ffff7b", - "#ffffff", - ], + color=SUN_COLORS, ) 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=SUN_COLORS, ) # ==================== UTCI Comfort Related Variables ==================== @@ -408,7 +358,7 @@ class Variables: name="UTCI: Sun & Wind", unit="°C", range=[-70, 70], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_WIND = VariableInfo( @@ -416,7 +366,7 @@ class Variables: name="UTCI: no Sun & Wind", unit="°C", range=[-70, 70], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_SUN_NO_WIND = VariableInfo( @@ -424,7 +374,7 @@ class Variables: name="UTCI: Sun & no Wind", unit="°C", range=[-70, 70], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_NO_WIND = VariableInfo( @@ -432,7 +382,7 @@ class Variables: name="UTCI: no Sun & no Wind", unit="°C", range=[-70, 70], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-94, 158]), ) @@ -441,112 +391,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=UTCI_CATEGORIES_SCALE, ) 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=UTCI_CATEGORIES_SCALE, ) 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=UTCI_CATEGORIES_SCALE, ) 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=UTCI_CATEGORIES_SCALE, ) # ==================== Additional Meteorological Data ==================== @@ -555,7 +421,7 @@ class Variables: name="Vapor partial pressure", unit="Pa", range=[0, 5000], - color=["#ffe600", "#00c8ff", "#0000ff"], + color=DRY_HUMID, IP=IP(unit="Psi", range=[0, 5000 * 0.000145038]), ) P_SAT = VariableInfo( @@ -570,7 +436,7 @@ class Variables: name="Absolute humidity", unit="g water/kg dry air", range=[0, 0.03 * 1000], - color=["#ffe600", "#00c8ff", "#0000ff"], + color=DRY_HUMID, IP=IP(unit="lb water/klb dry air", range=[0, 0.03 * 1000]), ) T_WB = VariableInfo( @@ -578,7 +444,7 @@ class Variables: name="Wet bulb temperature", unit="°C", range=[-40, 50], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-40, 122]), ) T_DP = VariableInfo( @@ -586,7 +452,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-40, 50], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, IP=IP(unit="°F", range=[-40, 122]), ) EH = VariableInfo( @@ -594,7 +460,7 @@ class Variables: name="Enthalpy", unit="J/kg dry air", range=[0, 110000], - color=["#00b3ff", "#000082", "#ff0000", "#ffff00"], + color=BLUE_RED_YELLOW, 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 8477d5f..8030bf6 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 @@ -431,7 +431,7 @@ def heatmap_with_filter( ) if var == Variables.WIND_SPEED.col_name: - 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 = list(WIND_ROSE_BINS) if si_ip == UnitSystem.IP: spd_bins = convert_bins(spd_bins) fig.update_traces(zmin=0, zmax=spd_bins[-2]) @@ -499,7 +499,7 @@ def heatmap(df, var, global_local, si_ip): ) if var == Variables.WIND_SPEED.col_name: - 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 = list(WIND_ROSE_BINS) if si_ip == UnitSystem.IP: spd_bins = convert_bins(spd_bins) fig.update_traces(zmin=0, zmax=spd_bins[-2]) From e8eebace3ebc735776b28b51058908d59317aada Mon Sep 17 00:00:00 2001 From: FengW01 Date: Wed, 22 Oct 2025 16:47:38 +1100 Subject: [PATCH 5/9] Remove redundancy --- pages/lib/global_scheme.py | 90 +++++++++++++++--------------------- pages/lib/template_graphs.py | 2 +- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index ab2ade5..5879ce8 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -1,40 +1,52 @@ import plotly.io as pio -import colorcet as cc import numpy as np -from plotly.colors import sequential as pseq -from pages.lib.global_variables import Variables, VariableInfo +from pages.lib.global_variables import Variables, VariableInfo, CET_L19_10 # 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"] -# Take 10 colors at equal intervals (including both ends) -wind_speed_color = [ - cc.CET_L19[int(round(i * (len(cc.CET_L19) - 1) / (9)))] for i in range(10) -] - +wind_speed_color = CET_L19_10 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): - vmin, vmax = bins[0], bins[-1] + """ + 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 = (bins[i] - vmin) / span - right = ((bins[i + 1] if i + 1 < len(bins) else vmax) - vmin) / span + 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 @@ -42,36 +54,6 @@ def _stepped_colorscale_from_bins(bins, colors): WIND_ROSE_BINS, wind_speed_color ) -wind_dir_color = list(pseq.Viridis) -cloud_colors = [ - "#08306b", - "#7ec9f3", - "#e6eae9", -] -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"], -] - # containers container_row_center_full = "container-row row-center" container_col_center_one_of_three = ( diff --git a/pages/lib/template_graphs.py b/pages/lib/template_graphs.py index 8030bf6..1fb189d 100644 --- a/pages/lib/template_graphs.py +++ b/pages/lib/template_graphs.py @@ -563,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) From f45b6a0bd056907f9f51872cb4add5e3df592c1f Mon Sep 17 00:00:00 2001 From: FengW01 Date: Fri, 24 Oct 2025 15:16:48 +1100 Subject: [PATCH 6/9] refactor(colors): consolidate shared palettes & unit conversions into Enum and drop colorcet in favor of hex color lists --- Pipfile | 1 - Pipfile.lock | 11 +- pages/lib/global_scheme.py | 6 +- pages/lib/global_variables.py | 194 ++++++++++++++++++---------------- requirements.txt | 1 - 5 files changed, 106 insertions(+), 107 deletions(-) diff --git a/Pipfile b/Pipfile index 210142c..0c01f3d 100644 --- a/Pipfile +++ b/Pipfile @@ -16,7 +16,6 @@ pandas = "==2.2.0" numpy = "==1.26.3" dash-iconify = "*" scipy = "==1.12.0" -colorcet = "<4,>=3.0.1" [dev-packages] cleanpy = "*" diff --git a/Pipfile.lock b/Pipfile.lock index ce60fca..8e475b6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "79b1a6efc301bcc68eb75b61790df1ac8051751236f6b505086c26572d4d3458" + "sha256": "4f09fe1d5fd82b15503fd3b0c1606e5e6139df983488fdc78c72555daf01e167" }, "pipfile-spec": 6, "requires": { @@ -133,15 +133,6 @@ "markers": "python_version >= '3.10'", "version": "==8.2.1" }, - "colorcet": { - "hashes": [ - "sha256:2921b3cd81a2288aaf2d63dbc0ce3c26dcd882e8c389cc505d6886bf7aa9a4eb", - "sha256:2a7d59cc8d0f7938eeedd08aad3152b5319b4ba3bcb7a612398cc17a384cb296" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==3.1.0" - }, "dash": { "hashes": [ "sha256:4c1819588d83bed2cbcf5807daa5c2380c8c85789a6935a733f018f04ad8a6a2", diff --git a/pages/lib/global_scheme.py b/pages/lib/global_scheme.py index 5879ce8..8b93053 100644 --- a/pages/lib/global_scheme.py +++ b/pages/lib/global_scheme.py @@ -1,9 +1,7 @@ import plotly.io as pio import numpy as np -from pages.lib.global_variables import Variables, VariableInfo, CET_L19_10 +from pages.lib.global_variables import Variables, VariableInfo -# Colors Dictionary -wind_speed_color = CET_L19_10 WIND_ROSE_BINS = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf] @@ -51,7 +49,7 @@ def _stepped_colorscale_from_bins(bins, colors): wind_speed_colorscale_rose = _stepped_colorscale_from_bins( - WIND_ROSE_BINS, wind_speed_color + WIND_ROSE_BINS, Variables.WIND_SPEED.color ) # containers diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index 5a101cf..bcc63c5 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -1,57 +1,55 @@ from dataclasses import dataclass from typing import Optional, List, Any +from enum import Enum from config import UnitSystem -import colorcet as cc from plotly.colors import sequential as pseq + # ---------- Shared palettes & conversion constants ---------- -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"] - -# Evenly sample 10 colors (including both endpoints) from CET_L19 -CET_L19_10 = [ - cc.CET_L19[int(round(i * (len(cc.CET_L19) - 1) / (9)))] for i in range(10) -] - -# Unit conversions -PA_TO_PSI = 0.000145038 -WHM2_TO_BTUFT2 = 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"], -] +class Common(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_BTUFT2 = 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 @@ -152,7 +150,7 @@ class Variables: name="Dry bulb temperature", unit="°C", range=[-40, 50], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) DPT = VariableInfo( @@ -160,7 +158,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-50, 35], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-58, 95]), ) RH = VariableInfo( @@ -168,7 +166,7 @@ class Variables: name="Relative humidity", unit="%", range=[0, 100], - color=DRY_HUMID, + color=Common.DRY_HUMID.value, ) P_ATM = VariableInfo( @@ -188,7 +186,10 @@ class Variables: "#cc0000", "#ffaa00", ], - IP=IP(unit="Psi", range=[95000 * PA_TO_PSI, 105000 * PA_TO_PSI]), + IP=IP( + unit="Psi", + range=[95000 * Common.PA_TO_PSI.value, 105000 * Common.PA_TO_PSI.value], + ), ) # ==================== Radiation Related Variables ==================== @@ -197,40 +198,40 @@ class Variables: name="Extraterrestrial horizontal irradiation", unit="Wh/m2", range=[0, 1200], - color=SUN_COLORS, - IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), + color=Common.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), ) HOR_IR_RAD = VariableInfo( col_name="hor_ir_rad", name="Horizontal infrared radiation", unit="Wh/m2", range=[0, 500], - color=SUN_COLORS, - IP=IP(unit="Btu/ft2", range=[0, 500 * WHM2_TO_BTUFT2]), + color=Common.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 500 * Common.WHM2_TO_BTUFT2.value]), ) GLOB_HOR_RAD = VariableInfo( col_name="glob_hor_rad", name="Global horizontal radiation", unit="Wh/m2", range=[0, 1200], - color=SUN_COLORS, - IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), + color=Common.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), ) DIR_NOR_RAD = VariableInfo( col_name="dir_nor_rad", name="Direct normal radiation", unit="Wh/m2", range=[0, 1200], - color=SUN_COLORS, - IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), + color=Common.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), ) DIF_HOR_RAD = VariableInfo( col_name="dif_hor_rad", name="Diffuse horizontal radiation", unit="Wh/m2", range=[0, 1200], - color=SUN_COLORS, - IP=IP(unit="Btu/ft2", range=[0, 1200 * WHM2_TO_BTUFT2]), + color=Common.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), ) # ==================== Lighting Related Variables ==================== @@ -239,24 +240,24 @@ class Variables: name="Global horizontal illuminance", unit="lux", range=[0, 120000], - color=LIGHT_COLORS, - IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), + color=Common.LIGHT_COLORS.value, + IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), ) DIR_NOR_ILL = VariableInfo( col_name="dir_nor_ill", name="Direct normal illuminance", unit="lux", range=[0, 120000], - color=LIGHT_COLORS, - IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), + color=Common.LIGHT_COLORS.value, + IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), ) DIF_HOR_ILL = VariableInfo( col_name="dif_hor_ill", name="Diffuse horizontal illuminance", unit="lux", range=[0, 120000], - color=LIGHT_COLORS, - IP=IP(unit="fc", range=[0, 120000 * LUX_TO_FC]), + color=Common.LIGHT_COLORS.value, + IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), ) ZLUMI = VariableInfo( @@ -281,7 +282,18 @@ class Variables: name="Wind speed", unit="m/s", range=[0, 20], - color=CET_L19_10, + color=[ + "#feffff", + "#dcf0fc", + "#c2defe", + "#b8cafd", + "#beb1f5", + "#d093df", + "#e272bb", + "#eb4f8b", + "#e52d51", + "#d0210e", + ], IP=IP(unit="fpm", range=[0, 20 * 196.85039370078738]), ) @@ -290,21 +302,21 @@ class Variables: name="Total sky cover", unit="tenths", range=[0, 10], - color=SKY_COVER_TRI, + color=Common.SKY_COVER_TRI.value, ) OPAQUE_SKY_COVER = VariableInfo( col_name="Oskycover", name="Opaque sky cover", unit="tenths", range=[0, 10], - color=SKY_COVER_TRI, + color=Common.SKY_COVER_TRI.value, ) VIS = VariableInfo( col_name="Vis", name="Visibility", unit="km", range=[0, 100], - color=SKY_COVER_TRI, + color=Common.SKY_COVER_TRI.value, IP=IP(unit="miles", range=[0, 100 * 0.6215]), ) @@ -314,42 +326,42 @@ class Variables: name="Apparent zenith", unit="°deg", range=[0, 180], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) ZENITH = VariableInfo( col_name="zenith", name="Zenith", unit="°deg", range=[0, 180], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) APPARENT_ELEVATION = VariableInfo( col_name="apparent_elevation", name="Apparent elevation", unit="°deg", range=[-90, 90], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) ELEVATION = VariableInfo( col_name="elevation", name="Elevation", unit="°deg", range=[-90, 90], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) AZIMUTH = VariableInfo( col_name="azimuth", name="Azimuth", unit="°deg", range=[0, 360], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) EQUATION_OF_TIME = VariableInfo( col_name="equation_of_time", name="Equation of time", unit="°deg", range=[-20, 20], - color=SUN_COLORS, + color=Common.SUN_COLORS.value, ) # ==================== UTCI Comfort Related Variables ==================== @@ -358,7 +370,7 @@ class Variables: name="UTCI: Sun & Wind", unit="°C", range=[-70, 70], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_WIND = VariableInfo( @@ -366,7 +378,7 @@ class Variables: name="UTCI: no Sun & Wind", unit="°C", range=[-70, 70], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_SUN_NO_WIND = VariableInfo( @@ -374,7 +386,7 @@ class Variables: name="UTCI: Sun & no Wind", unit="°C", range=[-70, 70], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_NO_WIND = VariableInfo( @@ -382,7 +394,7 @@ class Variables: name="UTCI: no Sun & no Wind", unit="°C", range=[-70, 70], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) @@ -391,28 +403,28 @@ class Variables: name="UTCI: Sun & Wind : categories", unit="Thermal stress", range=[-5, 4], - color=UTCI_CATEGORIES_SCALE, + color=Common.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=UTCI_CATEGORIES_SCALE, + color=Common.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=UTCI_CATEGORIES_SCALE, + color=Common.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=UTCI_CATEGORIES_SCALE, + color=Common.UTCI_CATEGORIES_SCALE.value, ) # ==================== Additional Meteorological Data ==================== @@ -421,7 +433,7 @@ class Variables: name="Vapor partial pressure", unit="Pa", range=[0, 5000], - color=DRY_HUMID, + color=Common.DRY_HUMID.value, IP=IP(unit="Psi", range=[0, 5000 * 0.000145038]), ) P_SAT = VariableInfo( @@ -436,7 +448,7 @@ class Variables: name="Absolute humidity", unit="g water/kg dry air", range=[0, 0.03 * 1000], - color=DRY_HUMID, + color=Common.DRY_HUMID.value, IP=IP(unit="lb water/klb dry air", range=[0, 0.03 * 1000]), ) T_WB = VariableInfo( @@ -444,7 +456,7 @@ class Variables: name="Wet bulb temperature", unit="°C", range=[-40, 50], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) T_DP = VariableInfo( @@ -452,7 +464,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-40, 50], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) EH = VariableInfo( @@ -460,7 +472,7 @@ class Variables: name="Enthalpy", unit="J/kg dry air", range=[0, 110000], - color=BLUE_RED_YELLOW, + color=Common.BLUE_RED_YELLOW.value, IP=IP(unit="Btu/lb dry air", range=[0, 110000 * 0.000429923]), ) diff --git a/requirements.txt b/requirements.txt index aca379e..14cdb68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ certifi==2025.7.14 charset-normalizer==3.4.2 cleanpy==0.5.1 click==8.2.1 -colorcet>=3.0.1,<4 dash==3.2.0 dash-bootstrap-components==1.2.0 dash-core-components==2.0.0 From 077d18c2af92800e911303400ee02b850e37b463 Mon Sep 17 00:00:00 2001 From: Federico Tartarini Date: Mon, 27 Oct 2025 14:34:09 +1100 Subject: [PATCH 7/9] refactor(global_variables): rename Common to ColorPalettes and update references --- pages/lib/global_variables.py | 89 +++++++++++++++++------------------ 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index bcc63c5..a761d95 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -5,8 +5,7 @@ from plotly.colors import sequential as pseq -# ---------- Shared palettes & conversion constants ---------- -class Common(Enum): +class ColorPalettes(Enum): # Palettes BLUE_RED_YELLOW = ["#00b3ff", "#000082", "#ff0000", "#ffff00"] DRY_HUMID = ["#ffe600", "#00c8ff", "#0000ff"] @@ -24,7 +23,7 @@ class Common(Enum): # Unit conversions PA_TO_PSI = 0.000145038 - WHM2_TO_BTUFT2 = 0.3169983306 + WHM2_TO_BTU_FT2 = 0.3169983306 LUX_TO_FC = 0.0929 # UTCI category colorscale @@ -150,7 +149,7 @@ class Variables: name="Dry bulb temperature", unit="°C", range=[-40, 50], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) DPT = VariableInfo( @@ -158,7 +157,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-50, 35], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-58, 95]), ) RH = VariableInfo( @@ -166,7 +165,7 @@ class Variables: name="Relative humidity", unit="%", range=[0, 100], - color=Common.DRY_HUMID.value, + color=ColorPalettes.DRY_HUMID.value, ) P_ATM = VariableInfo( @@ -188,7 +187,7 @@ class Variables: ], IP=IP( unit="Psi", - range=[95000 * Common.PA_TO_PSI.value, 105000 * Common.PA_TO_PSI.value], + range=[95000 * ColorPalettes.PA_TO_PSI.value, 105000 * ColorPalettes.PA_TO_PSI.value], ), ) @@ -198,40 +197,40 @@ class Variables: name="Extraterrestrial horizontal irradiation", unit="Wh/m2", range=[0, 1200], - color=Common.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), + 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=Common.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 500 * Common.WHM2_TO_BTUFT2.value]), + 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=Common.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), + 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=Common.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), + 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=Common.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * Common.WHM2_TO_BTUFT2.value]), + color=ColorPalettes.SUN_COLORS.value, + IP=IP(unit="Btu/ft2", range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value]), ) # ==================== Lighting Related Variables ==================== @@ -240,24 +239,24 @@ class Variables: name="Global horizontal illuminance", unit="lux", range=[0, 120000], - color=Common.LIGHT_COLORS.value, - IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), + 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=Common.LIGHT_COLORS.value, - IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), + 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=Common.LIGHT_COLORS.value, - IP=IP(unit="fc", range=[0, 120000 * Common.LUX_TO_FC.value]), + color=ColorPalettes.LIGHT_COLORS.value, + IP=IP(unit="fc", range=[0, 120000 * ColorPalettes.LUX_TO_FC.value]), ) ZLUMI = VariableInfo( @@ -302,21 +301,21 @@ class Variables: name="Total sky cover", unit="tenths", range=[0, 10], - color=Common.SKY_COVER_TRI.value, + color=ColorPalettes.SKY_COVER_TRI.value, ) OPAQUE_SKY_COVER = VariableInfo( col_name="Oskycover", name="Opaque sky cover", unit="tenths", range=[0, 10], - color=Common.SKY_COVER_TRI.value, + color=ColorPalettes.SKY_COVER_TRI.value, ) VIS = VariableInfo( col_name="Vis", name="Visibility", unit="km", range=[0, 100], - color=Common.SKY_COVER_TRI.value, + color=ColorPalettes.SKY_COVER_TRI.value, IP=IP(unit="miles", range=[0, 100 * 0.6215]), ) @@ -326,42 +325,42 @@ class Variables: name="Apparent zenith", unit="°deg", range=[0, 180], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) ZENITH = VariableInfo( col_name="zenith", name="Zenith", unit="°deg", range=[0, 180], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) APPARENT_ELEVATION = VariableInfo( col_name="apparent_elevation", name="Apparent elevation", unit="°deg", range=[-90, 90], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) ELEVATION = VariableInfo( col_name="elevation", name="Elevation", unit="°deg", range=[-90, 90], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) AZIMUTH = VariableInfo( col_name="azimuth", name="Azimuth", unit="°deg", range=[0, 360], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) EQUATION_OF_TIME = VariableInfo( col_name="equation_of_time", name="Equation of time", unit="°deg", range=[-20, 20], - color=Common.SUN_COLORS.value, + color=ColorPalettes.SUN_COLORS.value, ) # ==================== UTCI Comfort Related Variables ==================== @@ -370,7 +369,7 @@ class Variables: name="UTCI: Sun & Wind", unit="°C", range=[-70, 70], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_WIND = VariableInfo( @@ -378,7 +377,7 @@ class Variables: name="UTCI: no Sun & Wind", unit="°C", range=[-70, 70], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_SUN_NO_WIND = VariableInfo( @@ -386,7 +385,7 @@ class Variables: name="UTCI: Sun & no Wind", unit="°C", range=[-70, 70], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) UTCI_NO_SUN_NO_WIND = VariableInfo( @@ -394,7 +393,7 @@ class Variables: name="UTCI: no Sun & no Wind", unit="°C", range=[-70, 70], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-94, 158]), ) @@ -403,28 +402,28 @@ class Variables: name="UTCI: Sun & Wind : categories", unit="Thermal stress", range=[-5, 4], - color=Common.UTCI_CATEGORIES_SCALE.value, + 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=Common.UTCI_CATEGORIES_SCALE.value, + 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=Common.UTCI_CATEGORIES_SCALE.value, + 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=Common.UTCI_CATEGORIES_SCALE.value, + color=ColorPalettes.UTCI_CATEGORIES_SCALE.value, ) # ==================== Additional Meteorological Data ==================== @@ -433,7 +432,7 @@ class Variables: name="Vapor partial pressure", unit="Pa", range=[0, 5000], - color=Common.DRY_HUMID.value, + color=ColorPalettes.DRY_HUMID.value, IP=IP(unit="Psi", range=[0, 5000 * 0.000145038]), ) P_SAT = VariableInfo( @@ -448,7 +447,7 @@ class Variables: name="Absolute humidity", unit="g water/kg dry air", range=[0, 0.03 * 1000], - color=Common.DRY_HUMID.value, + color=ColorPalettes.DRY_HUMID.value, IP=IP(unit="lb water/klb dry air", range=[0, 0.03 * 1000]), ) T_WB = VariableInfo( @@ -456,7 +455,7 @@ class Variables: name="Wet bulb temperature", unit="°C", range=[-40, 50], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) T_DP = VariableInfo( @@ -464,7 +463,7 @@ class Variables: name="Dew point temperature", unit="°C", range=[-40, 50], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="°F", range=[-40, 122]), ) EH = VariableInfo( @@ -472,7 +471,7 @@ class Variables: name="Enthalpy", unit="J/kg dry air", range=[0, 110000], - color=Common.BLUE_RED_YELLOW.value, + color=ColorPalettes.BLUE_RED_YELLOW.value, IP=IP(unit="Btu/lb dry air", range=[0, 110000 * 0.000429923]), ) From b4858981558baac0c73c1f6ec1c22c34bee265b6 Mon Sep 17 00:00:00 2001 From: Federico Tartarini Date: Mon, 27 Oct 2025 14:36:25 +1100 Subject: [PATCH 8/9] chore(Dockerfile): enhance image setup with pipenv and improve logging --- Dockerfile | 23 +++++++----- docs/contributing/contributing.md | 4 +-- pages/lib/extract_df.py | 4 +-- requirements.txt | 59 ------------------------------- 4 files changed, 17 insertions(+), 73 deletions(-) delete mode 100644 requirements.txt 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/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 From 4f9a69ba913603befc1592df9b22249ed81d5654 Mon Sep 17 00:00:00 2001 From: Federico Tartarini Date: Mon, 27 Oct 2025 14:38:22 +1100 Subject: [PATCH 9/9] lint(global_variables): ruff format --- pages/lib/global_variables.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/pages/lib/global_variables.py b/pages/lib/global_variables.py index a761d95..b2a3a17 100644 --- a/pages/lib/global_variables.py +++ b/pages/lib/global_variables.py @@ -187,7 +187,10 @@ class Variables: ], IP=IP( unit="Psi", - range=[95000 * ColorPalettes.PA_TO_PSI.value, 105000 * ColorPalettes.PA_TO_PSI.value], + range=[ + 95000 * ColorPalettes.PA_TO_PSI.value, + 105000 * ColorPalettes.PA_TO_PSI.value, + ], ), ) @@ -198,7 +201,10 @@ class Variables: unit="Wh/m2", range=[0, 1200], color=ColorPalettes.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value]), + IP=IP( + unit="Btu/ft2", + range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value], + ), ) HOR_IR_RAD = VariableInfo( col_name="hor_ir_rad", @@ -206,7 +212,10 @@ class Variables: unit="Wh/m2", range=[0, 500], color=ColorPalettes.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 500 * ColorPalettes.WHM2_TO_BTU_FT2.value]), + IP=IP( + unit="Btu/ft2", + range=[0, 500 * ColorPalettes.WHM2_TO_BTU_FT2.value], + ), ) GLOB_HOR_RAD = VariableInfo( col_name="glob_hor_rad", @@ -214,7 +223,10 @@ class Variables: unit="Wh/m2", range=[0, 1200], color=ColorPalettes.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value]), + IP=IP( + unit="Btu/ft2", + range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value], + ), ) DIR_NOR_RAD = VariableInfo( col_name="dir_nor_rad", @@ -222,7 +234,10 @@ class Variables: unit="Wh/m2", range=[0, 1200], color=ColorPalettes.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value]), + IP=IP( + unit="Btu/ft2", + range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value], + ), ) DIF_HOR_RAD = VariableInfo( col_name="dif_hor_rad", @@ -230,7 +245,10 @@ class Variables: unit="Wh/m2", range=[0, 1200], color=ColorPalettes.SUN_COLORS.value, - IP=IP(unit="Btu/ft2", range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value]), + IP=IP( + unit="Btu/ft2", + range=[0, 1200 * ColorPalettes.WHM2_TO_BTU_FT2.value], + ), ) # ==================== Lighting Related Variables ====================