Source code for ladybug_comfort.collection.solarcal

# coding=utf-8
"""Objects for calculating solar-adjusted MRT from DataCollections."""
from __future__ import division

from ..solarcal import outdoor_sky_heat_exch, indoor_sky_heat_exch, \
    shortwave_from_horiz_solar, shortwave_from_horiz_components, \
    sharp_from_solar_and_body_azimuth
from ..parameter.solarcal import SolarCalParameter
from .base import ComfortCollection

from ladybug.location import Location
from ladybug.sunpath import Sunpath
from ladybug.datacollection import HourlyDiscontinuousCollection

from ladybug.datatype.temperature import Temperature, MeanRadiantTemperature
from ladybug.datatype.temperaturedelta import RadiantTemperatureDelta
from ladybug.datatype.energyflux import Irradiance, EffectiveRadiantField, \
    HorizontalInfraredRadiationIntensity, DiffuseHorizontalIrradiance, \
    DirectNormalIrradiance, DirectHorizontalIrradiance
from ladybug.datatype.energyintensity import Radiation
from ladybug.datatype.fraction import Fraction


class _SolarCalBase(ComfortCollection):
    """Base class used by all objects that use SolarCal with Data Collections."""
    __slots__ = ('_location', '_fract_exp', '_flr_ref', '_body_par', '_dmrt', '_mrt',
                 '_fract_exp_coll', '_flr_ref_coll', '_dmrt_coll', '_mrt_coll')

    def __init__(self, location, fraction_body_exposed=None, floor_reflectance=None,
                 solarcal_body_parameter=None):
        # set required inputs
        self._location_check(location)

        # check optional inputs
        self._fract_exp = self._fraction_input_check(
            fraction_body_exposed, 'fraction_body_exposed', 1)
        self._flr_ref = self._fraction_input_check(
            floor_reflectance, 'floor_reflectance', 0.25)

        # check comfort parameters
        self._body_par_check(solarcal_body_parameter)

        # setup lists to be filled
        self._dmrt = []
        self._mrt = []

    @property
    def location(self):
        """Ladybug Location object."""
        return self._location.duplicate()

    @property
    def fraction_body_exposed(self):
        """Data Collection of body fraction exposed to direct sun."""
        return self._get_coll('_fract_exp_coll', self._fract_exp,
                              Fraction('Fraction Body Exposed'), 'fraction')

    @property
    def floor_reflectance(self):
        """Data Collection of floor reflectance."""
        return self._get_coll('_flr_ref_coll', self._flr_ref,
                              Fraction('Floor Reflectance'), 'fraction')

    @property
    def solarcal_body_parameter(self):
        """SolarCal body parameters that are assigned to this object."""
        return self._body_par

    @property
    def mrt_delta(self):
        """Data Collection of total MRT delta in C."""
        return self._get_coll('_dmrt_coll', self._dmrt, RadiantTemperatureDelta, 'dC')

    @property
    def mean_radiant_temperature(self):
        """Data Collection of total mean radiant temperature in C."""
        return self._get_coll('_mrt_coll', self._mrt, MeanRadiantTemperature, 'C')

    def _location_check(self, location):
        assert isinstance(location, Location), 'location must be a Ladybug Location' \
            ' object. Got {}.'.format(type(location))
        self._location = location.duplicate()

    def _radiation_check(self, data_coll, name):
        assert isinstance(data_coll, HourlyDiscontinuousCollection), \
            '{} must be an hourly collection. Got {}.'.format(name, type(data_coll))
        if isinstance(data_coll.header.data_type, Radiation):
            self._check_datacoll(data_coll, Radiation, 'Wh/m2', name)
            timestep = data_coll.header.analysis_period.timestep
            assert timestep == 1, '{} timestep must be 1 when using Radiation as the ' \
                'data type. Got timestep of {}'.format(name, timestep)
        else:
            self._check_datacoll(data_coll, Irradiance, 'W/m2', name)

    def _fraction_input_check(self, data_coll, name, default):
        if data_coll is not None:
            return self._check_input(data_coll, Fraction, 'fraction', name)
        else:
            return [default] * self._calc_length

    def _body_par_check(self, body_par):
        if body_par is None:
            self._body_par = SolarCalParameter(posture='standing')
        else:
            assert isinstance(body_par, SolarCalParameter), \
                'solarcal_body_parameter must be a SolarCalParameter object. Got {}'\
                .format(type(body_par))
            self._body_par = body_par

    def _get_altitudes_and_sharps(self):
        """Get altitudes and sharps from solar position."""
        sp = Sunpath.from_location(self._location)
        _altitudes = []
        if self._body_par.body_azimuth is None:
            _sharps = [self._body_par.sharp] * self._calc_length
            for t_date in self._base_collection.datetimes:
                sun = sp.calculate_sun_from_date_time(t_date)
                _altitudes.append(sun.altitude)
        else:
            _sharps = []
            for t_date in self._base_collection.datetimes:
                sun = sp.calculate_sun_from_date_time(t_date)
                sharp = sharp_from_solar_and_body_azimuth(sun.azimuth,
                                                          self._body_par.body_azimuth)
                _sharps.append(sharp)
                _altitudes.append(sun.altitude)
        return _altitudes, _sharps


