"""Dctimestep command."""
from honeybee_radiance_command.options.dctimestep import DctimestepOptions
from honeybee_radiance_command._command import Command
import honeybee_radiance_command._typing as typing
[docs]
class Dctimestep(Command):
""""Dctimestep command.
This class should ideally be accessed through one of the four classmethods defined
for it. Accessing through class method ensures that the _study_type variable is
appropriately set and all the tests in the validation method are run properly.
Dctimestep computes annual simulation time steps via matrix-multiplication.
Dctimestep has two invocation forms. In the first form, dctimestep is given a
daylight coefficient specification and an optional sky vector or matrix, which
may be read from the standard input if unspecified. The daylight coefficients
are multiplied against these sky values and the results are written to the
standard output. This may be a list of color values or a combined Radiance
image, as explained below. In the second form, dctimestep takes four input
files, forming a matrix expression. The first argument is the View matrix file
that specifies how window output directions are related to some set of measured
values, such as an array of illuminance points or images.
Args:
options: Dctimestep options. It will be set to Radiance default values if
unspecified.
output: Path to the output matrix file. This should not be set if the output
file(s) has already been defined through the -o option in DctimestepOptions.
sky_vector: Path to the input sky_vector file, generated by gendaymtx or genskyvec
that is required for daylight coefficient, direct-daylight-coefficient
three-phase, three-phase-direct and four-phase-direct simulations.
sun_vector: Path to the input sun_vector file, generated by gendaymtx or genskyvec
that is required for daylight coefficient, direct-daylight-coefficient
three-phase, three-phase-direct and four-phase-direct simulations.
day_coef_matrix: Path to the input daylight coefficient matrix file, generated
by rfluxmtx.
sun_coef_matrix: Path to the input sun_coefficient matrix file, generated by
rcontrib or rfluxmtx.
view_matrix: Path to the input view matrix, created by rfluxmtx, for three-phase,
four-phase, three-phase-direct and four-phase-direct simulations.
t_matrix: Path to the input t (transmission matrix) BSDF file in xml format.
daylight_matrix: Path to the input daylight matrix, created by rfluxmtx, for
three-phase, four-phase, three-phase-direct and four-phase-direct +
simulations.
facade_matrix: Path to the input facade matrix, created by rfluxmtx, for
four-phase and four-phase-direct simulations.
Properties:
* options
* output
* sky_vector
* sun_vector
* day_coef_matrix
* sun_coef_matrix
* facade_matrix
* view_matrix
* daylight_matrix
* t_matrix
"""
__slots__ = ('_sky_vector', '_day_coef_matrix', '_view_matrix', '_daylight_matrix',
'_t_matrix', '_sun_vector', '_sun_coef_matrix', '_facade_matrix',
'_study_type')
def __init__(self, options=None, output=None, sky_vector=None, sun_vector=None,
day_coef_matrix=None, sun_coef_matrix=None, view_matrix=None,
t_matrix=None, daylight_matrix=None, facade_matrix=None,
study_type=None):
"""Initialize command"""
Command.__init__(self, output=output)
self.options = options
self.sky_vector = sky_vector
self.sun_vector = sun_vector
self.day_coef_matrix = day_coef_matrix
self.sun_coef_matrix = sun_coef_matrix
self.view_matrix = view_matrix
self.t_matrix = t_matrix
self.daylight_matrix = daylight_matrix
self.facade_matrix = facade_matrix
self._study_type = study_type
[docs]
@classmethod
def daylight_coef_calc(cls, options=None, output=None,
sky_vector=None, day_coef_matrix=None):
"""Return a class instance explicitly for daylight coefficient calcs"""
dc_cls = cls(options=options, output=output, sky_vector=sky_vector,
day_coef_matrix=day_coef_matrix)
dc_cls._study_type = 'daylight_coef'
return dc_cls
[docs]
@classmethod
def direct_sun_calc(cls, options=None, output=None,
sun_vector=None, sun_coef_matrix=None):
"""Return a class instance explicitly for sun coefficient calcs"""
sc_cls = cls(options=options, output=output, sun_vector=sun_vector,
sun_coef_matrix=sun_coef_matrix)
sc_cls._study_type = 'direct_sun'
return sc_cls
[docs]
@classmethod
def three_phase_calc(cls, options=None, output=None,
sky_vector=None, view_matrix=None, t_matrix=None,
daylight_matrix=None):
"""Return a class instance explicitly for three phase calcs"""
tph_cls = cls(options=options, output=output, sky_vector=sky_vector,
view_matrix=view_matrix, t_matrix=t_matrix,
daylight_matrix=daylight_matrix)
tph_cls._study_type = 'three_phase'
return tph_cls
[docs]
@classmethod
def four_phase_calc(cls, options=None, output=None,
sky_vector=None, view_matrix=None, t_matrix=None,
facade_matrix=None, daylight_matrix=None):
"""Return a class instance explicitly for three phase calcs"""
fph_cls = cls(options=options, output=output, sky_vector=sky_vector,
view_matrix=view_matrix, t_matrix=t_matrix,
daylight_matrix=daylight_matrix, facade_matrix=facade_matrix)
fph_cls._study_type = 'four_phase'
return fph_cls
@property
def options(self):
"""dctimestep options."""
return self._options
@options.setter
def options(self, value):
if not value:
value = DctimestepOptions()
if not isinstance(value, DctimestepOptions):
raise ValueError('Expected Dctimestep options not {}'.format(value))
self._options = value
@property
def sky_vector(self):
"""Sky vector file that is meant for daylight coefficient and three phase
simulations. This is typically generated by gendaymtx or genskyvec"""
return self._sky_vector
@sky_vector.setter
def sky_vector(self, value):
self._sky_vector = typing.path_checker(value)
@property
def sun_vector(self):
"""Sun vector file that is meant for direct sun calculations. This is
typically generated by gendaymtx or genskyvec"""
return self._sun_vector
@sun_vector.setter
def sun_vector(self, value):
self._sun_vector = typing.path_checker(value)
@property
def day_coef_matrix(self):
"""Daylight coefficient matrix file"""
return self._day_coef_matrix
@day_coef_matrix.setter
def day_coef_matrix(self, value):
self._day_coef_matrix = typing.path_checker(value)
@property
def sun_coef_matrix(self):
"""Sun matrix file that is meant for direct sun calculations"""
return self._sun_coef_matrix
@sun_coef_matrix.setter
def sun_coef_matrix(self, value):
self._sun_coef_matrix = typing.path_checker(value)
@property
def view_matrix(self):
"""View matrix file used for three phase and four phase simulations. Generated
by rfluxmtx."""
return self._view_matrix
@view_matrix.setter
def view_matrix(self, value):
self._view_matrix = typing.path_checker(value)
@property
def t_matrix(self):
"""Transmission matrix file that is a data-driven BSDF. Typical format is xml"""
return self._t_matrix
@t_matrix.setter
def t_matrix(self, value):
self._t_matrix = typing.path_checker(value, extn_list=('.xml',),
file_descr='BSDF file')
@property
def daylight_matrix(self):
"""Daylight matrix file that is meant for three or four phase simulations."""
return self._daylight_matrix
@daylight_matrix.setter
def daylight_matrix(self, value):
self._daylight_matrix = typing.path_checker(value)
@property
def facade_matrix(self):
"""Facade matrix file that is meant for four phase simulations."""
return self._facade_matrix
@facade_matrix.setter
def facade_matrix(self, value):
self._facade_matrix = typing.path_checker(value)
[docs]
def validate(self):
Command.validate(self)
calc_inputs_dict = {'direct_sun': ('sun_coef_matrix', 'sun_vector'),
'daylight_coef': ('day_coef_matrix', 'sky_vector'),
'three_phase': ('view_matrix', 't_matrix', 'daylight_matrix',
'sky_vector'),
'four_phase': ('view_matrix', 't_matrix', 'facade_matrix',
'daylight_matrix', 'sky_vector')}
# Perform two checks to ensure that:
# Check1: An appropriate study type has been selected/assigned.
# Check2: Ensure that all the inputs are available for the selected calc type.
# What can still go wrong:
# If inputs that are not required for a particular calc type are set,
# they will be ignored.
# Check 1
assert self._study_type in calc_inputs_dict.keys(), \
'A valid study type has not been set. The valid options are: (%s) and the ' \
'appropriate one will be set automatically if this class being accessed ' \
'through a classmethod.' % ','.join(calc_inputs_dict.keys())
# Check 2
inputs_for_calc = calc_inputs_dict[self._study_type]
inputs_not_set = [val for val in inputs_for_calc if not getattr(self, val)]
assert not inputs_not_set, \
'The follwing inputs for the calc ' \
'type "%s" have not been set: %s' % (
self._study_type, ', '.join(inputs_not_set))
if self.options.o and self.output:
raise Exception('The output has been specified using the "output" attribute'
' as well as the "o"(i.e. -o) option. Only one of these '
'options can be specified at a time. ')
[docs]
def to_radiance(self, stdin_input=False):
"""Command in Radiance format."""
self.validate()
command_parts = [self.command, self.options.to_radiance()]
if self._study_type == 'daylight_coef':
command_parts.extend([self.day_coef_matrix, self.sky_vector])
elif self._study_type == 'direct_sun':
command_parts.extend([self.sun_coef_matrix, self.sun_vector])
elif self._study_type == 'three_phase':
command_parts.extend([self.view_matrix, self.t_matrix, self.daylight_matrix,
self.sky_vector])
elif self._study_type == 'four_phase':
command_parts.extend([self.view_matrix, self.t_matrix, self.facade_matrix,
self.daylight_matrix, self.sky_vector])
cmd = ' '.join(command_parts)
if self.pipe_to:
cmd = ' | '.join((cmd, self.pipe_to.to_radiance(stdin_input=True)))
elif self.output:
cmd = ' > '.join((cmd, self.output))
return ' '.join(cmd.split())