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): Enable Load Objects component to Load POMF files #293

Merged
merged 1 commit into from
Aug 31, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified dragonfly_grasshopper/icon/DF Load Objects.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions dragonfly_grasshopper/json/DF_Load_Objects.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.8.1",
"version": "1.8.2",
"nickname": "LoadObjects",
"outputs": [
[
Expand All @@ -16,7 +16,7 @@
{
"access": "item",
"name": "_df_file",
"description": "A file path to a dragonfly JSON from which objects will be loaded\nback into Grasshopper. The objects in the file must be non-abridged\nin order to be loaded back correctly.",
"description": "A file path to a dragonfly JSON (or DFJSON representing a full dragonfly\nModel) from which objects will be loaded into Grasshopper. This can\nalso be the path to a Pollination Model Format (.POMF) file from which\na dragonfly Model will be loaded. Note that, if the objects in the JSON\nare not a full model, they must be non-abridged in order to be\nloaded correctly.",
"type": "System.Object",
"default": null
},
Expand All @@ -29,7 +29,7 @@
}
],
"subcategory": "2 :: Serialize",
"code": "\nimport io\n\ntry: # import the core dragonfly dependencies\n import dragonfly.dictutil as df_dict_util\n from dragonfly.model import Model\n from dragonfly.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly:\\n\\t{}'.format(e))\n\ntry: # import the dragonfly_energy dependencies\n from dragonfly_energy.opendss.network import ElectricalNetwork, RoadNetwork\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_energy dependencies\n import honeybee_energy.dictutil as energy_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_radiance dependencies\n import honeybee_radiance.dictutil as radiance_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system, tolerance\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport json\n\n\ndef df_energy_dict_to_object(df_energy_dict, raise_exception=True):\n \"\"\"Re-serialize a dictionary of an object within dragonfly_energy.\n\n Args:\n df_energy_dict: A dictionary of a Dragonfly energy object. Note\n that this should be a non-abridged dictionary to be valid.\n raise_exception: Boolean to note whether an exception should be raised\n if the object is not identified as a part of dragonfly_energy.\n\n Returns:\n A Python object derived from the input df_energy_dict.\n \"\"\"\n try: # get the type key from the dictionary\n obj_type = df_energy_dict['type']\n except KeyError:\n raise ValueError('Dragonfly_energy dictionary lacks required \"type\" key.')\n\n if obj_type == 'ElectricalNetwork':\n return ElectricalNetwork.from_dict(df_energy_dict)\n elif obj_type == 'RoadNetwork':\n return RoadNetwork.from_dict(df_energy_dict)\n elif raise_exception:\n raise ValueError(\n '{} is not a recognized dragonfly energy object'.format(obj_type)\n )\n\n\ndef model_units_tolerance_check(model):\n \"\"\"Convert a model to the current {{Cad}} units and check the tolerance.\n\n Args:\n model: A dragonfly Model, which will have its units checked.\n \"\"\"\n # check the model units\n if model.units != units_system():\n print('Imported model units \"{}\" do not match that of the current {{Cad}} '\n 'model units \"{}\"\\nThe model is being automatically converted '\n 'to the {{Cad}} doc units.'.format(model.units, units_system()))\n model.convert_to_units(units_system())\n\n # check that the model tolerance is not too far from the {{Cad}} tolerance\n if model.tolerance / tolerance >= 100:\n msg = 'Imported Model tolerance \"{}\" is significantly coarser than the ' \\\n 'current {{Cad}} model tolerance \"{}\".\\nIt is recommended that the ' \\\n '{{Cad}} document tolerance be changed to be coarser and this ' \\\n 'component is re-reun.'.format(model.tolerance, tolerance)\n print msg\n give_warning(ghenv.Component, msg)\n\n\ndef version_check(data):\n \"\"\"Check the version of the object if it was included in the dictionary.\n\n This is most useful in cases of importing entire Models to make sure\n the Model isn't newer than the currently installed Dragonfly.\n\n Args:\n data: Dictionary of the object, which optionally has the \"version\" key.\n \"\"\"\n if 'version' in data and data['version'] is not None:\n model_ver = tuple(int(d) for d in data['version'].split('.'))\n df_ver = folders.dragonfly_schema_version\n if model_ver > df_ver:\n msg = 'Imported Model schema version \"{}\" is newer than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model may fail to import ' \\\n 'or (worse) some newer features of the Model might not be imported ' \\\n 'without detection.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n give_warning(ghenv.Component, msg)\n elif model_ver != df_ver:\n msg = 'Imported Model schema version \"{}\" is older than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model will be upgraded upon ' \\\n 'import.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n\n\nif all_required_inputs(ghenv.Component) and _load:\n with io.open(_df_file, encoding='utf-8') as inf:\n first_char = inf.read(1)\n second_char = inf.read(1)\n with io.open(_df_file, encoding='utf-8') as inf:\n if second_char == '{':\n inf.read(1)\n data = json.load(inf)\n\n version_check(data) # try to check the version\n try:\n df_objs = df_dict_util.dict_to_object(data, False) # re-serialize as a core object\n if df_objs is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_objs is None:\n df_objs = energy_dict_util.dict_to_object(data, False)\n if df_objs is None: # try to re-serialize it as a radiance object\n df_objs = radiance_dict_util.dict_to_object(data, False)\n elif isinstance(df_objs, Model):\n model_units_tolerance_check(df_objs)\n except ValueError: # no 'type' key; assume that its a group of objects\n df_objs = []\n for df_dict in data.values():\n df_obj = df_dict_util.dict_to_object(df_dict, False) # re-serialize as a core object\n if df_obj is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_obj is None:\n df_obj = energy_dict_util.dict_to_object(df_dict, False)\n if df_obj is None: # try to re-serialize it as a radiance object\n df_obj = radiance_dict_util.dict_to_object(df_dict, False)\n df_objs.append(df_obj)",
"code": "\nimport os\nimport io\nimport zipfile\nimport tempfile\nimport uuid\n\ntry: # import the core dragonfly dependencies\n import dragonfly.dictutil as df_dict_util\n from dragonfly.model import Model\n from dragonfly.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly:\\n\\t{}'.format(e))\n\ntry: # import the dragonfly_energy dependencies\n from dragonfly_energy.opendss.network import ElectricalNetwork, RoadNetwork\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_energy dependencies\n import honeybee_energy.dictutil as energy_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_radiance dependencies\n import honeybee_radiance.dictutil as radiance_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\n from ladybug.futil import unzip_file\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system, tolerance\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport json\n\n\ndef df_energy_dict_to_object(df_energy_dict, raise_exception=True):\n \"\"\"Re-serialize a dictionary of an object within dragonfly_energy.\n\n Args:\n df_energy_dict: A dictionary of a Dragonfly energy object. Note\n that this should be a non-abridged dictionary to be valid.\n raise_exception: Boolean to note whether an exception should be raised\n if the object is not identified as a part of dragonfly_energy.\n\n Returns:\n A Python object derived from the input df_energy_dict.\n \"\"\"\n try: # get the type key from the dictionary\n obj_type = df_energy_dict['type']\n except KeyError:\n raise ValueError('Dragonfly_energy dictionary lacks required \"type\" key.')\n\n if obj_type == 'ElectricalNetwork':\n return ElectricalNetwork.from_dict(df_energy_dict)\n elif obj_type == 'RoadNetwork':\n return RoadNetwork.from_dict(df_energy_dict)\n elif raise_exception:\n raise ValueError(\n '{} is not a recognized dragonfly energy object'.format(obj_type)\n )\n\n\ndef model_units_tolerance_check(model):\n \"\"\"Convert a model to the current {{Cad}} units and check the tolerance.\n\n Args:\n model: A dragonfly Model, which will have its units checked.\n \"\"\"\n # check the model units\n if model.units != units_system():\n print('Imported model units \"{}\" do not match that of the current {{Cad}} '\n 'model units \"{}\"\\nThe model is being automatically converted '\n 'to the {{Cad}} doc units.'.format(model.units, units_system()))\n model.convert_to_units(units_system())\n\n # check that the model tolerance is not too far from the {{Cad}} tolerance\n if model.tolerance / tolerance >= 100:\n msg = 'Imported Model tolerance \"{}\" is significantly coarser than the ' \\\n 'current {{Cad}} model tolerance \"{}\".\\nIt is recommended that the ' \\\n '{{Cad}} document tolerance be changed to be coarser and this ' \\\n 'component is re-reun.'.format(model.tolerance, tolerance)\n print msg\n give_warning(ghenv.Component, msg)\n\n\ndef version_check(data):\n \"\"\"Check the version of the object if it was included in the dictionary.\n\n This is most useful in cases of importing entire Models to make sure\n the Model isn't newer than the currently installed Dragonfly.\n\n Args:\n data: Dictionary of the object, which optionally has the \"version\" key.\n \"\"\"\n if 'version' in data and data['version'] is not None:\n model_ver = tuple(int(d) for d in data['version'].split('.'))\n df_ver = folders.dragonfly_schema_version\n if model_ver > df_ver:\n msg = 'Imported Model schema version \"{}\" is newer than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model may fail to import ' \\\n 'or (worse) some newer features of the Model might not be imported ' \\\n 'without detection.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n give_warning(ghenv.Component, msg)\n elif model_ver != df_ver:\n msg = 'Imported Model schema version \"{}\" is older than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model will be upgraded upon ' \\\n 'import.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n\n\nif all_required_inputs(ghenv.Component) and _load:\n # first, check whether the file is a Pollination Model Format (.POMF) file\n if zipfile.is_zipfile(_df_file):\n folder_name = str(uuid.uuid4())[:6]\n temp_dir = tempfile.gettempdir()\n folder_path = os.path.join(temp_dir, folder_name)\n os.mkdir(folder_path)\n unzip_file(_df_file, folder_path)\n _df_file = os.path.join(folder_path, 'model.json')\n\n # then\n with io.open(_df_file, encoding='utf-8') as inf:\n first_char = inf.read(1)\n second_char = inf.read(1)\n with io.open(_df_file, encoding='utf-8') as inf:\n if second_char == '{':\n inf.read(1)\n data = json.load(inf)\n\n version_check(data) # try to check the version\n try:\n df_objs = df_dict_util.dict_to_object(data, False) # re-serialize as a core object\n if df_objs is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_objs is None:\n df_objs = energy_dict_util.dict_to_object(data, False)\n if df_objs is None: # try to re-serialize it as a radiance object\n df_objs = radiance_dict_util.dict_to_object(data, False)\n elif isinstance(df_objs, Model):\n model_units_tolerance_check(df_objs)\n except ValueError: # no 'type' key; assume that its a group of objects\n df_objs = []\n for df_dict in data.values():\n df_obj = df_dict_util.dict_to_object(df_dict, False) # re-serialize as a core object\n if df_obj is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_obj is None:\n df_obj = energy_dict_util.dict_to_object(df_dict, False)\n if df_obj is None: # try to re-serialize it as a radiance object\n df_obj = radiance_dict_util.dict_to_object(df_dict, False)\n df_objs.append(df_obj)",
"category": "Dragonfly",
"name": "DF Load Objects",
"description": "Load any dragonfly object from a dragonfly JSON file\n-\nThis includes any Model, Building, Story, Room2D, WindowParameter, or ShadingParameter.\n-\nIt also includes any energy Material, Construction, ConstructionSet, Schedule, \nLoad, ProgramType, or Simulation object.\n-"
Expand Down
26 changes: 22 additions & 4 deletions dragonfly_grasshopper/src/DF Load Objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
-

