diff --git a/pollination/direct_sun_hours/_direct_sunlight_calc.py b/pollination/direct_sun_hours/_direct_sunlight_calc.py deleted file mode 100644 index fc13629..0000000 --- a/pollination/direct_sun_hours/_direct_sunlight_calc.py +++ /dev/null @@ -1,101 +0,0 @@ -from pollination_dsl.dag import Inputs, DAG, task -from dataclasses import dataclass - -from pollination.honeybee_radiance.post_process import ConvertToBinary, SumRow -from pollination.honeybee_radiance.contrib import DaylightContribution -from pollination.path.copy import Copy - - -@dataclass -class DirectSunHoursCalculation(DAG): - - timestep = Inputs.int( - description='Input wea timestep. This value will be used to divide the ' - 'cumulative results to ensure the units of the output are in hours.', default=1, - spec={'type': 'integer', 'minimum': 1, 'maximum': 60} - ) - - sun_modifiers = Inputs.file( - description='A file with sun modifiers.' - ) - - sensor_grid = Inputs.file( - description='Sensor grid file.', - extensions=['pts'] - ) - - octree_file = Inputs.file( - description='A Radiance octree file with suns.', - extensions=['oct'] - ) - - sensor_count = Inputs.int( - description='Number of sensors in the input sensor grid.' - ) - - grid_name = Inputs.str( - description='Sensor grid file name. This is useful to rename the final result ' - 'file to {grid_name}.ill' - ) - - bsdfs = Inputs.folder( - description='Folder containing any BSDF files needed for ray tracing.', - optional=True - ) - - @task(template=DaylightContribution) - def direct_irradiance_calculation( - self, - fixed_radiance_parameters='-aa 0.0 -I -faa -ab 0 -dc 1.0 -dt 0.0 -dj 0.0 -dr 0', - conversion='0.265 0.670 0.065', - sensor_count=sensor_count, - modifiers=sun_modifiers, - sensor_grid=sensor_grid, - grid_name=grid_name, - scene_file=octree_file, - bsdf_folder=bsdfs - ): - return [ - { - 'from': DaylightContribution()._outputs.result_file, - 'to': '{{self.grid_name}}.ill' - } - ] - - @task( - template=ConvertToBinary, needs=[direct_irradiance_calculation] - ) - def convert_to_sun_hours( - self, input_mtx=direct_irradiance_calculation._outputs.result_file, - grid_name=grid_name, minimum=0, include_min='exclude' - ): - return [ - { - 'from': ConvertToBinary()._outputs.output_mtx, - 'to': '{{self.grid_name}}_sun_hours.ill' - } - ] - - @task(template=Copy, needs=[convert_to_sun_hours]) - def copy_sun_hours( - self, grid_name=grid_name, src=convert_to_sun_hours._outputs.output_mtx): - return [ - { - 'from': Copy()._outputs.dst, - 'to': '../direct_sun_hours/{{self.grid_name}}.ill' - } - ] - - @task( - template=SumRow, needs=[convert_to_sun_hours], - ) - def calculate_cumulative_hours( - self, input_mtx=convert_to_sun_hours._outputs.output_mtx, - grid_name=grid_name, divisor=timestep - ): - return [ - { - 'from': SumRow()._outputs.output_mtx, - 'to': '../cumulative/{{self.grid_name}}.res' - } - ] diff --git a/pollination/direct_sun_hours/_postprocess.py b/pollination/direct_sun_hours/_postprocess.py deleted file mode 100644 index aed8c68..0000000 --- a/pollination/direct_sun_hours/_postprocess.py +++ /dev/null @@ -1,105 +0,0 @@ -from pollination_dsl.dag import Inputs, GroupedDAG, task, Outputs -from dataclasses import dataclass -from pollination.honeybee_radiance.grid import MergeFolderData -from pollination.path.copy import CopyFile, CopyFileMultiple - -# input/output alias -from pollination.alias.inputs.wea import wea_input - - -@dataclass -class DirectSunHoursPostprocess(GroupedDAG): - """Post-process for direct sun hours.""" - - # inputs - input_folder = Inputs.folder( - description='Folder with initial results before redistributing the ' - 'results to the original grids.' - ) - - grids_info = Inputs.file( - description='Grids information from the original model.' - ) - - sun_up_hours = Inputs.file( - description='Sun up hours up file.' - ) - - timestep = Inputs.file( - description='Timestep file.' - ) - - wea = Inputs.file( - description='Wea file.', - extensions=['wea'], - alias=wea_input - ) - - @task(template=CopyFile) - def copy_timestep(self, src=timestep): - return [ - { - 'from': CopyFile()._outputs.dst, - 'to': 'results/direct_sun_hours/timestep.txt' - } - ] - - @task(template=CopyFileMultiple) - def copy_sun_up_hours(self, src=sun_up_hours): - return [ - { - 'from': CopyFileMultiple()._outputs.dst_1, - 'to': 'results/direct_sun_hours/sun-up-hours.txt' - }, - { - 'from': CopyFileMultiple()._outputs.dst_2, - 'to': 'results/cumulative/sun-up-hours.txt' - } - ] - - @task(template=CopyFileMultiple) - def copy_grid_info(self, src=grids_info): - return [ - { - 'from': CopyFileMultiple()._outputs.dst_1, - 'to': 'results/direct_sun_hours/grids_info.json' - }, - { - 'from': CopyFileMultiple()._outputs.dst_2, - 'to': 'results/cumulative/grids_info.json' - } - ] - - @task( - template=MergeFolderData, needs=[copy_sun_up_hours, copy_grid_info], - sub_paths={'input_folder': 'direct_sun_hours'} - ) - def restructure_timestep_results( - self, input_folder=input_folder, - extension='ill' - ): - return [ - { - 'from': MergeFolderData()._outputs.output_folder, - 'to': 'results/direct_sun_hours' - } - ] - - @task( - template=MergeFolderData, needs=[copy_sun_up_hours, copy_grid_info], - sub_paths={'input_folder': 'cumulative'} - ) - def restructure_cumulative_results( - self, input_folder=input_folder, - extension='res' - ): - return [ - { - 'from': MergeFolderData()._outputs.output_folder, - 'to': 'results/cumulative' - } - ] - - results = Outputs.folder( - source='results', description='results folder.' - ) diff --git a/pollination/direct_sun_hours/_prepare_folder.py b/pollination/direct_sun_hours/_prepare_folder.py deleted file mode 100644 index 1125f9f..0000000 --- a/pollination/direct_sun_hours/_prepare_folder.py +++ /dev/null @@ -1,196 +0,0 @@ -from pollination_dsl.dag import Inputs, GroupedDAG, task, Outputs -from dataclasses import dataclass -from pollination.ladybug.translate import WeaToConstant -from pollination.honeybee_radiance.sun import CreateSunMatrix, ParseSunUpHours -from pollination.honeybee_radiance.translate import CreateRadianceFolderGrid -from pollination.honeybee_radiance.octree import CreateOctreeWithSky -from pollination.honeybee_radiance.grid import SplitGridFolder -from pollination.path.copy import CopyFile -from pollination.path.write import WriteInt - -# input/output alias -from pollination.alias.inputs.model import hbjson_model_grid_input -from pollination.alias.inputs.wea import wea_input -from pollination.alias.inputs.north import north_input -from pollination.alias.inputs.grid import grid_filter_input, \ - min_sensor_count_input, cpu_count - - -@dataclass -class DirectSunHoursPrepareFolder(GroupedDAG): - """Prepare folder for direct sun hours.""" - - # inputs - timestep = Inputs.int( - description='Input wea timestep. This value will be used to divide the ' - 'cumulative results to ensure the units of the output are in hours.', default=1, - spec={'type': 'integer', 'minimum': 1, 'maximum': 60} - ) - - north = Inputs.float( - default=0, - description='A number for rotation from north.', - spec={'type': 'number', 'minimum': 0, 'maximum': 360}, - alias=north_input - ) - - cpu_count = Inputs.int( - default=50, - description='The maximum number of CPUs for parallel execution. This will be ' - 'used to determine the number of sensors run by each worker.', - spec={'type': 'integer', 'minimum': 1}, - alias=cpu_count - ) - - min_sensor_count = Inputs.int( - description='The minimum number of sensors in each sensor grid after ' - 'redistributing the sensors based on cpu_count. This value takes ' - 'precedence over the cpu_count and can be used to ensure that ' - 'the parallelization does not result in generating unnecessarily small ' - 'sensor grids. The default value is set to 1, which means that the ' - 'cpu_count is always respected.', default=500, - spec={'type': 'integer', 'minimum': 1}, - alias=min_sensor_count_input - ) - - grid_filter = Inputs.str( - description='Text for a grid identifier or a pattern to filter the sensor grids ' - 'of the model that are simulated. For instance, first_floor_* will simulate ' - 'only the sensor grids that have an identifier that starts with ' - 'first_floor_. By default, all grids in the model will be simulated.', - default='*', - alias=grid_filter_input - ) - - model = Inputs.file( - description='A Honeybee model in HBJSON file format.', - extensions=['json', 'hbjson', 'pkl', 'hbpkl', 'zip'], - alias=hbjson_model_grid_input - ) - - wea = Inputs.file( - description='Wea file.', - extensions=['wea'], - alias=wea_input - ) - - @task(template=WeaToConstant) - def convert_wea_to_constant(self, wea=wea): - """Convert a wea to have constant irradiance values.""" - return [ - { - 'from': WeaToConstant()._outputs.constant_wea, - 'to': 'resources/constant.wea' - } - ] - - @task(template=CreateSunMatrix, needs=[convert_wea_to_constant]) - def generate_sunpath( - self, wea=convert_wea_to_constant._outputs.constant_wea, - north=north, output_type=1 - ): - """Create sunpath for sun-up-hours.""" - return [ - { - 'from': CreateSunMatrix()._outputs.sunpath, - 'to': 'resources/sunpath.mtx' - }, - { - 'from': CreateSunMatrix()._outputs.sun_modifiers, - 'to': 'resources/suns.mod' - } - ] - - @task(template=ParseSunUpHours, needs=[generate_sunpath]) - def parse_sun_up_hours(self, sun_modifiers=generate_sunpath._outputs.sun_modifiers): - return [ - { - 'from': ParseSunUpHours()._outputs.sun_up_hours, - 'to': 'resources/sun-up-hours.txt' - } - ] - - @task(template=WriteInt) - def write_timestep(self, src=timestep): - return [ - { - 'from': WriteInt()._outputs.dst, - 'to': 'resources/timestep.txt' - } - ] - - @task(template=CreateRadianceFolderGrid, annotations={'main_task': True}) - def create_rad_folder(self, input_model=model, grid_filter=grid_filter): - """Translate the input model to a radiance folder.""" - return [ - { - 'from': CreateRadianceFolderGrid()._outputs.model_folder, - 'to': 'model' - }, - { - 'from': CreateRadianceFolderGrid()._outputs.bsdf_folder, - 'to': 'model/bsdf' - }, - { - 'from': CreateRadianceFolderGrid()._outputs.sensor_grids_file, - 'to': 'resources/grids_info.json' - } - ] - - @task( - template=CreateOctreeWithSky, needs=[generate_sunpath, create_rad_folder] - ) - def create_octree( - self, model=create_rad_folder._outputs.model_folder, - sky=generate_sunpath._outputs.sunpath - ): - """Create octree from radiance folder and sunpath for direct studies.""" - return [ - { - 'from': CreateOctreeWithSky()._outputs.scene_file, - 'to': 'resources/scene_with_suns.oct' - } - ] - - @task( - template=SplitGridFolder, needs=[create_rad_folder], - sub_paths={'input_folder': 'grid'} - ) - def split_grid_folder( - self, input_folder=create_rad_folder._outputs.model_folder, - cpu_count=cpu_count, cpus_per_grid=1, min_sensor_count=min_sensor_count - ): - """Split sensor grid folder based on the number of CPUs""" - return [ - { - 'from': SplitGridFolder()._outputs.output_folder, - 'to': 'resources/grid' - }, - { - 'from': SplitGridFolder()._outputs.dist_info, - 'to': 'initial_results/direct_sun_hours/_redist_info.json' - } - ] - - @task(template=CopyFile, needs=[split_grid_folder]) - def copy_redist_info(self, src=split_grid_folder._outputs.dist_info): - return [ - { - 'from': CopyFile()._outputs.dst, - 'to': 'initial_results/cumulative/_redist_info.json' - } - ] - - model_folder = Outputs.folder( - source='model', description='input model folder folder.' - ) - - resources = Outputs.folder( - source='resources', description='resources folder.' - ) - - initial_results = Outputs.folder( - source='initial_results', description='initial results folder.' - ) - - sensor_grids = Outputs.list(source='resources/grid/_info.json') diff --git a/pollination/direct_sun_hours/entry.py b/pollination/direct_sun_hours/entry.py index 4919e0a..6b925f9 100644 --- a/pollination/direct_sun_hours/entry.py +++ b/pollination/direct_sun_hours/entry.py @@ -1,18 +1,7 @@ from pollination_dsl.dag import Inputs, DAG, task, Outputs from dataclasses import dataclass -# input/output alias -from pollination.alias.inputs.model import hbjson_model_grid_input -from pollination.alias.inputs.wea import wea_input -from pollination.alias.inputs.north import north_input -from pollination.alias.inputs.grid import grid_filter_input, \ - min_sensor_count_input, cpu_count -from pollination.alias.outputs.daylight import direct_sun_hours_results, \ - cumulative_sun_hour_results - -from ._prepare_folder import DirectSunHoursPrepareFolder -from ._direct_sunlight_calc import DirectSunHoursCalculation -from ._postprocess import DirectSunHoursPostprocess +from pollination.ladybug_radiance.direct_sunhours import DirectSunHours @dataclass @@ -20,138 +9,53 @@ class DirectSunHoursEntryPoint(DAG): """Direct sun hours entry point.""" # inputs - timestep = Inputs.int( - description='Input wea timestep. This value will be used to divide the ' - 'cumulative results to ensure the units of the output are in hours.', default=1, - spec={'type': 'integer', 'minimum': 1, 'maximum': 60} - ) - - north = Inputs.float( - default=0, - description='A number for rotation from north.', - spec={'type': 'number', 'minimum': 0, 'maximum': 360}, - alias=north_input - ) - - cpu_count = Inputs.int( - default=50, - description='The maximum number of CPUs for parallel execution. This will be ' - 'used to determine the number of sensors run by each worker.', - spec={'type': 'integer', 'minimum': 1}, - alias=cpu_count + vectors = Inputs.file( + description='A file that includes sun vectors.' ) - min_sensor_count = Inputs.int( - description='The minimum number of sensors in each sensor grid after ' - 'redistributing the sensors based on cpu_count. This value takes ' - 'precedence over the cpu_count and can be used to ensure that ' - 'the parallelization does not result in generating unnecessarily small ' - 'sensor grids. The default value is set to 1, which means that the ' - 'cpu_count is always respected.', default=500, - spec={'type': 'integer', 'minimum': 1}, - alias=min_sensor_count_input + offset_dist = Inputs.float( + description='Number in model units for the distance to move points from ' + 'the surfaces of the input geometry.', default=0.01, + spec={'type': 'number', 'maximum': 1.0, 'minimum': 0.001} ) - grid_filter = Inputs.str( - description='Text for a grid identifier or a pattern to filter the sensor grids ' - 'of the model that are simulated. For instance, first_floor_* will simulate ' - 'only the sensor grids that have an identifier that starts with ' - 'first_floor_. By default, all grids in the model will be simulated.', - default='*', - alias=grid_filter_input + timestep = Inputs.int( + description='A number for vectors timesteps', default=1, + spec={'type': 'number', 'maximum': 60, 'minimum': 1} ) - model = Inputs.file( - description='A Honeybee model in HBJSON file format.', - extensions=['json', 'hbjson', 'pkl', 'hbpkl', 'zip'], - alias=hbjson_model_grid_input + study_mesh = Inputs.file( + description='Path to a JSON file for input study mesh in Ladybug Geometry ' + 'format.' ) - wea = Inputs.file( - description='Wea file.', - extensions=['wea'], - alias=wea_input + context_mesh = Inputs.file( + description='Path to a JSON file for input context mesh in Ladybug Geometry ' + 'format.', optional=True ) - @task(template=DirectSunHoursPrepareFolder) - def prepare_folder_direct_sun_hours( - self, timestep=timestep, north=north, - cpu_count=cpu_count, min_sensor_count=min_sensor_count, - grid_filter=grid_filter, model=model, wea=wea + @task(template=DirectSunHours) + def run_direct_sun_hours( + self, vectors=vectors, offset_dist=offset_dist, timestep=timestep, + study_mesh=study_mesh, context_mesh=context_mesh ): return [ { - 'from': DirectSunHoursPrepareFolder()._outputs.model_folder, - 'to': 'model' - }, - { - 'from': DirectSunHoursPrepareFolder()._outputs.resources, - 'to': 'resources' + 'from': DirectSunHours()._outputs.direct_sunlight_values, + 'to': 'direct_sun_hours.json' }, { - 'from': DirectSunHoursPrepareFolder()._outputs.initial_results, - 'to': 'initial_results' - }, - { - 'from': DirectSunHoursPrepareFolder()._outputs.sensor_grids - } - ] - - @task( - template=DirectSunHoursCalculation, - needs=[prepare_folder_direct_sun_hours], - loop=prepare_folder_direct_sun_hours._outputs.sensor_grids, - sub_folder='initial_results/{{item.full_id}}', # subfolder for each grid - sub_paths={ - 'octree_file': 'scene_with_suns.oct', - 'sensor_grid': 'grid/{{item.full_id}}.pts', - 'sun_modifiers': 'suns.mod', - 'bsdfs': 'bsdf' - } - ) - def direct_sun_hours_raytracing( - self, - timestep=timestep, - sensor_count='{{item.count}}', - octree_file=prepare_folder_direct_sun_hours._outputs.resources, - grid_name='{{item.full_id}}', - sensor_grid=prepare_folder_direct_sun_hours._outputs.resources, - sun_modifiers=prepare_folder_direct_sun_hours._outputs.resources, - bsdfs=prepare_folder_direct_sun_hours._outputs.model_folder - ): - pass - - @task( - template=DirectSunHoursPostprocess, - needs=[prepare_folder_direct_sun_hours, direct_sun_hours_raytracing], - sub_paths={ - 'grids_info': 'grids_info.json', - 'sun_up_hours': 'sun-up-hours.txt', - 'timestep': 'timestep.txt' - } - ) - def postprocess_direct_sun_hours( - self, input_folder=prepare_folder_direct_sun_hours._outputs.initial_results, - grids_info=prepare_folder_direct_sun_hours._outputs.resources, - sun_up_hours=prepare_folder_direct_sun_hours._outputs.resources, - timestep=prepare_folder_direct_sun_hours._outputs.resources, - wea=wea, - ): - return [ - { - 'from': DirectSunHoursPostprocess()._outputs.results, - 'to': 'results' + 'from': DirectSunHours()._outputs.visualization_set, + 'to': 'visualization/viz.vsf' } ] - direct_sun_hours = Outputs.folder( - source='results/direct_sun_hours', - description='Hourly results for direct sun hours.', - alias=direct_sun_hours_results + direct_sun_hours = Outputs.file( + source='direct_sun_hours.json', + description='Hourly results for direct sun hours.' ) - cumulative_sun_hours = Outputs.folder( - source='results/cumulative', - description='Cumulative direct sun hours for all the input hours.', - alias=cumulative_sun_hour_results + visualization_set = Outputs.file( + source='visualization/viz.vsf', + description='Direct sun hours visualization.', ) diff --git a/requirements.txt b/requirements.txt index e51f193..1c36379 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1 @@ -pollination-honeybee-radiance==0.22.42 -pollination-ladybug>=0.2.3 -pollination-alias==0.11.8 -pollination-path==0.3.2 +pollination-ladybug-radiance==0.2.2