Skip to content

Commit

Permalink
fix(simulate): Enable Measure Component to Accept List Inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Aug 31, 2023
1 parent 9d87d49 commit ddd8e08
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 4 deletions.
Binary file modified honeybee_grasshopper_energy/icon/HB Load Measure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions honeybee_grasshopper_energy/json/HB_Load_Measure.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.6.0",
"version": "1.6.1",
"nickname": "LoadMeasure",
"outputs": [
[
Expand All @@ -22,7 +22,7 @@
}
],
"subcategory": "5 :: Simulate",
"code": "\ntry:\n from honeybee_energy.measure import Measure\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport {{Plugin}}.Kernel as gh\n\n\ndef add_component_input_from_arg(argument):\n \"\"\"Add an input parameter to this component using a MeasureArgument object.\n\n Args:\n argument: A honeybee-energy MeasureArgument object that will be used\n to create a new input parameter for the component.\n \"\"\"\n # create the input parameter object\n param = gh.Parameters.Param_ScriptVariable()\n\n # assign the required properties to the input\n arg_id = '_{}'.format(argument.identifier) if argument.required else \\\n '{}_'.format(argument.identifier)\n param.NickName = arg_id\n param.Name = arg_id if argument.display_name is None else argument.display_name\n param.AllowTreeAccess = False # Measures don't support lists\n param.Access = gh.{{PLGN}}_ParamAccess.item # Measures don't support lists\n param.Optional = True # always needed so that default can come from measure file\n\n # assign the optional properties to the input if they exist\n if argument.type_text == 'Choice':\n descr = [argument.description] if argument.description else []\n if None not in argument.valid_choices:\n descr.append('Choose from the following options:')\n descr = descr + list(argument.valid_choices)\n param.Description = '\\n '.join(descr)\n elif argument.description:\n param.Description = argument.description\n if argument.default_value is not None:\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, argument.default_value)\n elif argument.type_text == 'Choice' and argument.valid_choices == (None,):\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, 'None')\n\n # add the parameter to the compoent\n index = ghenv.Component.Params.Input.Count\n ghenv.Component.Params.RegisterInputParam(param, index)\n ghenv.Component.Params.OnParametersChanged()\n\ndef transform_name_and_description(measure):\n \"\"\"Transform this component's name and description to match a measure.\n\n Args:\n measure: A honeybee-energy Measure object that will be used to assign\n this component's name and description.\n \"\"\"\n # assign the measure metadata\n ghenv.Component.NickName = measure.identifier\n ghenv.Component.Name = measure.display_name if measure.display_name \\\n else measure.identifier\n if measure.description:\n ghenv.Component.Description = measure.description\n\n\ndef transform_component(measure):\n \"\"\"Transform this component to have a name and arguments that match a measure.\n\n Args:\n measure: A honeybee-energy Measure object that will be used to assign\n this component's name, description, and input arguments.\n \"\"\"\n # assign the measure metadata\n transform_name_and_description(measure)\n # assign the input arguments\n for arg in measure.arguments:\n add_component_input_from_arg(arg)\n\n\ndef check_arguments_and_set_defaults(measure):\n \"\"\"Check to be sure the names of component inputs align with measure arguments.\n\n This method will also assign any default values from the measure if there is\n no value input to the component.\n\n Args:\n measure: A honeybee-energy Measure object that will be used check this\n component's input arguments.\n \"\"\"\n for i in range(1, ghenv.Component.Params.Input.Count):\n # get the param and the measure argument object\n param = ghenv.Component.Params.Input[i]\n arg = measure_init.arguments[i - 1]\n\n # check that the param matches the measure argument\n assert arg.identifier in param.NickName, \\\n \"This component's inputs do not match that of the input measure.\\n\" \\\n \"Grab a fresh 'HB Load Measure' component and reload the measure.\"\n\n # add any default values\n if not param.VolatileDataCount or param.VolatileData[0][0] is None:\n if arg.default_value is not None:\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, arg.default_value)\n elif arg.type_text == 'Choice' and arg.valid_choices == (None,):\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, 'None')\n\n\ndef update_measure_arguments(measure):\n \"\"\"Update the arguments of a measure object based on this component's inputs.\n\n Args:\n measure: A honeybee-energy Measure object to have its arguments updated\n with the inputs to this component.\n \"\"\"\n for i in range(1, ghenv.Component.Params.Input.Count):\n try:\n value = ghenv.Component.Params.Input[i].VolatileData[0][0]\n if value is not None:\n val = str(value) # cast to string to avoid weird {{Plugin}} types\n argument = measure.arguments[i - 1]\n if argument.valid_choices == (None,) and val == 'None':\n pass # choice argument with no valid choices\n else:\n argument.value = val if val != 'False' else False\n except Exception: # there is no input for this value; just ignore it\n pass\n\n\ndef is_measure_input():\n \"\"\"Check if a measure path is input to this component.\n\n This is needed because we don't know if there are default values for all\n required inputs until we load the measure.\n \"\"\"\n if _measure_path is None:\n msg = 'Input parameter _measure_path failed to collect data!'\n print(msg)\n give_warning(ghenv.Component, msg)\n return False\n return True\n\n\nif is_measure_input():\n # load the measure\n measure_init = Measure(_measure_path)\n\n # transform the component or check the inputs and set defaults\n if ghenv.Component.Params.Input.Count == 1: # first time loading the measure\n transform_component(measure_init)\n else: # the component has already been transformed\n transform_name_and_description(measure_init)\n check_arguments_and_set_defaults(measure_init)\n\n # if the measure has all inputs that it needs, output the measure\n if all_required_inputs(ghenv.Component):\n update_measure_arguments(measure_init)\n measure = measure_init\n",
"code": "\ntry:\n from honeybee_energy.measure import Measure\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport {{Plugin}}.Kernel as gh\n\n\ndef add_component_input_from_arg(argument):\n \"\"\"Add an input parameter to this component using a MeasureArgument object.\n\n Args:\n argument: A honeybee-energy MeasureArgument object that will be used\n to create a new input parameter for the component.\n \"\"\"\n # create the input parameter object\n param = gh.Parameters.Param_ScriptVariable()\n\n # assign the required properties to the input\n arg_id = '_{}'.format(argument.identifier) if argument.required else \\\n '{}_'.format(argument.identifier)\n param.NickName = arg_id\n param.Name = arg_id if argument.display_name is None else argument.display_name\n param.AllowTreeAccess = False # Measures don't support lists\n param.Access = gh.{{PLGN}}_ParamAccess.item # Measures don't support lists\n param.Optional = True # always needed so that default can come from measure file\n\n # assign the optional properties to the input if they exist\n if argument.type_text == 'Choice':\n descr = [argument.description] if argument.description else []\n if None not in argument.valid_choices:\n descr.append('Choose from the following options:')\n descr = descr + list(argument.valid_choices)\n param.Description = '\\n '.join(descr)\n elif argument.description:\n param.Description = argument.description\n if argument.default_value is not None:\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, argument.default_value)\n elif argument.type_text == 'Choice' and argument.valid_choices == (None,):\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, 'None')\n\n # add the parameter to the compoent\n index = ghenv.Component.Params.Input.Count\n ghenv.Component.Params.RegisterInputParam(param, index)\n ghenv.Component.Params.OnParametersChanged()\n\ndef transform_name_and_description(measure):\n \"\"\"Transform this component's name and description to match a measure.\n\n Args:\n measure: A honeybee-energy Measure object that will be used to assign\n this component's name and description.\n \"\"\"\n # assign the measure metadata\n ghenv.Component.NickName = measure.identifier\n ghenv.Component.Name = measure.display_name if measure.display_name \\\n else measure.identifier\n if measure.description:\n ghenv.Component.Description = measure.description\n\n\ndef transform_component(measure):\n \"\"\"Transform this component to have a name and arguments that match a measure.\n\n Args:\n measure: A honeybee-energy Measure object that will be used to assign\n this component's name, description, and input arguments.\n \"\"\"\n # assign the measure metadata\n transform_name_and_description(measure)\n # assign the input arguments\n for arg in measure.arguments:\n add_component_input_from_arg(arg)\n\n\ndef check_arguments_and_set_defaults(measure):\n \"\"\"Check to be sure the names of component inputs align with measure arguments.\n\n This method will also assign any default values from the measure if there is\n no value input to the component.\n\n Args:\n measure: A honeybee-energy Measure object that will be used check this\n component's input arguments.\n \"\"\"\n for i in range(1, ghenv.Component.Params.Input.Count):\n # get the param and the measure argument object\n param = ghenv.Component.Params.Input[i]\n arg = measure_init.arguments[i - 1]\n\n # check that the param matches the measure argument\n assert arg.identifier in param.NickName, \\\n \"This component's inputs do not match that of the input measure.\\n\" \\\n \"Grab a fresh 'HB Load Measure' component and reload the measure.\"\n\n # add any default values\n if not param.VolatileDataCount or param.VolatileData[0][0] is None:\n if arg.default_value is not None:\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, arg.default_value)\n elif arg.type_text == 'Choice' and arg.valid_choices == (None,):\n param.AddVolatileData(gh.Data.{{PLGN}}_Path(0), 0, 'None')\n\n\ndef update_measure_arguments(measure):\n \"\"\"Update the arguments of a measure object based on this component's inputs.\n\n Args:\n measure: A honeybee-energy Measure object to have its arguments updated\n with the inputs to this component.\n \"\"\"\n for i in range(1, ghenv.Component.Params.Input.Count):\n try:\n try: # sense if there are multiple inputs\n run_count = ghenv.Component.RunCount\n value = ghenv.Component.Params.Input[i].VolatileData[0][run_count - 1]\n except Exception:\n vdc = ghenv.Component.Params.Input[i].VolatileDataCount\n value = ghenv.Component.Params.Input[i].VolatileData[0][vdc - 1]\n if value is not None:\n val = str(value) # cast to string to avoid weird {{Plugin}} types\n argument = measure.arguments[i - 1]\n if argument.valid_choices == (None,) and val == 'None':\n pass # choice argument with no valid choices\n else:\n argument.value = val if val != 'False' else False\n except Exception: # there is no input for this value; just ignore it\n pass\n\n\ndef is_measure_input():\n \"\"\"Check if a measure path is input to this component.\n\n This is needed because we don't know if there are default values for all\n required inputs until we load the measure.\n \"\"\"\n if _measure_path is None:\n msg = 'Input parameter _measure_path failed to collect data!'\n print(msg)\n give_warning(ghenv.Component, msg)\n return False\n return True\n\n\nif is_measure_input():\n # load the measure\n measure_init = Measure(_measure_path)\n\n # transform the component or check the inputs and set defaults\n if ghenv.Component.Params.Input.Count == 1: # first time loading the measure\n transform_component(measure_init)\n else: # the component has already been transformed\n transform_name_and_description(measure_init)\n check_arguments_and_set_defaults(measure_init)\n\n # if the measure has all inputs that it needs, output the measure\n if all_required_inputs(ghenv.Component):\n update_measure_arguments(measure_init)\n measure = measure_init\n",
"category": "HB-Energy",
"name": "HB Load Measure",
"description": "Load OpenStudio measures into Grasshopper and assign the measure's input arguments.\nThe resulting measure object can be plugged into the \"measures_\" input of the\n\"HB Model To OSM\" component in order to be included in the export to OpenStudio.\n-\nRead more about OpenStudio measures and creating your own here:\nhttp://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/\n-\nYou can also download several measures created by others from here:\nhttps://bcl.nrel.gov/nrel/types/measure\n-"
Expand Down
9 changes: 7 additions & 2 deletions honeybee_grasshopper_energy/src/HB Load Measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