Args:
_df_file: A file path to a dragonfly JSON from which objects will be loaded
back into Grasshopper. The objects in the file must be non-abridged
in order to be loaded back correctly.
_df_file: A file path to a dragonfly JSON (or DFJSON representing a full dragonfly
Model) from which objects will be loaded into Grasshopper. This can
also be the path to a Pollination Model Format (.POMF) file from which
a dragonfly Model will be loaded. Note that, if the objects in the JSON
are not a full model, they must be non-abridged in order to be
loaded correctly.
_load: Set to "True to load the objects from the _df_file.

Returns:
Expand All @@ -30,12 +33,16 @@

ghenv.Component.Name = 'DF Load Objects'
ghenv.Component.NickName = 'LoadObjects'
ghenv.Component.Message = '1.8.1'
ghenv.Component.Message = '1.8.2'
ghenv.Component.Category = 'Dragonfly'
ghenv.Component.SubCategory = '2 :: Serialize'
ghenv.Component.AdditionalHelpFromDocStrings = '2'

import os
import io
import zipfile
import tempfile
import uuid

try: # import the core dragonfly dependencies
import dragonfly.dictutil as df_dict_util
Expand All @@ -60,6 +67,7 @@
raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))

try: # import the core ladybug_rhino dependencies
from ladybug.futil import unzip_file
from ladybug_rhino.grasshopper import all_required_inputs, give_warning
from ladybug_rhino.config import units_system, tolerance
except ImportError as e:
Expand Down Expand Up @@ -145,6 +153,16 @@ def version_check(data):


if all_required_inputs(ghenv.Component) and _load:
# first, check whether the file is a Pollination Model Format (.POMF) file
if zipfile.is_zipfile(_df_file):
folder_name = str(uuid.uuid4())[:6]
temp_dir = tempfile.gettempdir()
folder_path = os.path.join(temp_dir, folder_name)
os.mkdir(folder_path)
unzip_file(_df_file, folder_path)
_df_file = os.path.join(folder_path, 'model.json')

# then
with io.open(_df_file, encoding='utf-8') as inf:
first_char = inf.read(1)
second_char = inf.read(1)
Expand Down
Binary file modified dragonfly_grasshopper/user_objects/DF Load Objects.ghuser
Binary file not shown.