Source code for honeybee_radiance_command.gensky

# coding: utf-8

"""Gensky command."""

from .options.gensky import GenskyOptions
from ._command import Command
from ._typing import tuple_with_length, int_in_range
import honeybee_radiance_command._exception as exceptions


[docs]class Gensky(Command): """Gensky Command. Gensky produces a RADIANCE scene description for the CIE standard sky distribution at the given month, day and time. By default, the time is interpreted as local standard time on a 24-hour clock. The time value may be given either as decimal hours, or using a colon to separate hours and minutes. Args: month: An integer representing the number of the month. Count starts from 01. day: An integer representing the number of the day in a month. Count starts from 01. time: A string representing hour and minute in 24 hours format. Examples of acceptable format are 21.30 and 21:30. time_zone: A three letter text representing the time zone. Following are acceptable time zones with their corresponding hour differences from Greenwhich mean time; YST +9, PST +8, MST +7, CST +6, EST +5, GMT 0, CET -1, EET -2, AST -3, GST -4, IST -5.5, JST -9, NZST -12, YDT +8, PDT +7, MDT +6, CDT +5, EDT +4, BST -1, CEST -2, EEST -3, ADT -4, GDT -5, IDT -6.5, JDT -10, NZDT -13 solar_time: A boolean to use local solar time. If set to True then the time is preceded by '+' sign and local solar time is used instead of local standard time. options: Command options. It will be set to Radiance default values if unspecified. output: File path to the output file (Default: None). Properties * options * month * day * time * time_zone * solar_time * input """ __slots__ = ('_month', '_day', '_time', '_time_zone', '_solar_time', '_input') def __init__(self, month=None, day=None, time=None, time_zone=None, solar_time=False, options=None, output=None): Command.__init__(self, output=output) self.options = options self.month = month self.day = day self.time = time self.time_zone = time_zone self.solar_time = solar_time @property def options(self): """Gensky options.""" return self._options @options.setter def options(self, value): if not value: value = GenskyOptions() if not isinstance(value, GenskyOptions): raise ValueError('Expected GenskyOptions not {}'.format(type(value))) self._options = value @property def month(self): """Month.""" return self._month @month.setter def month(self, value): if not value: self._month = None else: self._month = int_in_range(value, 1, 12) @property def day(self): """Day.""" return self._day @day.setter def day(self, value): if not value: self._day = None else: self._day = int_in_range(value, 1, 31) @property def time(self): """time.""" return self._time @time.setter def time(self, value): if not value: self._time = None elif isinstance(value, float): hour, minute = str(value).split('.') # Validate hour hour = int_in_range(int(hour), 0, 23) # Validate minute if minute in ('25', '5', '75'): minutes = {'25': '15', '5': '30', '75': '45'} self._time = '%s:%s' % (hour, minutes[minute]) else: raise ValueError( 'Decimal values are only allowed for 15 minute increments.' ' Such as 9.25, 9.5, and 9.75 which will become 9:15, 9:30 and' ' 9:45 respectively. You provided %s' % (value) ) elif isinstance(value, str) and ':' in value: hour, minute = value.split(':') # Validate hour hour = int_in_range(int(hour), 0, 23) # Validate minute minute = int_in_range(int(minute), 0, 59) self._time = value else: raise ValueError( '%s is not a valid format. Examples of acceptable formats are' ' a float value of 21.5 or a string value of 21:30' % (value) ) @property def time_zone(self): """time zone.""" return self._time_zone @time_zone.setter def time_zone(self, value): time_zones = [ 'YST', 'PST', 'MST', 'CST', 'EST', 'GMT', 'CET', 'EET', 'AST', 'GST', 'IST', 'JST', 'NZST', 'YDT', 'PDT', 'MDT', 'CDT', 'EDT', 'BST', 'CEST', 'EEST', 'ADT', 'GDT', 'IDT', 'JDT', 'NZDT'] if not value: self._time_zone = None elif value.upper() in time_zones: self._time_zone = value else: raise ValueError( 'Time zone must a three letter string from the following' ' options %s.' % (time_zones) ) @property def solar_time(self): """Whether solar time is requested.""" return self._solar_time @solar_time.setter def solar_time(self, value): if not value: self._solar_time = None elif isinstance(value, bool): self._solar_time = value else: raise ValueError('Solar time only accepts True or False as a value.') @property def input(self): """Input string for gensky.""" if not self.month and not self.day and not self.time: self._input = None return self._input # Only month, day and time provided as arguments elif not (self.time_zone and self.solar_time): self._input = '%s %s %s' % (str(self.month), str(self.day), str(self.time)) return self._input # Time zone is provided elif self.time_zone and not self.solar_time: self._input = '%s %s %s%s' % (str(self.month), str(self.day), str(self.time), self.time_zone) return self._input # Local solar time requested elif self.solar_time and not self.time_zone: self._input = '+%s %s %s' % (str(self.month), str(self.day), str(self.time)) return self._input # Time zone and solar time both requested elif self.time_zone and self.solar_time: self._input = '+%s %s %s%s' % (str(self.month), str(self.day), str(self.time), self.time_zone) return self._input
[docs] @classmethod def from_ang(cls, angles, options=None): """Create a Gensky command using sun altitude and azimuth angles in degrees. The altitude is measured in degrees above the horizon, and the azimuth is measured in degrees west of South. Args: angles: A tuple of altitude and azimuth angles. options: Command options. It will be set to Radiance default values if not provided by user. """ cls_from_ang = cls() if not options: options = cls_from_ang.options options.ang = tuple_with_length(angles, length=2) return cls_from_ang
[docs] def to_radiance(self, stdin_input=False): """Command in Radiance format. Args: stdin_input: A boolean that indicates if the input for this command comes from stdin. This is for instance the case when you pipe the input from another command (default: False). """ # If form_ang is not used, validate arguments if not self.options.ang.is_set: self.validate() # Month, day, and time are set and then -ang option is set elif self.options.ang.is_set and (self.month and self.day and self.time): raise ValueError( 'Gensky command can be used with either month, day, time or with' ' -ang option that uses sun altitude, azimuth. Setting both are' ' not allowed.') command_parts = [self.command] if self.options: command_parts.append(self.options.to_radiance()) cmd = ' '.join(command_parts) # This will happen when from_ang method is used if not stdin_input and not self.input: cmd = '%s' % (cmd) if not stdin_input and self.input: cmd = '%s %s' % (cmd, self.input) if self.output: cmd = '%s > %s' % (cmd, self.output) return ' '.join(cmd.split())
[docs] def validate(self): Command.validate(self) if not self.month: raise exceptions.MissingArgumentError(self.command, 'month') if not self.day: raise exceptions.MissingArgumentError(self.command, 'day') if not self.time: raise exceptions.MissingArgumentError(self.command, 'time')