Unable to run Dragonfly with URBANopt through python: Error: No such command 'hb-models-to-osm'

Dear Ladybug Tools Community,

I am trying to figure out the best workflow for an urban building energy modeling project where I am trying to make parametric adjustments as “scenarios” to a set of simulated residential multi-family low-rise apartment buildings. For this example, let’s say I am a weatherization assistance agency looking to explore insulation retrofits for apartment buildings in a specific neighborhood, specifically delineated as a specific census tract. Let’s say I want to look at only apartment buildings between 20,000 and 30,000 square feet that were built before 1980, and let’s say for this specific census tract I have identified 200 of such buildings for my studied census tract. Now, for these buildings, which are being studied for potential retrofits, let’s say there are 5 different insulation materials I am looking at simulating the energy performance of, each of a different insulation R-value. This would mean 200 x 5 = 1,000 EnergyPlus simulations, which is a lot of computational processing for my laptop! My question then is would this be an appropriate use-case for Dragonfly? And more specifically, would I need URBANopt for this or no? Would URBANopt speed of the simulation processing time am I fundamentally misunderstanding the appropriate use for URBANopt? My project does not concern district heating/cooling systems.

I ask about URBANopt, because I have not been able to get it to work.

I tried running this Dragonfly QuickStart example code with URBANOpt, sourced from the dragonfly-energy GitHub page: GitHub - ladybug-tools/dragonfly-energy: 🐉 Dragonfly extension for energy simulation · GitHub

from dragonfly.model import Model
from dragonfly.building import Building
from dragonfly.story import Story
from dragonfly.room2d import Room2D
from dragonfly.windowparameter import SimpleWindowRatio
from honeybee_energy.lib.programtypes import office_program

# create the Building object
pts_1 = (Point3D(0, 0, 3), Point3D(0, 10, 3), Point3D(10, 10, 3), Point3D(10, 0, 3))
pts_2 = (Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(20, 10, 3), Point3D(20, 0, 3))
pts_3 = (Point3D(0, 10, 3), Point3D(0, 20, 3), Point3D(10, 20, 3), Point3D(10, 10, 3))
pts_4 = (Point3D(10, 10, 3), Point3D(10, 20, 3), Point3D(20, 20, 3), Point3D(20, 10, 3))
room2d_1 = Room2D('Office1', Face3D(pts_1), 3)
room2d_2 = Room2D('Office2', Face3D(pts_2), 3)
room2d_3 = Room2D('Office3', Face3D(pts_3), 3)
room2d_4 = Room2D('Office4', Face3D(pts_4), 3)
story = Story('OfficeFloor', [room2d_1, room2d_2, room2d_3, room2d_4])
story.solve_room_2d_adjacency(0.01)
story.set_outdoor_window_parameters(SimpleWindowRatio(0.4))
story.multiplier = 4
building = Building('OfficeBuilding', [story])

# assign energy properties
for room in story.room_2ds:
    room.properties.energy.program_type = office_program
    room.properties.energy.add_default_ideal_air()

# create the Model object
model = Model('NewDevelopment', [building])

# create the dragonfly Model object
model = Model('NewDevelopment', [building])

# serialize the dragonfly Model to Honeybee Models and convert them to IDF
hb_models = model.to_honeybee('Building', use_multiplier=False, tolerance=0.01)
idfs = [hb_model.to.idf(hb_model) for hb_model in hb_models]

from ladybug.location import Location

# create the dragonfly Model object
model = Model('NewDevelopment', [building])

# create a location for the geoJSON and write it to a folder
location = Location('Boston', 'MA', 'USA', 42.366151, -71.019357)
sim_folder = './tests/urbanopt_model'
geojson, hb_model_jsons, hb_models = model.to.urbanopt(model, location, folder=sim_folder)

# ============================================================
# ATTEMPT TO SIMULATE THE EXPORTED MODEL WITH URBANOPT
# ============================================================

from dragonfly_energy.run import (
    base_honeybee_osw,
    prepare_urbanopt_folder,
    run_urbanopt
)

# Create the Honeybee/OpenStudio workflow used by URBANopt.
workflow_osw = base_honeybee_osw(
    project_directory=sim_folder,
    epw_file=epw_file,
    skip_report=True
)

print("Workflow OSW:", workflow_osw)

# Create the URBANopt scenario CSV and runner configuration.
scenario_csv = prepare_urbanopt_folder(
    feature_geojson=geojson,
    cpu_count=1,
    verbose=True
)

print("Scenario CSV:", scenario_csv)

# Run URBANopt.
results = run_urbanopt(
    feature_geojson=geojson,
    scenario_csv=scenario_csv
)

print("URBANopt results:", results)

And I get this error message:

Workflow OSW: C:\Users\MyName\tests\urbanopt_model\mappers\honeybee_workflow.osw
Scenario CSV: ./tests/urbanopt_model\honeybee_scenario.csv
b"Usage: python -m dragonfly_energy translate [OPTIONS] COMMAND [ARGS]...\r\nTry 'python -m dragonfly_energy translate --help' for help.\r\n\r\nError: No such command 'hb-models-to-osm'.\r\n"
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
Cell In[24], line 77
     74 print("Scenario CSV:", scenario_csv)
     76 # Run URBANopt.
---> 77 results = run_urbanopt(
     78     feature_geojson=geojson,
     79     scenario_csv=scenario_csv
     80 )
     82 print("URBANopt results:", results)

File ~\anaconda3\Lib\site-packages\dragonfly_energy\run.py:423, in run_urbanopt(feature_geojson, scenario_csv, cpu_count)
    421     if returncode != 0:
    422         print(stderr)
--> 423         raise Exception('Failed to translate HBJSONs to OSMs.')
    425 # ensure that the URBANopt environment paths are set up correctly
    426 folders.retrieve_urbanopt_env_path()

Exception: Failed to translate HBJSONs to OSMs.

This tells me that while Dragonfly is able to render the models themselves, the actual energy simulation is not happening because the Honeybee JSON models cannot be translated to OSM? I am confused on how to properly fix this issue. Though the reason for this post largely comes down to asking do I really even need URBANopt to begin with for my project, or can I just rely on Dragonfly + Honeybee? I am using the Dragonfly in pure python just because I still struggle with Grasshopper and I personally prefer the workflow of using python scripts!

Thanks!