Source code for honeybee_radiance_postprocess.annualdaylight

"""Functions for post-processing annual daylight outputs.

Note: These functions will most likely be moved to a separate package in the near future.
"""
import json
import os
import numpy as np

from ladybug.color import Colorset
from ladybug.datatype.fraction import Fraction
from ladybug.legend import LegendParameters
from honeybee_radiance.postprocess.annual import filter_schedule_by_hours, \
    _process_input_folder

from .metrics import da_array2d, cda_array2d, udi_array2d, \
    udi_lower_array2d, udi_upper_array2d
from .util import filter_array


[docs]def metrics_to_files(ill_file, occ_pattern, output_folder, threshold=300, min_t=100, max_t=3000, grid_name=None, total_hours=None, sun_down_occ_hours=0): """Compute annual metrics for an ill file and write the results to a folder. This function generates 5 different files or daylight autonomy, continuous daylight autonomy, lower than useful daylight illuminance, useful daylight illuminance and higher than useful daylight illuminance. Args: ill_file: Path to an ill file generated by Radiance. The ill file should be tab separated and shot NOT have a header. The results for each sensor point should be available in a row and and each column should be the illuminance value for a sun_up_hour. The number of columns should match the number of sun up hours. occ_pattern: A list of 0 and 1 values for hours of occupancy. output_folder: An output folder where the results will be written to. The folder will be created if not exist. threshold: Threshold illuminance level for daylight autonomy. Default: 300. min_t: Minimum threshold for useful daylight illuminance. Default: 100. max_t: Maximum threshold for useful daylight illuminance. Default: 3000. grid_name: An optional name for grid name which will be used to name the output files. If None the name of the input file will be used. total_hours: An integer for the total number of occupied hours in the occupancy schedule. If None, it will be assumed that all of the occupied hours are sun-up hours and are already accounted for in the the occ_pattern. Returns: Tuple(file.da, file.cda, file.udi, file.udi, file.udi) """ if not os.path.isdir(output_folder): os.makedirs(output_folder) grid_name = grid_name or os.path.split(ill_file)[-1][-4:] da = os.path.join(output_folder, 'da', '%s.da' % grid_name).replace('\\', '/') cda = os.path.join(output_folder, 'cda', '%s.cda' % grid_name).replace('\\', '/') udi = os.path.join(output_folder, 'udi', '%s.udi' % grid_name).replace('\\', '/') udi_lower = \ os.path.join(output_folder, 'udi_lower', '%s.udi' % grid_name).replace('\\', '/') udi_upper = \ os.path.join(output_folder, 'udi_upper', '%s.udi' % grid_name).replace('\\', '/') for file_path in [da, cda, udi, udi_upper, udi_lower]: folder = os.path.dirname(file_path) if not os.path.isdir(folder): os.makedirs(folder) mask = np.array(occ_pattern) results = np.load(ill_file) results_occ = np.apply_along_axis(filter_array, 1, results, mask=mask) dar = da_array2d(results_occ, total_occ=total_hours, threshold=threshold) np.savetxt(da, dar, fmt='%.2f') cdar = cda_array2d(results_occ, total_occ=total_hours, threshold=threshold) np.savetxt(cda, cdar, fmt='%.2f') udir = udi_array2d(results_occ, total_occ=total_hours, min_t=min_t, max_t=max_t) np.savetxt(udi, udir, fmt='%.2f') udi_lowerr = udi_lower_array2d(results_occ, total_occ=total_hours, min_t=min_t, sun_down_occ_hours=sun_down_occ_hours) np.savetxt(udi_lower, udi_lowerr, fmt='%.2f') udi_upperr = udi_upper_array2d(results_occ, total_occ=total_hours, max_t=max_t) np.savetxt(udi_upper, udi_upperr, fmt='%.2f') return da, cda, udi_lower, udi, udi_upper
# TODO - support a list of schedules/schedule folder to match the input grids
[docs]def metrics_to_folder( results_folder, schedule=None, threshold=300, min_t=100, max_t=3000, grids_filter='*', sub_folder='metrics' ): """Compute annual metrics in a folder and write them in a subfolder. This folder is an output folder of annual daylight recipe. Folder should include grids_info.json and sun-up-hours.txt - the script uses the list in grids_info.json to find the result files for each sensor grid. Args: results_folder: Results folder. schedule: An annual schedule for 8760 hours of the year as a list of values. threshold: Threshold illuminance level for daylight autonomy. Default: 300. min_t: Minimum threshold for useful daylight illuminance. Default: 100. max_t: Maximum threshold for useful daylight illuminance. Default: 3000. grids_filter: A pattern to filter the grids. By default all the grids will be processed. sub_folder: An optional relative path for subfolder to copy results files. Default: metrics Returns: str -- Path to results folder. """ grids, sun_up_hours = _process_input_folder(results_folder, grids_filter) occ_pattern, total_occ, sun_down_occ_hours = \ filter_schedule_by_hours(sun_up_hours=sun_up_hours, schedule=schedule) metrics_folder = os.path.join(results_folder, sub_folder) if not os.path.isdir(metrics_folder): os.makedirs(metrics_folder) for grid in grids: ill_file = os.path.join(results_folder, '%s.npy' % grid['full_id']) metrics_to_files( ill_file, occ_pattern, metrics_folder, threshold, min_t, max_t, grid['full_id'], total_occ, sun_down_occ_hours ) # copy info.json to all results folders for folder_name in ['da', 'cda', 'udi_lower', 'udi', 'udi_upper']: grid_info = os.path.join(metrics_folder, folder_name, 'grids_info.json') with open(grid_info, 'w') as outf: json.dump(grids, outf) metric_info_dict = _annual_daylight_vis_metadata() for metric, data in metric_info_dict.items(): file_path = os.path.join(metrics_folder, metric, 'vis_metadata.json') with open(file_path, 'w') as fp: json.dump(data, fp, indent=4) return metrics_folder
def _annual_daylight_vis_metadata(): """Return visualization metadata for annual daylight.""" udi_l_lpar = LegendParameters(min=0, max=100, colors=Colorset.nuanced()) udi_u_lpar = LegendParameters(min=0, max=100, colors=Colorset.glare_study()) udi_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) cda_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) da_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) metric_info_dict = { 'udi_lower': { 'type': 'VisualizationMetaData', 'data_type': Fraction('Useful Daylight Illuminance Lower').to_dict(), 'unit': '%', 'legend_parameters': udi_l_lpar.to_dict() }, 'udi_upper': { 'type': 'VisualizationMetaData', 'data_type': Fraction('Useful Daylight Illuminance Upper').to_dict(), 'unit': '%', 'legend_parameters': udi_u_lpar.to_dict() }, 'udi': { 'type': 'VisualizationMetaData', 'data_type': Fraction('Useful Daylight Illuminance').to_dict(), 'unit': '%', 'legend_parameters': udi_lpar.to_dict() }, 'cda': { 'type': 'VisualizationMetaData', 'data_type': Fraction('Continuous Daylight Autonomy').to_dict(), 'unit': '%', 'legend_parameters': cda_lpar.to_dict() }, 'da': { 'type': 'VisualizationMetaData', 'data_type': Fraction('Daylight Autonomy').to_dict(), 'unit': '%', 'legend_parameters': da_lpar.to_dict() } } return metric_info_dict def _annual_daylight_config(): """Return vtk-config for annual daylight. """ cfg = { "data": [ { "identifier": "Useful Daylight Illuminance Lower", "object_type": "grid", "unit": "Percentage", "path": "udi_lower", "hide": False, "legend_parameters": { "hide_legend": False, "min": 0, "max": 100, "color_set": "nuanced", }, }, { "identifier": "Useful Daylight Illuminance Upper", "object_type": "grid", "unit": "Percentage", "path": "udi_upper", "hide": False, "legend_parameters": { "hide_legend": False, "min": 0, "max": 100, "color_set": "glare_study", "label_parameters": { "color": [34, 247, 10], "size": 0, "bold": True, }, }, }, { "identifier": "Useful Daylight Illuminance", "object_type": "grid", "unit": "Percentage", "path": "udi", "hide": False, "legend_parameters": { "hide_legend": False, "min": 0, "max": 100, "color_set": "annual_comfort", "label_parameters": { "color": [34, 247, 10], "size": 0, "bold": True, }, }, }, { "identifier": "Continuous Daylight Autonomy", "object_type": "grid", "unit": "Percentage", "path": "cda", "hide": False, "legend_parameters": { "hide_legend": False, "min": 0, "max": 100, "color_set": "annual_comfort", "label_parameters": { "color": [34, 247, 10], "size": 0, "bold": True, }, }, }, { "identifier": "Daylight Autonomy", "object_type": "grid", "unit": "Percentage", "path": "da", "hide": False, "legend_parameters": { "hide_legend": False, "min": 0, "max": 100, "color_set": "annual_comfort", "label_parameters": { "color": [34, 247, 10], "size": 0, "bold": True, }, }, }, ] } return cfg