Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(serialize): Expose an option for only using interior floors #339

Merged
merged 2 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file modified honeybee_grasshopper_core/icon/HB Dump gbXML.png
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_core/json/HB_Dump_Objects.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.7.0",
"version": "1.7.1",
"nickname": "DumpObjects",
"outputs": [
[
Expand Down Expand Up @@ -57,7 +57,7 @@
}
],
"subcategory": "3 :: Serialize",
"code": "\nimport sys\nimport os\nimport json\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.face import Face\n from honeybee.aperture import Aperture\n from honeybee.door import Door\n from honeybee.shade import Shade\n from honeybee.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the core 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\n\ndef geo_object_warning(obj):\n \"\"\"Give a warning that individual geometry objects should be added to a Model.\"\"\"\n msg = 'An individual {} has been connected to the _hb_objs.\\n' \\\n 'The recommended practice is to add this object to a Model and\\n' \\\n 'serialize the Model instead of serializing individual objects.'.format(\n obj.__class__.__name__)\n print(msg)\n give_warning(ghenv.Component, msg)\n\n\nif all_required_inputs(ghenv.Component) and _dump:\n # set the component defaults\n name = _name_ if _name_ is not None else 'unnamed'\n file_name = '{}.json'.format(name) if len(_hb_objs) > 1 or not \\\n isinstance(_hb_objs[0], Model) else '{}.hbjson'.format(name)\n folder = _folder_ if _folder_ is not None else folders.default_simulation_folder\n hb_file = os.path.join(folder, file_name)\n abridged = bool(abridged_)\n\n # check to see if any objects are of the geometry type and give a warning\n geo_types = (Room, Face, Aperture, Door, Shade)\n for obj in _hb_objs:\n if isinstance(obj, geo_types):\n geo_object_warning(obj)\n\n # create the dictionary to be written to a JSON file\n if len(_hb_objs) == 1: # write a single object into a file if the length is 1\n try:\n obj_dict = _hb_objs[0].to_dict(abridged=abridged)\n except TypeError: # no abridged option\n obj_dict = _hb_objs[0].to_dict()\n else: # create a dictionary of the objects that are indexed by name\n obj_dict = {}\n for obj in _hb_objs:\n try:\n obj_dict[obj.identifier] = obj.to_dict(abridged=abridged)\n except TypeError: # no abridged option\n obj_dict[obj.identifier] = obj.to_dict()\n\n # write the dictionary into a file\n if not os.path.isdir(folder):\n os.makedirs(folder)\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(hb_file, 'wb') as fp:\n obj_str = json.dumps(obj_dict, indent=4, ensure_ascii=False)\n fp.write(obj_str.encode('utf-8'))\n else:\n with open(hb_file, 'w', encoding='utf-8') as fp:\n obj_str = json.dump(obj_dict, fp, indent=4, ensure_ascii=False)\n",
"code": "\nimport sys\nimport os\nimport json\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.face import Face\n from honeybee.aperture import Aperture\n from honeybee.door import Door\n from honeybee.shade import Shade\n from honeybee.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the core 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\n\ndef geo_object_warning(obj):\n \"\"\"Give a warning that individual geometry objects should be added to a Model.\"\"\"\n msg = 'An individual {} has been connected to the _hb_objs.\\n' \\\n 'The recommended practice is to add this object to a Model and\\n' \\\n 'serialize the Model instead of serializing individual objects.'.format(\n obj.__class__.__name__)\n print(msg)\n give_warning(ghenv.Component, msg)\n\n\nif all_required_inputs(ghenv.Component) and _dump:\n # set the component defaults\n name = _name_ if _name_ is not None else 'unnamed'\n file_name = '{}.json'.format(name) if len(_hb_objs) > 1 or not \\\n isinstance(_hb_objs[0], Model) else '{}.hbjson'.format(name)\n folder = _folder_ if _folder_ is not None else folders.default_simulation_folder\n hb_file = os.path.join(folder, file_name)\n abridged = bool(abridged_)\n\n # check to see if any objects are of the geometry type and give a warning\n geo_types = (Room, Face, Aperture, Door, Shade)\n for obj in _hb_objs:\n if isinstance(obj, geo_types):\n geo_object_warning(obj)\n\n # create the dictionary to be written to a JSON file\n if len(_hb_objs) == 1: # write a single object into a file if the length is 1\n try:\n obj_dict = _hb_objs[0].to_dict(abridged=abridged)\n except TypeError: # no abridged option\n obj_dict = _hb_objs[0].to_dict()\n else: # create a dictionary of the objects that are indexed by name\n obj_dict = {}\n for obj in _hb_objs:\n try:\n obj_dict[obj.identifier] = obj.to_dict(abridged=abridged)\n except TypeError: # no abridged option\n obj_dict[obj.identifier] = obj.to_dict()\n\n # write the dictionary into a file\n if not os.path.isdir(folder):\n os.makedirs(folder)\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(hb_file, 'wb') as fp:\n obj_str = json.dumps(obj_dict, indent=indent_, ensure_ascii=False)\n fp.write(obj_str.encode('utf-8'))\n else:\n with open(hb_file, 'w', encoding='utf-8') as fp:\n obj_str = json.dump(obj_dict, fp, indent=indent_, ensure_ascii=False)\n",
"category": "Honeybee",
"name": "HB Dump Objects",
"description": "Dump any honeybee object to a JSON file. You can use \"HB Load Objects\" component\nto load the objects from the file back into Grasshopper.\n-\nHoneybee objects include any honeybee energy Material, Construction,\nConstructionSet, Schedule, Load, ProgramType, or Simulation object.\n-"
Expand Down
11 changes: 9 additions & 2 deletions honeybee_grasshopper_core/json/HB_Dump_gbXML.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.7.0",
"version": "1.7.1",
"nickname": "DumpGBXML",
"outputs": [
[
Expand Down Expand Up @@ -34,6 +34,13 @@
"type": "string",
"default": null
},
{
"access": "item",
"name": "x",
"description": "A boolean to note whether all interior horizontal faces should\nbe written with the InteriorFloor type instead of the combination\nof InteriorFloor and Ceiling that happens by default with OpenStudio\ngbXML serialization. (Default: False).",
"type": "bool",
"default": null
},
{
"access": "item",
"name": "triangulate_",
Expand All @@ -57,7 +64,7 @@
}
],
"subcategory": "3 :: Serialize",
"code": "\nimport sys\nimport os\nimport json\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the honeybee_energy dependencies\n from honeybee_energy.result.osw import OSW\n from honeybee_energy.run import to_gbxml_osw, run_osw, add_gbxml_space_boundaries\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_openstudio_version\nexcept ImportError as e:\n raise ImportError('\\nFailed to import lbt_recipes:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\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\n\nif all_required_inputs(ghenv.Component) and _dump:\n # check the presence of openstudio and check that the version is compatible\n check_openstudio_version()\n\n # check the input and set the component defaults\n assert isinstance(_model, Model), \\\n 'Excpected Honeybee Model object. Got {}.'.format(type(_model))\n name = _name_ if _name_ is not None else _model.identifier\n lower_name = name.lower()\n gbxml_file = name if lower_name.endswith('.xml') or lower_name.endswith('.gbxml') \\\n else '{}.xml'.format(name)\n folder = _folder_ if _folder_ is not None else folders.default_simulation_folder\n gbxml = os.path.join(folder, gbxml_file)\n\n # duplicate model to avoid mutating it as we edit it for energy simulation\n _model = _model.duplicate()\n # scale the model if the units are not meters\n _model.convert_to_units('Meters')\n # remove degenerate geometry within native E+ tolerance of 1 cm\n _model.remove_degenerate_geometry(0.01)\n\n # write out the HBJSON and OpenStudio Workflow (OSW) that translates models to gbXML\n out_directory = os.path.join(folders.default_simulation_folder, 'temp_translate')\n if not os.path.isdir(out_directory):\n os.makedirs(out_directory)\n triangulate_ = False if triangulate_ is None else triangulate_\n model_dict = _model.to_dict(included_prop=['energy'], triangulate_sub_faces=triangulate_)\n _model.properties.energy.add_autocal_properties_to_dict(model_dict)\n _model.properties.energy.simplify_window_constructions_in_dict(model_dict)\n hb_file = os.path.join(out_directory, '{}.hbjson'.format(_model.identifier))\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(hb_file, 'wb') as fp:\n obj_str = json.dumps(model_dict, indent=4, ensure_ascii=False)\n fp.write(obj_str.encode('utf-8'))\n else:\n with open(hb_file, 'w', encoding='utf-8') as fp:\n obj_str = json.dump(model_dict, fp, indent=4, ensure_ascii=False)\n osw = to_gbxml_osw(hb_file, gbxml, out_directory)\n\n # run the measure to translate the model JSON to an openstudio measure\n osm, idf = run_osw(osw, silent=True)\n if idf is None:\n log_osw = OSW(os.path.join(out_directory, 'out.osw'))\n raise Exception(\n 'Failed to run OpenStudio CLI:\\n{}'.format('\\n'.join(log_osw.errors)))\n\n # add in the space boundary geometry if the user has requested it\n if full_geo_:\n add_gbxml_space_boundaries(gbxml, _model)\n",
"code": "\nimport sys\nimport os\nimport json\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the honeybee_energy dependencies\n from honeybee_energy.result.osw import OSW\n from honeybee_energy.run import to_gbxml_osw, run_osw, set_gbxml_floor_types, \\\n add_gbxml_space_boundaries\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_openstudio_version\nexcept ImportError as e:\n raise ImportError('\\nFailed to import lbt_recipes:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\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\n\nif all_required_inputs(ghenv.Component) and _dump:\n # check the presence of openstudio and check that the version is compatible\n check_openstudio_version()\n\n # check the input and set the component defaults\n assert isinstance(_model, Model), \\\n 'Excpected Honeybee Model object. Got {}.'.format(type(_model))\n name = _name_ if _name_ is not None else _model.identifier\n lower_name = name.lower()\n gbxml_file = name if lower_name.endswith('.xml') or lower_name.endswith('.gbxml') \\\n else '{}.xml'.format(name)\n folder = _folder_ if _folder_ is not None else folders.default_simulation_folder\n gbxml = os.path.join(folder, gbxml_file)\n\n # duplicate model to avoid mutating it as we edit it for energy simulation\n _model = _model.duplicate()\n # scale the model if the units are not meters\n _model.convert_to_units('Meters')\n # remove degenerate geometry within native E+ tolerance of 1 cm\n _model.remove_degenerate_geometry(0.01)\n\n # write out the HBJSON and OpenStudio Workflow (OSW) that translates models to gbXML\n out_directory = os.path.join(folders.default_simulation_folder, 'temp_translate')\n if not os.path.isdir(out_directory):\n os.makedirs(out_directory)\n triangulate_ = False if triangulate_ is None else triangulate_\n model_dict = _model.to_dict(included_prop=['energy'], triangulate_sub_faces=triangulate_)\n _model.properties.energy.add_autocal_properties_to_dict(model_dict)\n _model.properties.energy.simplify_window_constructions_in_dict(model_dict)\n hb_file = os.path.join(out_directory, '{}.hbjson'.format(_model.identifier))\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(hb_file, 'wb') as fp:\n obj_str = json.dumps(model_dict, indent=4, ensure_ascii=False)\n fp.write(obj_str.encode('utf-8'))\n else:\n with open(hb_file, 'w', encoding='utf-8') as fp:\n obj_str = json.dump(model_dict, fp, indent=4, ensure_ascii=False)\n osw = to_gbxml_osw(hb_file, gbxml, out_directory)\n\n # run the measure to translate the model JSON to an openstudio measure\n osm, idf = run_osw(osw, silent=True)\n if idf is None:\n log_osw = OSW(os.path.join(out_directory, 'out.osw'))\n raise Exception(\n 'Failed to run OpenStudio CLI:\\n{}'.format('\\n'.join(log_osw.errors)))\n\n # add in the space boundary geometry or reset floor types if the user requested it\n if int_floors_:\n set_gbxml_floor_types(gbxml, interior_type='InteriorFloor')\n if full_geo_:\n add_gbxml_space_boundaries(gbxml, _model)\n",
"category": "Honeybee",
"name": "HB Dump gbXML",
"description": "Dump a Honyebee Model to a gbXML file.\n_\nThe gbXML format is a common open standard used to transfer energy model geometry\nand (some) energy simulation properties from one simulation environment to another.\n_\nThe forward translators within the OpenStudio SDK are used to export all Honeybee\nmodel geometry and properties.\n-"
Expand Down
6 changes: 3 additions & 3 deletions honeybee_grasshopper_core/src/HB Dump Objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