ghenv.Component.Name = 'HB Load Measure'
ghenv.Component.NickName = 'LoadMeasure'
ghenv.Component.Message = '1.6.0'
ghenv.Component.Message = '1.6.1'
ghenv.Component.Category = 'HB-Energy'
ghenv.Component.SubCategory = '5 :: Simulate'
ghenv.Component.AdditionalHelpFromDocStrings = '4'
Expand Down Expand Up @@ -157,7 +157,12 @@ def update_measure_arguments(measure):
"""
for i in range(1, ghenv.Component.Params.Input.Count):
try:
value = ghenv.Component.Params.Input[i].VolatileData[0][0]
try: # sense if there are multiple inputs
run_count = ghenv.Component.RunCount
value = ghenv.Component.Params.Input[i].VolatileData[0][run_count - 1]
except Exception:
vdc = ghenv.Component.Params.Input[i].VolatileDataCount
value = ghenv.Component.Params.Input[i].VolatileData[0][vdc - 1]
if value is not None:
val = str(value) # cast to string to avoid weird Grasshopper types
argument = measure.arguments[i - 1]
Expand Down
Binary file modified honeybee_grasshopper_energy/user_objects/HB Load Measure.ghuser
Binary file not shown.

0 comments on commit ddd8e08

Please sign in to comment.