Skip to content

Commit

Permalink
feat(visualize): Add components for Radiation Graphics
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Jan 9, 2023
1 parent 1a9f668 commit 2838be9
Show file tree
Hide file tree
Showing 39 changed files with 1,034 additions and 257 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ladybug_grasshopper/icon/LB Cumulative Sky Matrix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ladybug_grasshopper/icon/LB Radiation Dome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ladybug_grasshopper/icon/LB Radiation Rose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ladybug_grasshopper/icon/LB Sky Dome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ladybug_grasshopper/icon/LB Wind Profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ladybug_grasshopper/icon/LB Wind Rose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 99 additions & 0 deletions ladybug_grasshopper/json/LB_Benefit_Sky_Matrix.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"version": "1.5.0",
"nickname": "BenefitMatrix",
"outputs": [
[
{
"access": "None",
"name": "sky_mtx",
"description": "A sky matrix object containing the radiation benefit/harm coming from each\npatch of the sky. This can be used for a radiation study, a radition rose,\nor a sky dome visualization. It can also be deconstructed into its\nindividual values with the \"LB Deconstruct Matrix\" component.",
"type": null,
"default": null
}
]
],
"inputs": [
{
"access": "item",
"name": "north_",
"description": "A number between -360 and 360 for the counterclockwise\ndifference between the North and the positive Y-axis in degrees.\n90 is West and 270 is East. This can also be Vector for the\ndirection to North. (Default: 0)",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "_location",
"description": "A ladybug Location that has been output from the \"LB Import EPW\"\ncomponent or the \"LB Construct Location\" component.",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "_temperature",
"description": "An annual hourly DataCollection of temperature, which will be used\nto establish whether radiation is desired or not for each time step.",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "_bal_temp_",
"description": "The temperature in Celsius between which radiation switches from being a\nbenefit to a harm. Typical residential buildings have balance temperatures\nas high as 18C and commercial buildings tend to have lower values\naround 12C. (Default 15C).",
"type": "double",
"default": null
},
{
"access": "item",
"name": "_bal_offset_",
"description": "The temperature offset from the balance temperature in Celsius where\nradiation is neither harmful nor helpful. (Default: 2).",
"type": "double",
"default": null
},
{
"access": "item",
"name": "_direct_rad",
"description": "An annual hourly DataCollection of Direct Normal Radiation such\nas that which is output from the \"LB Import EPW\" component or the\n\"LB Import STAT\" component.",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "_diffuse_rad",
"description": "An annual hourly DataCollection of Diffuse Horizontal Radiation\nsuch as that which is output from the \"LB Import EPW\" component or\nthe \"LB Import STAT\" component.",
"type": "System.Object",
"default": null
},
{
"access": "list",
"name": "_hoys_",
"description": "A number or list of numbers between 0 and 8760 that respresent\nthe hour(s) of the year for which to generate the sky matrix. The\n\"LB Calculate HOY\" component can output this number given a month,\nday and hour. The \"LB Analysis Period\" component can output a\nlist of HOYs within a certain hour or date range. By default,\nthe matrix will be for the entire year.",
"type": "double",
"default": null
},
{
"access": "item",
"name": "high_density_",
"description": "A Boolean to indicate whether the higher-density Reinhart sky\nmatrix should be generated (True), which has roughly 4 times the sky\npatches as the (default) original Tregenza sky (False). Note that,\nwhile the Reinhart sky has a higher resolution and is more accurate,\nit will result in considerably longer calculation time for incident\nradiation studies. The difference in sky resolution can be observed\nwith the \"LB Sky Dome\" component. (Default: False).",
"type": "bool",
"default": null
},
{
"access": "item",
"name": "_ground_ref_",
"description": "A number between 0 and 1 to note the average ground reflectance\nthat is associated with the sky matrix. (Default: 0.2).",
"type": "double",
"default": null
},
{
"access": "item",
"name": "_folder_",
"description": "The folder in which the Radiance commands are executed to\nproduce the sky matrix. If None, it will be written to Ladybug's\ndefault EPW folder.",
"type": "string",
"default": null
}
],
"subcategory": "2 :: Visualize Data",
"code": "\nimport math\n\ntry:\n from ladybug_geometry.geometry2d.pointvector import Vector2D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_radiance.skymatrix import SkyMatrix\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.togeometry import to_vector2d\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_radiance_date\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\n# check the istalled Radiance date and get the path to the gemdaymtx executable\ncheck_radiance_date()\n\n\nif all_required_inputs(ghenv.Component):\n # process and set defaults for all of the global inputs\n _bal_temp_ = 15 if _bal_temp_ is None else _bal_temp_\n _bal_offset_ = 2 if _bal_offset_ is None else _bal_offset_\n if north_ is not None: # process the north_\n try:\n north_ = math.degrees(\n to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))\n except AttributeError: # north angle instead of vector\n north_ = float(north_)\n else:\n north_ = 0\n ground_r = 0.2 if _ground_ref_ is None else _ground_ref_\n\n # create the sky matrix object\n sky_mtx = SkyMatrix.from_components_benefit(\n _location, _direct_rad, _diffuse_rad, _temperature, _bal_temp_, _bal_offset_,\n _hoys_, north_, high_density_, ground_r)\n if _folder_:\n sky_mtx.folder = _folder_\n",
"category": "Ladybug",
"name": "LB Benefit Sky Matrix",
"description": "Get a matrix representing the benefit/harm of radiation based on temperature data.\n_\nRadiation benefit matrices are helpful for evaluating building massing and facade\ndesigns in terms of passive solar heat gain vs. cooling energy increase.\n_\nThis component uses Radiance's gendaymtx function to calculate the radiation\nfor each patch of the sky. Gendaymtx is written by Ian Ashdown and Greg Ward.\nMorere information can be found in Radiance manual at:\nhttp://www.radiance-online.org/learning/documentation/manual-pages/pdfs/gendaymtx.pdf\n-"
}
6 changes: 3 additions & 3 deletions ladybug_grasshopper/json/LB_Cumulative_Sky_Matrix.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.5.0",
"version": "1.5.1",
"nickname": "SkyMatrix",
"outputs": [
[
Expand Down Expand Up @@ -51,7 +51,7 @@
{
"access": "item",
"name": "high_density_",
"description": "A Boolean to indicate whether the higher-density Reinhart\nsky matrix should be generated (True), which has roughly 4 times\nthe sky patches as the (default) original Tregenza sky (False).\nNote that, while the Reinhart sky has a higher resolution and is\nmore accurate, it will result in considerably longer calculation\ntime for incident radiation studies. The difference in sky\nresolution can be observed with the (Default: False).",
"description": "A Boolean to indicate whether the higher-density Reinhart sky\nmatrix should be generated (True), which has roughly 4 times the sky\npatches as the (default) original Tregenza sky (False). Note that,\nwhile the Reinhart sky has a higher resolution and is more accurate,\nit will result in considerably longer calculation time for incident\nradiation studies. The difference in sky resolution can be observed\nwith the \"LB Sky Dome\" component. (Default: False).",
"type": "bool",
"default": null
},
Expand All @@ -71,7 +71,7 @@
}
],
"subcategory": "2 :: Visualize Data",
"code": "\nimport os\nimport subprocess\nimport math\n\ntry:\n from ladybug_geometry.geometry2d.pointvector import Vector2D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug.wea import Wea\n from ladybug.viewsphere import view_sphere\n from ladybug.dt import DateTime\n from ladybug.config import folders as lb_folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.togeometry import to_vector2d\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, objectify_output\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\n# TODO: Remove dependency on honeybee + Radiance after genskymtx is in its own LB extension\ntry:\n from honeybee_radiance.config import folders as hb_folders\n from lbt_recipes.version import check_radiance_date\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\n# check the istalled Radiance date and get the path to the gemdaymtx executable\ncheck_radiance_date()\ngendaymtx_exe = os.path.join(hb_folders.radbin_path, 'gendaymtx.exe') if \\\n os.name == 'nt' else os.path.join(hb_folders.radbin_path, 'gendaymtx')\n\n\n# constants for converting RGB values output by gendaymtx to broadband radiation\nPATCHES_PER_ROW = {\n 1: view_sphere.TREGENZA_PATCHES_PER_ROW + (1,),\n 2: view_sphere.REINHART_PATCHES_PER_ROW + (1,)\n}\nPATCH_ROW_COEFF = {\n 1 : view_sphere.TREGENZA_COEFFICIENTS,\n 2: view_sphere.REINHART_COEFFICIENTS\n}\n\n\ndef broadband_radiation(patch_row_str, row_number, wea_duration, sky_density=1):\n \"\"\"Parse a row of gendaymtx RGB patch data in W/sr/m2 to radiation in kWh/m2.\n\n This includes aplying broadband weighting to the RGB bands, multiplication\n by the steradians of each patch, and multiplying by the duration of time that\n they sky matrix represents in hours.\n\n Args:\n patch_row_str: Text string for a single row of RGB patch data.\n row_number: Interger for the row number that the patch corresponds to.\n sky_density: Integer (either 1 or 2) for the density.\n wea_duration: Number for the duration of the Wea in hours. This is used\n to convert between the average value output by the command and the\n cumulative value that is needed for all ladybug analyses.\n \"\"\"\n R, G, B = patch_row_str.split(' ')\n weight_val = 0.265074126 * float(R) + 0.670114631 * float(G) + 0.064811243 * float(B)\n return weight_val * PATCH_ROW_COEFF[sky_density][row_number] * wea_duration / 1000\n\n\ndef parse_mtx_data(data_str, wea_duration, sky_density=1):\n \"\"\"Parse a string of Radiance gendaymtx data to a list of radiation-per-patch.\n\n This function handles the removing of the header and the conversion of the\n RGB irradianc-=per-steraidian values to broadband radiation. It also removes\n the first patch, which is the ground and is not used by Ladybug.\n\n Args:\n data_str: The string that has been output by gendaymtx to stdout.\n wea_duration: Number for the duration of the Wea in hours. This is used\n to convert between the average value output by the command and the\n cumulative value that is needed for all ladybug analyses.\n sky_density: Integer (either 1 or 2) for the density.\n \"\"\"\n # split lines and remove the header, ground patch and last line break\n data_lines = data_str.split('\\n')\n patch_lines = data_lines[9:-1]\n\n # loop through the rows and convert the radiation RGB values\n broadband_irr = []\n patch_counter = 0\n for i, row_patch_count in enumerate(PATCHES_PER_ROW[sky_density]):\n row_slice = patch_lines[patch_counter:patch_counter + row_patch_count]\n irr_vals = (broadband_radiation(row, i, wea_duration, sky_density)\n for row in row_slice)\n broadband_irr.extend(irr_vals)\n patch_counter += row_patch_count\n return broadband_irr\n\n\nif all_required_inputs(ghenv.Component):\n # process and set defaults for all of the global inputs\n if north_ is not None: # process the north_\n try:\n north_ = math.degrees(\n to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))\n except AttributeError: # north angle instead of vector\n north_ = float(north_)\n else:\n north_ = 0\n density = 2 if high_density_ else 1\n ground_r = 0.2 if _ground_ref_ is None else _ground_ref_\n\n # filter the radiation by _hoys if they are input\n if len(_hoys_) != 0:\n _direct_rad = _direct_rad.filter_by_hoys(_hoys_)\n _diffuse_rad = _diffuse_rad.filter_by_hoys(_hoys_)\n\n # create the wea and write it to the default_epw_folder\n wea = Wea(_location, _direct_rad, _diffuse_rad)\n wea_duration = len(wea) / wea.timestep\n wea_folder = _folder_ if _folder_ is not None else \\\n os.path.join(lb_folders.default_epw_folder, 'sky_matrices')\n metd = _direct_rad.header.metadata\n wea_basename = metd['city'].replace(' ', '_') if 'city' in metd else 'unnamed'\n wea_path = os.path.join(wea_folder, wea_basename)\n wea_file = wea.write(wea_path)\n\n # execute the Radiance gendaymtx command\n use_shell = True if os.name == 'nt' else False\n # command for direct patches\n cmds = [gendaymtx_exe, '-m', str(density), '-d', '-O1', '-A', wea_file]\n process = subprocess.Popen(cmds, stdout=subprocess.PIPE, shell=use_shell)\n stdout = process.communicate()\n dir_data_str = stdout[0]\n # command for diffuse patches\n cmds = [gendaymtx_exe, '-m', str(density), '-s', '-O1', '-A', wea_file]\n process = subprocess.Popen(cmds, stdout=subprocess.PIPE, shell=use_shell)\n stdout = process.communicate()\n diff_data_str = stdout[0]\n\n # parse the data into a single matrix\n dir_vals = parse_mtx_data(dir_data_str, wea_duration, density)\n diff_vals = parse_mtx_data(diff_data_str, wea_duration, density)\n\n # collect sky metadata like the north, which will be used by other components\n metadata = [north_, ground_r]\n if _hoys_:\n metadata.extend([DateTime.from_hoy(h) for h in (_hoys_[0], _hoys_[-1])])\n else:\n metadata.extend([wea.analysis_period.st_time, wea.analysis_period.end_time])\n for key, val in _direct_rad.header.metadata.items():\n metadata.append('{} : {}'.format(key, val))\n\n # wrap everything together into an object to output from the component\n mtx_data = (metadata, dir_vals, diff_vals)\n sky_mtx = objectify_output('Cumulative Sky Matrix', mtx_data)\n",
"code": "\nimport math\n\ntry:\n from ladybug_geometry.geometry2d.pointvector import Vector2D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_radiance.skymatrix import SkyMatrix\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.togeometry import to_vector2d\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_radiance_date\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\n# check the istalled Radiance date and get the path to the gemdaymtx executable\ncheck_radiance_date()\n\n\nif all_required_inputs(ghenv.Component):\n # process and set defaults for all of the global inputs\n if north_ is not None: # process the north_\n try:\n north_ = math.degrees(\n to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))\n except AttributeError: # north angle instead of vector\n north_ = float(north_)\n else:\n north_ = 0\n ground_r = 0.2 if _ground_ref_ is None else _ground_ref_\n\n # create the sky matrix object\n sky_mtx = SkyMatrix.from_components(\n _location, _direct_rad, _diffuse_rad, _hoys_, north_, high_density_, ground_r)\n if _folder_:\n sky_mtx.folder = _folder_\n",
"category": "Ladybug",
"name": "LB Cumulative Sky Matrix",
"description": "Get a matrix containing radiation values from each patch of a sky dome.\n_\nCreating this matrix is a necessary pre-step before doing incident radiation\nanalysis with Rhino geometry or generating a radiation rose.\n_\nThis component uses Radiance's gendaymtx function to calculate the radiation\nfor each patch of the sky. Gendaymtx is written by Ian Ashdown and Greg Ward.\nMorere information can be found in Radiance manual at:\nhttp://www.radiance-online.org/learning/documentation/manual-pages/pdfs/gendaymtx.pdf\n-"
Expand Down
Loading

0 comments on commit 2838be9

Please sign in to comment.