ghenv.Component.Name = 'HB Dump Objects'
ghenv.Component.NickName = 'DumpObjects'
ghenv.Component.Message = '1.7.0'
ghenv.Component.Message = '1.7.1'
ghenv.Component.Category = 'Honeybee'
ghenv.Component.SubCategory = '3 :: Serialize'
ghenv.Component.AdditionalHelpFromDocStrings = '2'
Expand Down Expand Up @@ -107,8 +107,8 @@ def geo_object_warning(obj):
os.makedirs(folder)
if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8
with open(hb_file, 'wb') as fp:
obj_str = json.dumps(obj_dict, indent=4, ensure_ascii=False)
obj_str = json.dumps(obj_dict, indent=indent_, ensure_ascii=False)
fp.write(obj_str.encode('utf-8'))
else:
with open(hb_file, 'w', encoding='utf-8') as fp:
obj_str = json.dump(obj_dict, fp, indent=4, ensure_ascii=False)
obj_str = json.dump(obj_dict, fp, indent=indent_, ensure_ascii=False)
13 changes: 10 additions & 3 deletions honeybee_grasshopper_core/src/HB Dump gbXML.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
If unspecified, it will be derived from the model identifier.
_folder_: An optional directory into which the honeybee objects will be
written. The default is set to the default simulation folder.
int_floors_: A boolean to note whether all interior horizontal faces should
be written with the InteriorFloor type instead of the combination
of InteriorFloor and Ceiling that happens by default with OpenStudio
gbXML serialization. (Default: False).
triangulate_: Boolean to note whether sub-faces (including Apertures and Doors)
should be triangulated if they have more than 4 sides (True) or
whether they should be left as they are (False). This triangulation
Expand All @@ -47,7 +51,7 @@