[docs]class OutdoorSolarCal(_SolarCalBase): """Outdoor SolarCal Collection object. Args: location: A Ladybug Location object. direct_normal_solar: Hourly Data Collection with the direct normal solar irradiance in W/m2. diffuse_horizontal_solar: Hourly Data Collection with the diffuse horizontal solar irradiance in W/m2. surface_temperatures: Hourly Data Collection with the temperature of surfaces around the person in degrees Celsius. This includes the ground and any other surfaces blocking the view to the sky. When the temperature of these individual surfaces are known, the input here should be the average temperature of the surfaces weighted by view-factor to the human. When such individual surface temperatures are unknown, the outdoor dry bulb temperature is typically used as a proxy. horizontal_infrared: Hourly Data Collection with the horizontal infrared radiation intensity from the sky in W/m2. fraction_body_exposed: A Data Collection or number between 0 and 1 representing the fraction of the body exposed to direct sunlight. Note that this does not include the body’s self-shading; only the shading from surroundings. Default is 1 for a person standing in an open area. sky_exposure: A Data Collection or number between 0 and 1 representing the fraction of the sky vault in occupant’s view. Default is 1 for a person standing in an open area. floor_reflectance: A Data Collection or number between 0 and 1 that represents the reflectance of the floor. Default is for 0.25 which is characteristic of outdoor grass or dry bare soil. solarcal_body_parameter: Optional SolarCalParameter object to account for properties of the human geometry. Properties: * location * direct_normal_solar * diffuse_horizontal_solar * horizontal_infrared * surface_temperatures * fraction_body_exposed * sky_exposure * floor_reflectance * solarcal_body_parameter * shortwave_effective_radiant_field * longwave_effective_radiant_field * shortwave_mrt_delta * longwave_mrt_delta * mrt_delta * mean_radiant_temperature """ _model = 'Outdoor SolarCal' __slots__ = ('_dir_norm', '_diff_horiz', '_horiz_ir', '_srf_temp', '_sky_exp', '_s_erf', '_s_dmrt', '_l_erf', '_l_dmrt', '_dir_norm_coll', '_diff_horiz_coll', '_horiz_ir_coll', '_srf_temp_coll', '_sky_exp_coll', '_s_erf_coll', '_s_dmrt_coll', '_l_erf_coll', '_l_dmrt_coll') def __init__(self, location, direct_normal_solar, diffuse_horizontal_solar, horizontal_infrared, surface_temperatures, fraction_body_exposed=None, sky_exposure=None, floor_reflectance=None, solarcal_body_parameter=None): """Initialize Outdoor SolarCal object. """ # set up the object using radiation as a base self._radiation_check(direct_normal_solar, 'direct_normal_solar') self._radiation_check(diffuse_horizontal_solar, 'diffuse_horizontal_solar') self._input_collections = [direct_normal_solar, diffuse_horizontal_solar] self._calc_length = len(direct_normal_solar) self._base_collection = direct_normal_solar # check required inputs _SolarCalBase.__init__(self, location, fraction_body_exposed, floor_reflectance, solarcal_body_parameter) self._dir_norm = direct_normal_solar.values self._diff_horiz = diffuse_horizontal_solar.values self._horiz_ir = self._check_input( horizontal_infrared, HorizontalInfraredRadiationIntensity, 'W/m2', 'horizontal_infrared') self._srf_temp = self._check_input( surface_temperatures, Temperature, 'C', 'surface_temperatures') assert self._horiz_ir[0] != 9999, 'Missing data for Horizontal ' \ 'Infrared has been detected. Make sure that this data is not missing ' \ 'from the EPW.' # check optional inputs self._sky_exp = self._fraction_input_check(sky_exposure, 'sky_exposure', 1) # check that all input data collections are aligned. HourlyDiscontinuousCollection.are_collections_aligned(self._input_collections) # compute SolarCal self._calculate_solarcal() def _calculate_solarcal(self): """Compute SolarCal for each step of the Data Collection.""" # empty lists to be filled self._s_erf = [] self._s_dmrt = [] self._l_erf = [] self._l_dmrt = [] # get altitudes and sharps from solar position _altitudes, _sharps = self._get_altitudes_and_sharps() # calculate final erfs and mrt deltas for t_srfs, horiz_ir, diff, dir, alt, sharp, sky_e, fract_e, flr_ref in \ zip(self._srf_temp, self._horiz_ir, self._diff_horiz, self._dir_norm, _altitudes, _sharps, self._sky_exp, self._fract_exp, self._flr_ref): result = outdoor_sky_heat_exch(t_srfs, horiz_ir, diff, dir, alt, sky_e, fract_e, flr_ref, self._body_par.posture, sharp, self._body_par.body_absorptivity, self._body_par.body_emissivity) self._s_erf.append(result['s_erf']) self._s_dmrt.append(result['s_dmrt']) self._l_erf.append(result['l_erf']) self._l_dmrt.append(result['l_dmrt']) self._dmrt.append(result['s_dmrt'] + result['l_dmrt']) self._mrt.append(result['mrt']) @property def diffuse_horizontal_solar(self): """Data Collection of diffuse horizontal irradiance in W/m2.""" return self._get_coll('_diff_horiz_coll', self._diff_horiz, DiffuseHorizontalIrradiance, 'W/m2') @property def direct_normal_solar(self): """Data Collection of direct normal irradiance in W/m2.""" return self._get_coll('_dir_norm_coll', self._dir_norm, DirectNormalIrradiance, 'W/m2') @property def surface_temperatures(self): """Data Collection of surface temperature values in degrees C.""" return self._get_coll('_srf_temp_coll', self._srf_temp, Temperature('Surface Temperature'), 'C') @property def horizontal_infrared(self): """Data Collection of horizontal infrared radiation intensity in W/m2.""" return self._get_coll('_horiz_ir_coll', self._horiz_ir, HorizontalInfraredRadiationIntensity, 'W/m2') @property def sky_exposure(self): """Data Collection of sky view.""" return self._get_coll('_sky_exp_coll', self._sky_exp, Fraction('Sky Exposure'), 'fraction') @property def shortwave_effective_radiant_field(self): """Data Collection of shortwave effective radiant field in W/m2.""" return self._get_coll('_s_erf_coll', self._s_erf, EffectiveRadiantField, 'W/m2') @property def longwave_effective_radiant_field(self): """Data Collection of longwave effective radiant field in W/m2.""" return self._get_coll('_l_erf_coll', self._l_erf, EffectiveRadiantField, 'W/m2') @property def shortwave_mrt_delta(self): """Data Collection of shortwave MRT delta in C.""" return self._get_coll('_s_dmrt_coll', self._s_dmrt, RadiantTemperatureDelta, 'dC') @property def longwave_mrt_delta(self): """Data Collection of longwave MRT delta in C.""" return self._get_coll('_l_dmrt_coll', self._l_dmrt, RadiantTemperatureDelta, 'dC')
[docs]class IndoorSolarCal(_SolarCalBase): """Indoor SolarCal Collection object. Args: location: A Ladybug Location object. direct_normal_solar: Hourly Data Collection with the direct normal solar irradiance in W/m2. diffuse_horizontal_solar: Hourly Data Collection with the diffuse horizontal solar irradiance in W/m2. longwave_mrt: Hourly Data Collection or individual value with the longwave mean radiant temperature (MRT) expereinced as a result of indoor surface temperatures in C. fraction_body_exposed: A Data Collection or number between 0 and 1 representing the fraction of the body exposed to direct sunlight. Note that this does not include the body’s self-shading; only the shading from surroundings. Default is 1 for a person standing in an open area. sky_exposure: A Data Collection or number between 0 and 1 representing the fraction of the sky vault in occupant’s view. Default is 1 for a person standing in an open area. floor_reflectance: A Data Collection or number between 0 and 1 that represents the reflectance of the floor. Default is for 0.25 which is characteristic of outdoor grass or dry bare soil. window_transmittance: A Data Collection or number between 0 and 1 that represents the broadband solar transmittance of the window through which the sun is coming. Such values tend to be slightly less than the SHGC. Values might be as low as 0.2 and could be as high as 0.85 for a single pane of glass. Default is 0.4 assuming a double pane window with a relatively mild low-e coating. solarcal_body_parameter: Optional SolarCalParameter object to account for properties of the human geometry. Properties: * location * direct_normal_solar * diffuse_horizontal_solar * longwave_mrt * fraction_body_exposed * sky_exposure * floor_reflectance * window_transmittance * solarcal_body_parameter * effective_radiant_field * mrt_delta * mean_radiant_temperature """ _model = 'Indoor SolarCal' __slots__ = ('_dir_norm', '_diff_horiz', '_l_mrt', '_sky_exp', '_win_trans', '_erf', '_dmrt', '_dir_norm_coll', '_diff_horiz_coll', '_l_mrt_coll', '_sky_exp_coll', '_win_trans_coll', '_erf_coll', '_dmrt_coll') def __init__(self, location, direct_normal_solar, diffuse_horizontal_solar, longwave_mrt, fraction_body_exposed=None, sky_exposure=None, floor_reflectance=None, window_transmittance=None, solarcal_body_parameter=None): """Initialize Indoor SolarCal object. """ # set up the object using radiation as a base self._radiation_check(direct_normal_solar, 'direct_normal_solar') self._radiation_check(diffuse_horizontal_solar, 'diffuse_horizontal_solar') self._input_collections = [direct_normal_solar, diffuse_horizontal_solar] self._calc_length = len(direct_normal_solar) self._base_collection = direct_normal_solar # check required inputs _SolarCalBase.__init__(self, location, fraction_body_exposed, floor_reflectance, solarcal_body_parameter) self._dir_norm = direct_normal_solar.values self._diff_horiz = diffuse_horizontal_solar.values self._l_mrt = self._check_input(longwave_mrt, Temperature, 'C', 'longwave_mrt') # check optional inputs self._sky_exp = self._fraction_input_check( sky_exposure, 'sky_exposure', 1) self._win_trans = self._fraction_input_check( window_transmittance, 'window_transmittance', 0.4) # check that all input data collections are aligned. HourlyDiscontinuousCollection.are_collections_aligned(self._input_collections) # compute SolarCal self._calculate_solarcal() def _calculate_solarcal(self): """Compute SolarCal for each step of the Data Collection.""" # empty lists to be filled self._erf = [] # get altitudes and sharps from solar position _altitudes, _sharps = self._get_altitudes_and_sharps() # calculate final erfs and mrt deltas for l_mrt, diff, dir, alt, sharp, sky_e, fract_e, flr_ref, w_trans in \ zip(self._l_mrt, self._diff_horiz, self._dir_norm, _altitudes, _sharps, self._sky_exp, self._fract_exp, self._flr_ref, self._win_trans): result = indoor_sky_heat_exch(l_mrt, diff, dir, alt, sky_e, fract_e, flr_ref, w_trans, self._body_par.posture, sharp, self._body_par.body_absorptivity, self._body_par.body_emissivity) self._erf.append(result['erf']) self._dmrt.append(result['dmrt']) self._mrt.append(result['mrt']) @property def diffuse_horizontal_solar(self): """Data Collection of diffuse horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_diff_horiz_coll', self._diff_horiz, DiffuseHorizontalIrradiance, 'W/m2') @property def direct_normal_solar(self): """Data Collection of direct normal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_dir_norm_coll', self._dir_norm, DirectNormalIrradiance, 'W/m2') @property def longwave_mrt(self): """Data Collection of surface temperature values in degrees C.""" return self._get_coll('_l_mrt_coll', self._l_mrt, MeanRadiantTemperature, 'C') @property def sky_exposure(self): """Data Collection of sky view.""" return self._get_coll('_sky_exp_coll', self._sky_exp, Fraction('Sky Exposure'), 'fraction') @property def window_transmittance(self): """Data Collection of window transmittance.""" return self._get_coll('_win_trans_coll', self._win_trans, Fraction('Window Transmittance'), 'fraction') @property def effective_radiant_field(self): """Data Collection of shortwave effective radiant field in W/m2.""" return self._get_coll('_erf_coll', self._erf, EffectiveRadiantField, 'W/m2') @property def mrt_delta(self): """Data Collection of shortwave MRT delta in C.""" return self._get_coll('_dmrt_coll', self._dmrt, RadiantTemperatureDelta, 'dC')
[docs]class HorizontalSolarCal(_SolarCalBase): """SolarCal Collection object from horizontal solar components. This is particularly useful when trying to estimate solar MRT deltas from Radiance radiation simulation result. Args: location: A Ladybug Location object. direct_horizontal_solar: Hourly Data Collection with the direct horizontal solar irradiance in W/m2. diffuse_horizontal_solar: Hourly Data Collection with the diffuse horizontal solar irradiance in W/m2. longwave_mrt: Hourly Data Collection or individual value with the longwave mean radiant temperature (MRT) expereinced as a result of indoor surface temperatures in C. fraction_body_exposed: A Data Collection or number between 0 and 1 representing the fraction of the body exposed to direct sunlight. Note that this does not include the body’s self-shading; only the shading from surroundings. Default is 1 for a person standing in an open area. floor_reflectance: A Data Collection or number between 0 and 1 that represents the reflectance of the floor. Default is for 0.25 which is characteristic of outdoor grass or dry bare soil. solarcal_body_parameter: Optional SolarCalParameter object to account for properties of the human geometry. Properties: * location * direct_horizontal_solar * diffuse_horizontal_solar * longwave_mrt * fraction_body_exposed * floor_reflectance * solarcal_body_parameter * effective_radiant_field * mrt_delta * mean_radiant_temperature """ _model = 'Horizontal SolarCal' __slots__ = ('_dir_horiz', '_diff_horiz', '_l_mrt', '_erf', '_dmrt', '_dir_horiz_coll', '_diff_horiz_coll', '_l_mrt_coll', '_erf_coll', '_dmrt_coll') def __init__(self, location, direct_horizontal_solar, diffuse_horizontal_solar, longwave_mrt, fraction_body_exposed=None, floor_reflectance=None, solarcal_body_parameter=None): """Initialize Horizontal SolarCal object. """ # set up the object using radiation as a base self._radiation_check(direct_horizontal_solar, 'direct_horizontal_solar') self._radiation_check(diffuse_horizontal_solar, 'diffuse_horizontal_solar') self._input_collections = [direct_horizontal_solar, diffuse_horizontal_solar] self._calc_length = len(direct_horizontal_solar) self._base_collection = direct_horizontal_solar # check required inputs _SolarCalBase.__init__(self, location, fraction_body_exposed, floor_reflectance, solarcal_body_parameter) self._dir_horiz = direct_horizontal_solar.values self._diff_horiz = diffuse_horizontal_solar.values self._l_mrt = self._check_input(longwave_mrt, Temperature, 'C', 'longwave_mrt') # check that all input data collections are aligned. HourlyDiscontinuousCollection.are_collections_aligned(self._input_collections) # compute SolarCal self._calculate_solarcal() def _calculate_solarcal(self): """Compute SolarCal for each step of the Data Collection.""" # empty lists to be filled self._erf = [] # get altitudes and sharps from solar position _altitudes, _sharps = self._get_altitudes_and_sharps() # calculate final erfs and mrt deltas for l_mrt, diff, dir, alt, sharp, fract_e, flr_ref, in \ zip(self._l_mrt, self._diff_horiz, self._dir_horiz, _altitudes, _sharps, self._fract_exp, self._flr_ref): result = shortwave_from_horiz_solar(l_mrt, diff, dir, alt, fract_e, flr_ref, self._body_par.posture, sharp, self._body_par.body_absorptivity, self._body_par.body_emissivity) self._erf.append(result['erf']) self._dmrt.append(result['dmrt']) self._mrt.append(result['mrt']) @property def diffuse_horizontal_solar(self): """Data Collection of diffuse horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_diff_horiz_coll', self._diff_horiz, DiffuseHorizontalIrradiance, 'W/m2') @property def direct_horizontal_solar(self): """Data Collection of direct horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_dir_horiz_coll', self._dir_horiz, DirectHorizontalIrradiance, 'W/m2') @property def longwave_mrt(self): """Data Collection of surface temperature values in degrees C.""" return self._get_coll('_l_mrt_coll', self._l_mrt, MeanRadiantTemperature, 'C') @property def effective_radiant_field(self): """Data Collection of shortwave effective radiant field in W/m2.""" return self._get_coll('_erf_coll', self._erf, EffectiveRadiantField, 'W/m2') @property def mrt_delta(self): """Data Collection of shortwave MRT delta in C.""" return self._get_coll('_dmrt_coll', self._dmrt, RadiantTemperatureDelta, 'dC')
[docs]class HorizontalRefSolarCal(_SolarCalBase): """SolarCal Collection object from all horizontal components (including reflection). This is particularly useful when trying to estimate solar MRT deltas from Radiance radiation simulation result. Args: location: A Ladybug Location object. direct_horizontal_solar: Hourly Data Collection with the direct horizontal solar irradiance in W/m2. diffuse_horizontal_solar: Hourly Data Collection with the diffuse horizontal solar irradiance in W/m2. reflected_horizontal_solar: Hourly Data Collection with the ground-reflected horizontal solar irradiance in W/m2. longwave_mrt: Hourly Data Collection or individual value with the longwave mean radiant temperature (MRT) expereinced as a result of indoor surface temperatures in C. fraction_body_exposed: A Data Collection or number between 0 and 1 representing the fraction of the body exposed to direct sunlight. Note that this does not include the body’s self-shading; only the shading from surroundings. Default is 1 for a person standing in an open area. solarcal_body_parameter: Optional SolarCalParameter object to account for properties of the human geometry. Properties: * location * direct_horizontal_solar * diffuse_horizontal_solar * reflected_horizontal_solar * longwave_mrt * fraction_body_exposed * solarcal_body_parameter * effective_radiant_field * mrt_delta * mean_radiant_temperature """ _model = 'Horizontal Reflected SolarCal' __slots__ = ('_dir_horiz', '_diff_horiz', '_ref_horiz', '_l_mrt', '_erf', '_dmrt', '_dir_horiz_coll', '_diff_horiz_coll', '_ref_horiz_coll', '_l_mrt_coll', '_erf_coll', '_dmrt_coll') def __init__(self, location, direct_horizontal_solar, diffuse_horizontal_solar, reflected_horizontal_solar, longwave_mrt, fraction_body_exposed=None, solarcal_body_parameter=None): """Initialize Horizontal SolarCal object. """ # set up the object using radiation as a base self._radiation_check(direct_horizontal_solar, 'direct_horizontal_solar') self._radiation_check(diffuse_horizontal_solar, 'diffuse_horizontal_solar') self._radiation_check(reflected_horizontal_solar, 'reflected_horizontal_solar') self._input_collections = [direct_horizontal_solar, diffuse_horizontal_solar, reflected_horizontal_solar] self._calc_length = len(direct_horizontal_solar) self._base_collection = direct_horizontal_solar # check required inputs _SolarCalBase.__init__(self, location, fraction_body_exposed, None, solarcal_body_parameter) self._dir_horiz = direct_horizontal_solar.values self._diff_horiz = diffuse_horizontal_solar.values self._ref_horiz = reflected_horizontal_solar.values self._l_mrt = self._check_input(longwave_mrt, Temperature, 'C', 'longwave_mrt') # check that all input data collections are aligned. HourlyDiscontinuousCollection.are_collections_aligned(self._input_collections) # compute SolarCal self._calculate_solarcal() def _calculate_solarcal(self): """Compute SolarCal for each step of the Data Collection.""" # empty lists to be filled self._erf = [] # get altitudes and sharps from solar position _altitudes, _sharps = self._get_altitudes_and_sharps() # calculate final erfs and mrt deltas for l_mrt, diff, dir, ref, alt, sharp, fract_e, in \ zip(self._l_mrt, self._diff_horiz, self._dir_horiz, self._ref_horiz, _altitudes, _sharps, self._fract_exp): result = shortwave_from_horiz_components( l_mrt, diff, dir, ref, alt, fract_e, self._body_par.posture, sharp, self._body_par.body_absorptivity, self._body_par.body_emissivity) self._erf.append(result['erf']) self._dmrt.append(result['dmrt']) self._mrt.append(result['mrt']) @property def diffuse_horizontal_solar(self): """Data Collection of diffuse horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_diff_horiz_coll', self._diff_horiz, DiffuseHorizontalIrradiance, 'W/m2') @property def direct_horizontal_solar(self): """Data Collection of direct horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_dir_horiz_coll', self._dir_horiz, DirectHorizontalIrradiance, 'W/m2') @property def reflected_horizontal_solar(self): """Data Collection of direct horizontal irradiance in Wh/m2 or W/m2.""" return self._get_coll('_ref_horiz_coll', self._ref_horiz, Irradiance, 'W/m2') @property def longwave_mrt(self): """Data Collection of surface temperature values in degrees C.""" return self._get_coll('_l_mrt_coll', self._l_mrt, MeanRadiantTemperature, 'C') @property def effective_radiant_field(self): """Data Collection of shortwave effective radiant field in W/m2.""" return self._get_coll('_erf_coll', self._erf, EffectiveRadiantField, 'W/m2') @property def mrt_delta(self): """Data Collection of shortwave MRT delta in C.""" return self._get_coll('_dmrt_coll', self._dmrt, RadiantTemperatureDelta, 'dC')
class _HorizontalSolarCalMap(HorizontalSolarCal): """Special version of HorizontalSolarCal used in thermal mapping. This class exists purely for performance reasons so that solar positions do not need to be recalculated for every point within a thermal map. """ __slots__ = ('_altitudes', '_sharps') def __init__(self, altitudes, sharps, direct_horizontal_solar, diffuse_horizontal_solar, longwave_mrt, fraction_body_exposed=None, floor_reflectance=None, solarcal_body_parameter=None): self._altitudes = altitudes self._sharps = sharps HorizontalSolarCal.__init__( self, None, direct_horizontal_solar, diffuse_horizontal_solar, longwave_mrt, fraction_body_exposed, floor_reflectance, solarcal_body_parameter) def _location_check(self, location): self._location = None def _get_altitudes_and_sharps(self): return self._altitudes, self._sharps class _HorizontalRefSolarCalMap(HorizontalRefSolarCal): """Special version of HorizontalRefSolarCal used in thermal mapping. This class exists purely for performance reasons so that solar positions do not need to be recalculated for every point within a thermal map. """ __slots__ = ('_altitudes', '_sharps') def __init__(self, altitudes, sharps, direct_horizontal_solar, diffuse_horizontal_solar, reflected_horizontal_solar, longwave_mrt, fraction_body_exposed=None, solarcal_body_parameter=None): self._altitudes = altitudes self._sharps = sharps HorizontalRefSolarCal.__init__( self, None, direct_horizontal_solar, diffuse_horizontal_solar, reflected_horizontal_solar, longwave_mrt, fraction_body_exposed, solarcal_body_parameter) def _location_check(self, location): self._location = None def _get_altitudes_and_sharps(self): return self._altitudes, self._sharps