Source code for honeybee_radiance.lightsource.sky.sunmatrix

"""Generate a point-in-time climate-based sky."""
from __future__ import division
import honeybee.typing as typing
import ladybug.futil as futil
from ladybug.wea import Wea
from ladybug_geometry.geometry2d.pointvector import Vector2D

import os
import math


[docs] class SunMatrix(object): """Annual Climate-based Sun matrix. The output of SkyMatrix is similar to using command Radiance's gendaymtx command with ``-n -D`` options. The options are available in Radiance 5.3 and after that. For more information see gendaymtx documentation. https://www.radiance-online.org/learning/documentation/manual-pages/pdfs/gendaymtx.pdf Args: wea: A Ladybug wea object. north: A number between -360 and 360 for the counterclockwise difference between the North and the positive Y-axis in degrees. 90 is West and 270 is East (Default: 0) Properties: * wea * location * north * is_point_in_time * is_climate_based """ __slots__ = ('_wea', '_north') def __init__(self, wea, north=0): """Create a climate-based sun matrix.""" self.wea = wea self.north = north @property def wea(self): """Get and set wea.""" return self._wea @wea.setter def wea(self, value): assert isinstance(value, Wea), \ 'wea must be from type Wea not {}'.format(type(value)) self._wea = value @property def north(self): """Get and set north direction. A number between -360 and 360 for the counterclockwise difference between the North and the positive Y-axis in degrees. 90 is West and 270 is East. """ return self._north @north.setter def north(self, value): value = typing.float_in_range(value, -360, +360, 'Skymatrix north') self._north = value @property def is_climate_based(self): """Return True if the sky is created based on values from weather data.""" return True @property def is_point_in_time(self): """Return True if the sky is generated for a single point in time.""" return False @property def location(self): """Location information for sky matrix.""" return self.wea.location
[docs] def north_from_vector(self, north_vector): """Automatically set the north property using a Vector2D. Args: north_vector: A ladybug_geometry Vector2D for the north direction """ self._north = math.degrees(north_vector.angle_clockwise(Vector2D(0, 1)))
[docs] @classmethod def from_dict(cls, input_dict): """Create the sky from a dictionary. Args: input_dict: A python dictionary in the following format .. code-block:: python { 'type': 'SunMatrix', 'wea': {}, 'north': 0.0 # optional } """ if 'type' not in input_dict or input_dict['type'] != 'SunMatrix': raise ValueError('Input dict "type" must be "SunMatrix".') if 'north' in input_dict: sky = cls(Wea.from_dict(input_dict['wea']), input_dict['north']) else: sky = cls(input_dict['wea']) return sky
# TODO: add support for additional parameters # TODO: add gendaymtx to radiance-command and use it for validating inputs
[docs] def to_radiance(self, output_type=1, wea_file=None, output_name=None): """Return Radiance command to generate the sky. Note that you need to write the wea to a file (in.wea) before running this command. Alternatively you can use write method which will write the wea data to a file. Args: output_type: An integer between 0 to 1 for output type. * 0 = output in W/m2/sr visible * 1 = output in W/m2/sr solar (default) wea_file: Path to wea file (default: in.wea). output_name: A name for output files (default: suns). """ output_type = typing.int_in_range(output_type, 0, 1, 'SunMatrix output type') wea_file = wea_file or 'in.wea' output_name = output_name or 'suns' if self.north == 0: command = 'gendaymtx -n -D {0}.mtx -M {0}.mod -O{1} {2}'.format( output_name, output_type, wea_file ) else: command = 'gendaymtx -n -D {0}.mtx -M {0}.mod -O{1} -r {3} {2}'.format( output_name, output_type, wea_file, self.north ) return command
[docs] def to_dict(self): """Translate this matrix to a dictionary.""" return { 'type': 'SunMatrix', 'wea': self.wea.to_dict(), 'north': self.north }
[docs] def write_wea(self, folder='.', name=None, hoys=None): """Write wea to a file. Args: folder: Path to target folder (Default: '.'). name: Optional name for the wea file (Default: in.wea) hoys: Optional list of hoys to filter the hours of the wea. If None, this object's wea will be used as-is. Note that you may not want to use this input if this object's wea is not annual since an exception will be raised if a given hoy is not found in the wea. (Default: None). Returns: Path to wea file. """ name = name or 'in.wea' file_path = os.path.join(folder, name) wea_obj = self.wea if hoys is None else self.wea.filter_by_hoys(hoys) return wea_obj.write(file_path=file_path)
[docs] def to_file(self, folder, name=None, hoys=None, mkdir=False): """Write matrix to a Radiance file. This method also writes the wea information to a .wea file. Args: folder: Target folder. name: File name. hoys: Optional list of hoys to filter the hours of the wea. If None, this object's wea will be used as-is. Note that you may not want to use this input if this object's wea is not annual since an exception will be raised if a given hoy is not found in the wea. (Default: None). mkdir: A boolean to note if the directory should be created if doesn't exist (default: False). Returns: Full path to the newly created file. """ name = typing.valid_string(name) if name \ else '%s.rad' % self.__class__.__name__.lower() # write wea file first wea_file = self.write_wea(folder, hoys=hoys) content = self.to_radiance(wea_file=os.path.split(wea_file)[-1]) return futil.write_to_file_by_name(folder, name, '!' + content, mkdir)
def __eq__(self, value): if not isinstance(value, self.__class__) \ or value.wea != self.wea \ or value.north != self.north: return False return True def __ne__(self, value): return not self.__eq__(value) def __repr__(self): """Matrix representation.""" return '%s: %s' % (self.__class__.__name__, self.wea.location.city)