ghenv.Component.Name = 'HB Dump gbXML'
ghenv.Component.NickName = 'DumpGBXML'
ghenv.Component.Message = '1.7.0'
ghenv.Component.Message = '1.7.1'
ghenv.Component.Category = 'Honeybee'
ghenv.Component.SubCategory = '3 :: Serialize'
ghenv.Component.AdditionalHelpFromDocStrings = '4'
Expand All @@ -64,7 +68,8 @@

try: # import the honeybee_energy dependencies
from honeybee_energy.result.osw import OSW
from honeybee_energy.run import to_gbxml_osw, run_osw, add_gbxml_space_boundaries
from honeybee_energy.run import to_gbxml_osw, run_osw, set_gbxml_floor_types, \
add_gbxml_space_boundaries
except ImportError as e:
raise ImportError('\nFailed to import honeybee_energy:\n\t{}'.format(e))

Expand Down Expand Up @@ -125,6 +130,8 @@
raise Exception(
'Failed to run OpenStudio CLI:\n{}'.format('\n'.join(log_osw.errors)))

# add in the space boundary geometry if the user has requested it
# add in the space boundary geometry or reset floor types if the user requested it
if int_floors_:
set_gbxml_floor_types(gbxml, interior_type='InteriorFloor')
if full_geo_:
add_gbxml_space_boundaries(gbxml, _model)
Binary file modified honeybee_grasshopper_core/user_objects/HB Dump Objects.ghuser
Binary file not shown.
Binary file modified honeybee_grasshopper_core/user_objects/HB Dump gbXML.ghuser
Binary file not shown.