From 62c4518d21d050ba8fb51f9f2ea989ecb58431e0 Mon Sep 17 00:00:00 2001 From: Tristan Gerrish Date: Thu, 7 Nov 2024 10:52:40 +0000 Subject: [PATCH 1/2] Added SRI estimation methods --- .../Python/src/data/sri_data.csv | 442 ++++++++++++++++++ .../src/ladybugtools_toolkit/__init__.py | 17 +- .../honeybee_extension/sri.py | 207 +++++++- .../tests/test_honeybee_extension/test_sri.py | 82 +++- 4 files changed, 727 insertions(+), 21 deletions(-) create mode 100644 LadybugTools_Engine/Python/src/data/sri_data.csv diff --git a/LadybugTools_Engine/Python/src/data/sri_data.csv b/LadybugTools_Engine/Python/src/data/sri_data.csv new file mode 100644 index 00000000..ed7a7ee1 --- /dev/null +++ b/LadybugTools_Engine/Python/src/data/sri_data.csv @@ -0,0 +1,442 @@ +solar_absorptivity,thermal_absorptivity,sri +0.0,0.0,120.5548 +0.0,0.05,121.2417 +0.0,0.1,121.8758 +0.0,0.15,122.5099 +0.0,0.2,123.0911 +0.0,0.25,123.646 +0.0,0.3,124.1744 +0.0,0.35,124.6764 +0.0,0.4,125.1519 +0.0,0.45,125.6275 +0.0,0.5,126.0766 +0.0,0.55,126.4993 +0.0,0.6,126.8956 +0.0,0.65,127.2919 +0.0,0.7,127.6618 +0.0,0.75,128.0053 +0.0,0.8,128.3752 +0.0,0.85,128.6922 +0.0,0.9,129.0092 +0.0,0.95,129.3263 +0.0,1.0,129.6169 +0.05,0.0,109.5376 +0.05,0.05,110.5416 +0.05,0.1,111.4663 +0.05,0.15,112.3646 +0.05,0.2,113.21 +0.05,0.25,114.0026 +0.05,0.3,114.7688 +0.05,0.35,115.4822 +0.05,0.4,116.1691 +0.05,0.45,116.8296 +0.05,0.5,117.4637 +0.05,0.55,118.0713 +0.05,0.6,118.6526 +0.05,0.65,119.2074 +0.05,0.7,119.7358 +0.05,0.75,120.2378 +0.05,0.8,120.7398 +0.05,0.85,121.2153 +0.05,0.9,121.6645 +0.05,0.95,122.1136 +0.05,1.0,122.5363 +0.1,0.0,98.5205 +0.1,0.05,99.8415 +0.1,0.1,101.0832 +0.1,0.15,102.2457 +0.1,0.2,103.3554 +0.1,0.25,104.3857 +0.1,0.3,105.3897 +0.1,0.35,106.3408 +0.1,0.4,107.2391 +0.1,0.45,108.111 +0.1,0.5,108.93 +0.1,0.55,109.7226 +0.1,0.6,110.4624 +0.1,0.65,111.1757 +0.1,0.7,111.889 +0.1,0.75,112.5495 +0.1,0.8,113.1836 +0.1,0.85,113.7913 +0.1,0.9,114.3725 +0.1,0.95,114.9538 +0.1,1.0,115.5086 +0.15,0.0,87.5297 +0.15,0.05,89.1678 +0.15,0.1,90.7001 +0.15,0.15,92.1532 +0.15,0.2,93.5271 +0.15,0.25,94.8481 +0.15,0.3,96.0634 +0.15,0.35,97.2523 +0.15,0.4,98.362 +0.15,0.45,99.4188 +0.15,0.5,100.4491 +0.15,0.55,101.4267 +0.15,0.6,102.3514 +0.15,0.65,103.2232 +0.15,0.7,104.0951 +0.15,0.75,104.8877 +0.15,0.8,105.6803 +0.15,0.85,106.4465 +0.15,0.9,107.1598 +0.15,0.95,107.8732 +0.15,1.0,108.5337 +0.2,0.0,76.5125 +0.2,0.05,78.4941 +0.2,0.1,80.3699 +0.2,0.15,82.1136 +0.2,0.2,83.7517 +0.2,0.25,85.3369 +0.2,0.3,86.8164 +0.2,0.35,88.2166 +0.2,0.4,89.5376 +0.2,0.45,90.8058 +0.2,0.5,92.0211 +0.2,0.55,93.1836 +0.2,0.6,94.2933 +0.2,0.65,95.3501 +0.2,0.7,96.354 +0.2,0.75,97.3316 +0.2,0.8,98.2563 +0.2,0.85,99.1546 +0.2,0.9,100.0 +0.2,0.95,100.8454 +0.2,1.0,101.638 +0.25,0.0,65.4954 +0.25,0.05,67.8468 +0.25,0.1,70.0396 +0.25,0.15,72.1004 +0.25,0.2,74.0291 +0.25,0.25,75.852 +0.25,0.3,77.5694 +0.25,0.35,79.2074 +0.25,0.4,80.7662 +0.25,0.45,82.2457 +0.25,0.5,83.6724 +0.25,0.55,84.9934 +0.25,0.6,86.288 +0.25,0.65,87.5033 +0.25,0.7,88.6922 +0.25,0.75,89.8018 +0.25,0.8,90.8851 +0.25,0.85,91.9155 +0.25,0.9,92.9194 +0.25,0.95,93.8705 +0.25,1.0,94.7952 +0.3,0.0,54.5046 +0.3,0.05,57.1995 +0.3,0.1,59.7358 +0.3,0.15,62.0872 +0.3,0.2,64.3329 +0.3,0.25,66.4201 +0.3,0.3,68.4016 +0.3,0.35,70.2774 +0.3,0.4,72.074 +0.3,0.45,73.7649 +0.3,0.5,75.3501 +0.3,0.55,76.8824 +0.3,0.6,78.362 +0.3,0.65,79.7358 +0.3,0.7,81.0832 +0.3,0.75,82.3514 +0.3,0.8,83.5931 +0.3,0.85,84.7556 +0.3,0.9,85.8917 +0.3,0.95,86.9749 +0.3,1.0,88.0317 +0.35,0.0,43.4875 +0.35,0.05,46.5786 +0.35,0.1,49.4584 +0.35,0.15,52.1532 +0.35,0.2,54.6631 +0.35,0.25,57.041 +0.35,0.3,59.2867 +0.35,0.35,61.4003 +0.35,0.4,63.4082 +0.35,0.45,65.3104 +0.35,0.5,67.107 +0.35,0.55,68.8243 +0.35,0.6,70.4888 +0.35,0.65,72.0476 +0.35,0.7,73.5271 +0.35,0.75,74.9802 +0.35,0.8,76.354 +0.35,0.85,77.675 +0.35,0.9,78.9168 +0.35,0.95,80.1321 +0.35,1.0,81.321 +0.4,0.0,32.4703 +0.4,0.05,35.9577 +0.4,0.1,39.2074 +0.4,0.15,42.2193 +0.4,0.2,45.0462 +0.4,0.25,47.7147 +0.4,0.3,50.1982 +0.4,0.35,52.576 +0.4,0.4,54.7952 +0.4,0.45,56.9089 +0.4,0.5,58.9432 +0.4,0.55,60.8454 +0.4,0.6,62.6684 +0.4,0.65,64.4122 +0.4,0.7,66.0502 +0.4,0.75,67.6354 +0.4,0.8,69.1678 +0.4,0.85,70.6209 +0.4,0.9,72.0211 +0.4,0.95,73.3686 +0.4,1.0,74.6631 +0.45,0.0,21.4795 +0.45,0.05,25.3633 +0.45,0.1,28.9564 +0.45,0.15,32.3382 +0.45,0.2,35.4557 +0.45,0.25,38.4148 +0.45,0.3,41.1889 +0.45,0.35,43.7781 +0.45,0.4,46.2616 +0.45,0.45,48.5865 +0.45,0.5,50.8058 +0.45,0.55,52.9194 +0.45,0.6,54.9009 +0.45,0.65,56.8296 +0.45,0.7,58.6526 +0.45,0.75,60.3963 +0.45,0.8,62.0608 +0.45,0.85,63.646 +0.45,0.9,65.1783 +0.45,0.95,66.6579 +0.45,1.0,68.0845 +0.5,0.0,10.4624 +0.5,0.05,14.7688 +0.5,0.1,18.7583 +0.5,0.15,22.4571 +0.5,0.2,25.9181 +0.5,0.25,29.1678 +0.5,0.3,32.2061 +0.5,0.35,35.0594 +0.5,0.4,37.7543 +0.5,0.45,40.317 +0.5,0.5,42.7477 +0.5,0.55,45.0462 +0.5,0.6,47.2127 +0.5,0.65,49.2999 +0.5,0.7,51.2814 +0.5,0.75,53.1836 +0.5,0.8,55.0066 +0.5,0.85,56.7503 +0.5,0.9,58.4148 +0.5,0.95,60.0 +0.5,1.0,61.5324 +0.55,0.0,0.0 +0.55,0.05,4.2008 +0.55,0.1,8.5865 +0.55,0.15,12.6552 +0.55,0.2,16.4333 +0.55,0.25,19.9736 +0.55,0.3,23.2761 +0.55,0.35,26.3937 +0.55,0.4,29.3263 +0.55,0.45,32.1004 +0.55,0.5,34.716 +0.55,0.55,37.2259 +0.55,0.6,39.5773 +0.55,0.65,41.8494 +0.55,0.7,43.9894 +0.55,0.75,46.0502 +0.55,0.8,48.0053 +0.55,0.85,49.8811 +0.55,0.9,51.6777 +0.55,0.95,53.4214 +0.55,1.0,55.0859 +0.6,0.0,0.0 +0.6,0.05,0.0 +0.6,0.1,0.0 +0.6,0.15,2.8534 +0.6,0.2,6.9749 +0.6,0.25,10.8058 +0.6,0.3,14.3989 +0.6,0.35,17.7807 +0.6,0.4,20.9511 +0.6,0.45,23.9366 +0.6,0.5,26.7635 +0.6,0.55,29.4584 +0.6,0.6,32.0211 +0.6,0.65,34.4518 +0.6,0.7,36.7503 +0.6,0.75,38.9696 +0.6,0.8,41.0832 +0.6,0.85,43.0911 +0.6,0.9,45.0198 +0.6,0.95,46.8692 +0.6,1.0,48.6658 +0.65,0.0,0.0 +0.65,0.05,0.0 +0.65,0.1,0.0 +0.65,0.15,0.0 +0.65,0.2,0.0 +0.65,0.25,1.6909 +0.65,0.3,5.5746 +0.65,0.35,9.1942 +0.65,0.4,12.6288 +0.65,0.45,15.852 +0.65,0.5,18.8904 +0.65,0.55,21.7701 +0.65,0.6,24.4914 +0.65,0.65,27.107 +0.65,0.7,29.5905 +0.65,0.75,31.9419 +0.65,0.8,34.1876 +0.65,0.85,36.354 +0.65,0.9,38.4148 +0.65,0.95,40.3963 +0.65,1.0,42.2985 +0.7,0.0,0.0 +0.7,0.05,0.0 +0.7,0.1,0.0 +0.7,0.15,0.0 +0.7,0.2,0.0 +0.7,0.25,0.0 +0.7,0.3,0.0 +0.7,0.35,0.6869 +0.7,0.4,4.3329 +0.7,0.45,7.7939 +0.7,0.5,11.0436 +0.7,0.55,14.1347 +0.7,0.6,17.041 +0.7,0.65,19.8151 +0.7,0.7,22.4571 +0.7,0.75,24.967 +0.7,0.8,27.3712 +0.7,0.85,29.6697 +0.7,0.9,31.889 +0.7,0.95,33.9762 +0.7,1.0,36.0106 +0.75,0.0,0.0 +0.75,0.05,0.0 +0.75,0.1,0.0 +0.75,0.15,0.0 +0.75,0.2,0.0 +0.75,0.25,0.0 +0.75,0.3,0.0 +0.75,0.35,0.0 +0.75,0.4,0.0 +0.75,0.45,0.0 +0.75,0.5,3.2761 +0.75,0.55,6.5522 +0.75,0.6,9.6433 +0.75,0.65,12.6024 +0.75,0.7,15.4029 +0.75,0.75,18.0713 +0.75,0.8,20.6341 +0.75,0.85,23.0647 +0.75,0.9,25.3897 +0.75,0.95,27.6354 +0.75,1.0,29.7754 +0.8,0.0,0.0 +0.8,0.05,0.0 +0.8,0.1,0.0 +0.8,0.15,0.0 +0.8,0.2,0.0 +0.8,0.25,0.0 +0.8,0.3,0.0 +0.8,0.35,0.0 +0.8,0.4,0.0 +0.8,0.45,0.0 +0.8,0.5,0.0 +0.8,0.55,0.0 +0.8,0.6,2.325 +0.8,0.65,5.4425 +0.8,0.7,8.4016 +0.8,0.75,11.2285 +0.8,0.8,13.9234 +0.8,0.85,16.4861 +0.8,0.9,18.9696 +0.8,0.95,21.321 +0.8,1.0,23.5667 +0.85,0.0,0.0 +0.85,0.05,0.0 +0.85,0.1,0.0 +0.85,0.15,0.0 +0.85,0.2,0.0 +0.85,0.25,0.0 +0.85,0.3,0.0 +0.85,0.35,0.0 +0.85,0.4,0.0 +0.85,0.45,0.0 +0.85,0.5,0.0 +0.85,0.55,0.0 +0.85,0.6,0.0 +0.85,0.65,0.0 +0.85,0.7,1.4531 +0.85,0.75,4.4386 +0.85,0.8,7.2919 +0.85,0.85,9.9868 +0.85,0.9,12.576 +0.85,0.95,15.0594 +0.85,1.0,17.4373 +0.9,0.0,0.0 +0.9,0.05,0.0 +0.9,0.1,0.0 +0.9,0.15,0.0 +0.9,0.2,0.0 +0.9,0.25,0.0 +0.9,0.3,0.0 +0.9,0.35,0.0 +0.9,0.4,0.0 +0.9,0.45,0.0 +0.9,0.5,0.0 +0.9,0.55,0.0 +0.9,0.6,0.0 +0.9,0.65,0.0 +0.9,0.7,0.0 +0.9,0.75,0.0 +0.9,0.8,0.6869 +0.9,0.85,3.5403 +0.9,0.9,6.2616 +0.9,0.95,8.8771 +0.9,1.0,11.3606 +0.95,0.0,0.0 +0.95,0.05,0.0 +0.95,0.1,0.0 +0.95,0.15,0.0 +0.95,0.2,0.0 +0.95,0.25,0.0 +0.95,0.3,0.0 +0.95,0.35,0.0 +0.95,0.4,0.0 +0.95,0.45,0.0 +0.95,0.5,0.0 +0.95,0.55,0.0 +0.95,0.6,0.0 +0.95,0.65,0.0 +0.95,0.7,0.0 +0.95,0.75,0.0 +0.95,0.8,0.0 +0.95,0.85,0.0 +0.95,0.9,0.0 +0.95,0.95,2.7213 +0.95,1.0,5.3369 +1.0,0.0,0.0 +1.0,0.05,0.0 +1.0,0.1,0.0 +1.0,0.15,0.0 +1.0,0.2,0.0 +1.0,0.25,0.0 +1.0,0.3,0.0 +1.0,0.35,0.0 +1.0,0.4,0.0 +1.0,0.45,0.0 +1.0,0.5,0.0 +1.0,0.55,0.0 +1.0,0.6,0.0 +1.0,0.65,0.0 +1.0,0.7,0.0 +1.0,0.75,0.0 +1.0,0.8,0.0 +1.0,0.85,0.0 +1.0,0.9,0.0 +1.0,0.95,0.0 +1.0,1.0,0.0 diff --git a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/__init__.py b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/__init__.py index 2513fa5a..44a425ae 100644 --- a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/__init__.py +++ b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/__init__.py @@ -4,12 +4,23 @@ import os from pathlib import Path +import matplotlib.pyplot as plt + # pylint: disable=E0401 -import matplotlib.pyplot as plt +# get common paths +DATA_DIRECTORY = (Path(__file__).parent.parent / "data").absolute() +BHOM_DIRECTORY = (Path(__file__).parent / "bhom").absolute() +HOME_DIRECTORY = (Path("C:/Users/") / getpass.getuser()).absolute() # override "HOME" in case IT has set this to something other than default -os.environ["HOME"] = (Path("C:/Users/") / getpass.getuser()).as_posix() +os.environ["HOME"] = HOME_DIRECTORY.as_posix() # set plotting style for modules within this toolkit -plt.style.use(Path(__file__).parent / "bhom" / "bhom.mplstyle") +plt.style.use(BHOM_DIRECTORY / "bhom.mplstyle") + +# get dataset paths +SRI_DATA = DATA_DIRECTORY / "sri_data.csv" +KOEPPEN_DATA = DATA_DIRECTORY / "koeppen.csv" +ICE_MATERIALS_DATA = DATA_DIRECTORY / "ICE_database_sources.xlsx.csv" +VEGETATION_DATA = DATA_DIRECTORY / "vegetation.json" diff --git a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py index a79c2cc5..74df0aed 100644 --- a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py +++ b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py @@ -1,9 +1,17 @@ """Methods for calculating the Solar Reflective Index (SRI) of materials and constructions.""" import numpy as np +import pandas as pd +from honeybee.typing import clean_string from honeybee_energy.construction.opaque import OpaqueConstruction from honeybee_energy.material.opaque import EnergyMaterial +from honeybee_radiance.modifier.material import Plastic +from matplotlib.colors import hex2color +from sklearn.linear_model import LinearRegression + +from .. import SRI_DATA from ..bhom.analytics import bhom_analytics +from ..bhom.logging import CONSOLE_LOGGER @bhom_analytics() @@ -42,11 +50,11 @@ def calculate_sri( if not 0 <= solar_reflectance <= 1: raise ValueError( - "Solar reflectance must be between 0 (black body) and 1 (white-body)." + "Solar reflectance must be between 0 (black body) - 1 (white-body)." ) if not 0 <= thermal_emittance <= 1: raise ValueError( - "Thermal emittance must be between 0 (white-body) and 1 (black-body)." + "Thermal emittance must be between 0 (white-body) - 1 (black-body)." ) if wind_speed < 0: raise ValueError("Wind speed must be greater than 0.") @@ -56,7 +64,7 @@ def calculate_sri( coeffs = [5, 12, 30] wind_convection_coefficient = np.interp(wind_speed, speeds, coeffs) - # set the sensitivity threshold for the iterative calculation. Lower is more accurate but slower. + # set the sensitivity threshold for iterative calculation. Lower is more accurate but slower. threshold = 0.5 # W increment = 0.01 # K iterations = 100000 @@ -86,7 +94,8 @@ def calculate_sri( n += 1 if n > iterations: raise ValueError( - f"SRI calculation did not converge. Surface temperature of {surface_temperature - 273.15}C." + ("SRI calculation did not converge. Surface temperature of " + f"{surface_temperature - 273.15}C.") ) surface_temperature += increment @@ -204,3 +213,193 @@ def construction_sri( sky_temperature=sky_temperature, wind_speed=wind_speed, ) + +@bhom_analytics() +def estimate_sri_from_color( + color_hex: str, + thermal_emittance: float = 0.9, +) -> float: + """Estimate the SRI of a material from its color. + + Note: + This uses predefined datasets from + - https://www.deansteelbuildings.com/products/panels/paint-finish-color-selections/ + - https://www.berridge.com/resources/chart-of-sri-values/ + as the basis for the estimation of solar reflectance from colour luminosity. + + This method is an estimation and may not be accurate. It is usually + within ±10 of the actual SRI; however as full material properties are + not determinable from a HEX colour, then the resulting value must be + caveated with this warning! Metallic material finishes usually show + the largest discrepancy. + + Args: + color_hex (str): + A color string in hex format. + thermal_emittance (float): + Thermal emittance of the material. Unitless. Default is 0.9. + + Returns: + float: + SRI of the material. Unitless. + """ + + # create a dataframe of the pre-defined colours and their respective SRI values + df = pd.DataFrame( + columns=["color", "reported_sr", "reported_sri", "hex"], + data=[ + ["DSB Aluminum Zinc", 0.68, 55, "#dbdbe6"], + ["DSB Oyster White", 0.52, 59, "#dfdbd4"], + ["DSB Polar White", 0.61, 73, "#e2e8e7"], + ["DSB Light Stone", 0.56, 65, "#cec5a8"], + ["DSB Hawaiian Blue", 0.31, 31, "#406d84"], + ["DSB Sahara Tan", 0.47, 53, "#ad9277"], + ["DSB Ash Grey", 0.46, 52, "#a2a0a1"], + ["DSB Burnished Bronze", 0.28, 29, "#372c26"], + ["DSB Colony Green", 0.35, 37, "#657761"], + ["DSB Fern Green", 0.29, 29, "#0b2d1d"], + ["DSB Almond", 0.63, 75, "#ded8be"], + ["DSB Snow White", 0.65, 78, "#e1e6e9"], + ["DSB Brownstone", 0.47, 53, "#9f927f"], + ["DSB Black", 0.25, 24, "#000000"], + ["DSB Copper Metallic", 0.46, 51, "#b76e4c"], + ["DSB Scarlet Red", 0.42, 47, "#d6141c"], + ["DSB Harbor Blue", 0.26, 25, "#00405b"], + ["DSB Hunter Green", 0.35, 39, "#1c453c"], + ["DSB Roman Blue", 0.32, 33, "#366e87"], + ["DSB Colonial Red", 0.34, 37, "#6b312d"], + ["DSB Everglade", 0.33, 36, "#39706a"], + ["DSB Slate Grey", 0.37, 41, "#82847f"], + ["BER Aged Bronze", 0.31, 31, "#504533"], + ["BER Almond", 0.65, 77, "#e1e5cc"], + ["BER Bristol Blue", 0.33, 33, "#3a6c80"], + ["BER Buckskin", 0.43, 46, "#847f67"], + ["BER Burgundy", 0.32, 32, "#462523"], + ["BER Charcoal Grey", 0.29, 28, "#444949"], + ["BER Cityscape", 0.48, 54, "#99a1a7"], + ["BER Colonial Red", 0.35, 35, "#6c2927"], + ["BER Copper Brown", 0.32, 32, "#49382b"], + ["BER Dark Bronze", 0.28, 27, "#3c362e"], + ["BER Deep Red", 0.41, 44, "#a11e30"], + ["BER Evergreen", 0.3, 29, "#325a43"], + ["BER Forest Green", 0.3, 29, "#37614d"], + ["BER Hartford Green", 0.27, 25, "#33463b"], + ["BER Hemlock Green", 0.31, 31, "#597c6c"], + ["BER Matte Black", 0.26, 24, "#282b2d"], + ["BER Medium Bronze", 0.31, 31, "#5c4a36"], + ["BER Parchment", 0.6, 71, "#d3d2c6"], + ["BER Patina Green", 0.34, 35, "#5f9880"], + ["BER Royal Blue", 0.27, 26, "#004862"], + ["BER Shasta White", 0.61, 73, "#dde0dd"], + ["BER Sierra Tan", 0.39, 42, "#a49a7a"], + ["BER Teal Green", 0.26, 25, "#3d766f"], + ["BER Terra - Cota", 0.36, 38, "#a44f38"], + ["BER Zinc Grey", 0.39, 42, "#778082"], + ["BER Acrylic-Coated Galvalume'", 0.67, 59, "#e6e8e8"], + ["BER Award Blue", 0.17, 11, "#113f67"], + ["BER Natural White", 0.71, 86, "#fffef8"], + ["BER Antique Copper-Cote", 0.33, 34, "#818c6f"], + ["BER Champagne", 0.4, 43, "#9b9484"], + ["BER Copper-Cote", 0.51, 59, "#bc7038"], + ["BER Lead-Cote", 0.36, 38, "#9c9999"], + ["BER Preweathered Galvalume", 0.4, 43, "#7b8184"], + ["BER Zinc-Cote", 0.53, 59, "#c9cbcc"], + ["BER COR-TEN AZP Raw", 0.32, 34, "#a86a54"], + ], + ) + df.set_index("color", drop=True, inplace=True) + df.sort_values("reported_sri", inplace=True) + + # add r, g, b as 0-1 + df["r"], df["g"], df["b"] = np.array([hex2color(i) for i in df.hex]).T + + # create radiance modifiers from the pre-defined colors, and determine solar reflectance + df["radiance_material"] = [ + Plastic( + identifier=clean_string(row), + r_reflectance=i.r, + g_reflectance=i.g, + b_reflectance=i.b, + ) + for row, i in df.iterrows() + ] + df["radiance_reflectivity"] = [i.average_reflectance for i in df.radiance_material] + + # get polynomial approximator for SR based on relationship between reported SR and Radiance calculated SR + z = np.polyfit(df.dropna().radiance_reflectivity, df.dropna()["reported_sr"], 2) + p = np.poly1d(z) + + # create dataframe for the passed colors + color_r, color_g, color_b = hex2color(color_hex) + color_plastic = Plastic( + identifier="custom_color", + r_reflectance=color_r, + g_reflectance=color_g, + b_reflectance=color_b, + ) + color_estimated_sr = p(color_plastic.average_reflectance) + color_estimated_sri = calculate_sri( + solar_reflectance=color_estimated_sr, + thermal_emittance=thermal_emittance, + ) + + return color_estimated_sri + +@bhom_analytics() +def estimate_sri_properties( + target_sri: float, target_emittance: float = 0.85, tolerance: float = 5 +) -> tuple[float, float]: + """Estimate solar absorptance and thermal emittance for a target SRI. + + This method uses a linear regression model to estimate the solar absorptance and + thermal emittance of a material to achieve a target Solar Reflective Index (SRI). + The model is trained on a dataset of these properties and the resultant SRI using + fixed values for insolation, air_temperature, sky_temperature, and wind_speed. + + Args: + target_sri (float): + The target Solar Reflective Index (SRI) for the material. + target_emittance (float, optional): + The target Thermal Emittance for the material. Default is 0.85. + tolerance (float, optional): + The acceptable tolerance between resultant SRI and target SRI. Default is 5. + + Returns: + tuple[float, float]: The estimated solar absorptance and thermal emittance. + """ + + if target_sri < 0 or target_sri > 122: + raise ValueError("Target SRI must be between 0 and 122.") + + if target_emittance <= 0 or target_emittance >= 1: + raise ValueError( + "Thermal absorptivity estimation is beyond allowable limits for the target SRI." + ) + + # load the dataset + data = pd.read_csv(SRI_DATA, header=0) + + model = LinearRegression() + model.fit( + data[["solar_absorptivity", "thermal_absorptivity"]].values, data["sri"].values + ) + + possible_combinations = [] + sris = [] + for sa in np.linspace(0, 1, 101): + sri = model.predict([[sa, target_emittance]])[0] + if np.isclose(sri, target_sri, atol=tolerance): + possible_combinations.append(sa) + sris.append(sri) + sa_ = round(np.mean(possible_combinations), 4) + ta_ = round(target_emittance, 4) + + if sa_ <= 0 or sa_ >= 1: + CONSOLE_LOGGER.error( + ( + "Solar absorptivity estimation is beyond allowable limits " + "for the target SRI." + ) + ) + + return float(sa_), ta_ diff --git a/LadybugTools_Engine/Python/tests/test_honeybee_extension/test_sri.py b/LadybugTools_Engine/Python/tests/test_honeybee_extension/test_sri.py index edc77f04..c29a92b1 100644 --- a/LadybugTools_Engine/Python/tests/test_honeybee_extension/test_sri.py +++ b/LadybugTools_Engine/Python/tests/test_honeybee_extension/test_sri.py @@ -1,26 +1,22 @@ +"""Test methods for SRI calculations.""" + import pytest from honeybee_energy.construction.opaque import OpaqueConstruction from honeybee_energy.material.opaque import EnergyMaterial from ladybugtools_toolkit.honeybee_extension.sri import ( - calculate_sri, - construction_sri, - material_sri, -) - -MATERIAL = EnergyMaterial( - "sri_material", 1, 1, 100, 100, solar_absorptance=0.5, thermal_absorptance=0.9 -) + calculate_sri, construction_sri, estimate_sri_from_color, + estimate_sri_properties, material_sri) + +MATERIAL = EnergyMaterial("sri_material", 1, 1, 100, 100, solar_absorptance=0.5, thermal_absorptance=0.9) CONSTRUCTION = OpaqueConstruction("sri_construction", [MATERIAL]) def test_calculate_sri() -> None: """_""" - assert calculate_sri( - solar_reflectance=0.35, thermal_emittance=0.85, wind_speed=4 - ) == pytest.approx(36.354029062087186, 0.001) - assert calculate_sri( - solar_reflectance=0.35, thermal_emittance=0.85, wind_speed=0, air_temperature=40 - ) == pytest.approx(33.394936240990575, 0.001) + assert calculate_sri(solar_reflectance=0.35, thermal_emittance=0.85, wind_speed=4) == pytest.approx(36.354029062087186, 0.001) + assert calculate_sri(solar_reflectance=0.35, thermal_emittance=0.85, wind_speed=0, air_temperature=40) == pytest.approx( + 33.394936240990575, 0.001 + ) assert calculate_sri( solar_reflectance=0.35, thermal_emittance=0.85, @@ -39,3 +35,61 @@ def test_construction_sri() -> None: def test_material_sri() -> None: """_""" assert material_sri(MATERIAL) == pytest.approx(58.414795244385736, 0.001) + + +def test_sri_from_color() -> None: + """_""" + color_hexs = [ + "#82898F", + "#82898F", + "#A18594", + "#A18594", + "#FFFFFF", + "#FFFFFF", + "#C1876B", + "#C1876B", + "#000000", + "#000000", + ] + thermal_emittances = [ + 0.1, + 0.9, + 0.1, + 0.5, + 0.5, + 0.9, + 0.1, + 0.5, + 0.1, + 0.5, + ] + results = [ + 0, + 44.94055482166446, + 0.607661822985469, + 28.480845442536328, + 79.7886393659181, + 89.6433289299868, + 3.5667107001321003, + 30.779392338177015, + 0, + 6.737120211360634, + ] + for color_hex, thermal_emittance, result in zip(color_hexs, thermal_emittances, results): + assert estimate_sri_from_color(color_hex=color_hex, thermal_emittance=thermal_emittance) == pytest.approx(result, 0.001) + + +def test_estimate_sri_properties() -> None: + """_""" + for target_sri, target_emittance, result in [ + (10, 0.1, (0.7, 0.1)), + (10, 0.5, (0.785, 0.5)), + (10, 0.9, (0.87, 0.9)), + (50, 0.1, (0.405, 0.1)), + (50, 0.5, (0.49, 0.5)), + (50, 0.9, (0.575, 0.9)), + (100, 0.1, (0.03, 0.1)), + (100, 0.5, (0.115, 0.5)), + (100, 0.9, (0.2, 0.9)), + ]: + assert estimate_sri_properties(target_sri=target_sri, target_emittance=target_emittance) == pytest.approx(result, 0.001) From e86ae4ca46f87e80c4d0cf978ccb5fff5ec9c25b Mon Sep 17 00:00:00 2001 From: Tristan Gerrish <10939984+tg359@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:31:12 +0000 Subject: [PATCH 2/2] updated bhom.analytics import reference Co-authored-by: Thomas Edward Kingstone --- .../Python/src/ladybugtools_toolkit/honeybee_extension/sri.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py index 125f3b75..3196120f 100644 --- a/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py +++ b/LadybugTools_Engine/Python/src/ladybugtools_toolkit/honeybee_extension/sri.py @@ -11,8 +11,8 @@ from sklearn.linear_model import LinearRegression from .. import SRI_DATA -from ..bhom.analytics import bhom_analytics -from ..bhom.logging import CONSOLE_LOGGER +from python_toolkit.bhom.analytics import bhom_analytics +from python_toolkit.bhom.logging import CONSOLE_LOGGER @bhom_analytics()