Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

API Python examples of Data Transfer in EnergyPlus

asked 2021-05-04 11:57:36 -0500

cardav's avatar

updated 2021-06-01 09:29:32 -0500

Thank you again for your responses. I am attaching the Python script and the list of actuators for a better understanding.

1) My goal is to override the air properties at the inlet of the AHUs (not the weather file). Thus, from the available API data list of the simulation, I chose all the actuators related to the “Outdoor Air System Node” to perform the override of the Wet bulb temperature, which are (…._OAINLET NODE, …._COOLC COND OA NODE, … _COOLCOA REF NODE) and I used almost all the calling points. However, I could not get any satisfactory overrideC:\fakepath\Actuators.png.

class AverageZoneCalcs(EnergyPlusPlugin):

def __init__(self):
    self.do_setup = True

def on_end_of_zone_timestep_before_zone_reporting(self, state) -> int:
    if self.do_setup:["zone_volumes"] = []["zone_temps"] = []["zone_humidity_ratios"] = []
        zone_names = ["Perimeter_top_ZN_" + str(i) for i in range(1, 5)] + ["Perimeter_mid_ZN_" + str(i) for i in range(1, 5)] + ["Perimeter_bot_ZN_" + str(i) for i in range(1, 5)] + ["Core_bottom", "TopFloor_Plenum", "MidFloor_Plenum", "FirstFloor_Plenum", "Core_mid", "Core_top"]
        for zone_name in zone_names: 
            handle =, "Zone Air Volume", zone_name)
            zone_volume =, handle)
      , "Zone Mean Air Temperature", zone_name)
      , "Zone Mean Air Humidity Ratio", zone_name)
            )["avg_temp_variable"] =, "AverageBuildingTemp")["avg_hum_ratio_variable"] =, "AverageBuildingHR")
        self.do_setup = False
    zone_temps = list()
    zone_humidity_ratios = list()
    for t_handle in["zone_temps"]:
        zone_temps.append(, t_handle))
    for hr_handle in["zone_humidity_ratios"]:
        zone_humidity_ratios.append(, hr_handle))
    numerator_t  = 0.0
    numerator_hr = 0.0
    denominator = 0.0
    for i in range(5):
        numerator_t +=["zone_volumes"][i] * zone_temps[i]
        numerator_hr +=["zone_volumes"][i] * zone_humidity_ratios[i]
        denominator +=["zone_volumes"][i]
    average_temp = numerator_t / denominator
    average_HR = numerator_hr / denominator,["avg_temp_variable"], average_temp),["avg_hum_ratio_variable"], average_HR)
    return 0

class Dehumidifier(EnergyPlusPlugin):

def __init__(self):
    self.need_to_get_handles = True
    self.handles = {}
    self.values = {}
    self.psych = None
    self.OA_DBT_handle = None
    self.OA_WBT_handle = None
    self.Patm_handle = None
    self.WBT_override_handle = None

def get_handles(self, state):
    if self.need_to_get_handles:
        self.handles["OA_DBT"] =
            "Site Outdoor Air Drybulb Temperature",
        self.handles["OA_WBT"] =
            "Site Outdoor Air Wetbulb Temperature",
        self.handles["Patm"] =
            "Site Outdoor Air Barometric Pressure",
        self.handles["PACU_BOT_WBT_override"] =
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 
        self.handles["PACU_MID_WBT_override"] =
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 
        self.handles["PACU_TOP_WBT_override"] =
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 

    self.need_to_get_handles = False

def handles_are_valid(self, state):
    handles_are_valid = True
    for (k, v) in self.handles.items():
        if v == -1:
            handles_are_valid = False
            print(k, v)
            self.api.runtime.issue_severe(state, f"Handle not found for '{k}'")
    return handles_are_valid

def OA_inlet_manager(self, state ...
edit retag flag offensive close merge delete


I was not able to completely follow your code, but I did try to write a simpler program that set the outdoor air conditions on the 5ZoneAirCooled.idf example file that is shipped with E+. It worked for the drybulb temperature, but not the wetbulb. I think there is an E+ bug with setting the wetbulb temperature. I have filed an E+ issue. That may be why you are not seeing any override.

bonnema's avatar bonnema  ( 2021-07-20 13:26:30 -0500 )edit

2 Answers

Sort by » oldest newest most voted

answered 2021-05-05 08:57:36 -0500

updated 2021-05-16 09:44:42 -0500

Can you share you .py file?

1) I think your using the wrong calling point (you're setting a weather variable and then it is being reset from the weather file). Try begin_timestep_before_predictor.

2) This is probably best to show with an example:

In the IDF:

  Python Variables,                       !- Name
  a01_t_supp_f;                           !- Variable Name 1

  a01_t_supp_f,                           !- Name
  a01_t_supp_f,                           !- Python Plugin Variable Name
  Averaged,                               !- Type of Data in Variable
  SystemTimestep,                         !- Update Frequency
  ;                                       !- Units

  a01_t_supp_f,                           !- Key Value
  PythonPlugin:OutputVariable,            !- Variable Name
  Timestep;                               !- Reporting Frequency

In the Python script:

self.a01_t_supp_f_hndl =, "a01_t_supp_f"), self.a01_t_supp_f_hndl, self.a01_t_supp_f)

Read the documentation for PythonPlugin:OutputVariable and Output:Variable for information on update and reporting frequency.

3) This is hard to answer without more detail. I would encourage you to read Section 6 of for information on calling points. The E+ examples files (C:\EnergyPlusV9-5-0\ExampleFiles\PythonPlugin*.idf/.py on Windows) will most likely show an example of what you're looking for.

edit flag offensive delete link more

answered 2021-05-05 11:07:43 -0500

Matt Mitchell's avatar

Hi, thanks for using these new features and the question.

Re 1): my guess is that you are attempting to set the relhum value via the relhum sensor, not the actuator. Take a look at the following which is starting from the 1ZoneUncontrolled.idf file.

self.outdoor_air_relhum_actuator_handle =,
                                                                   "Weather Data",
                                                                   "Outdoor Relative Humidity",
                                                                   "Environment"), self.outdoor_air_relhum_actuator_handle, new_relhum)

A full example is posted here:

Re 2): the example posted at the link demonstrates this, but you will need to use a global variable, then set up a new output variable based on that.

Re 3): what's wrong with class member variables? In the examples shipped with EnergyPlus and linked above, you'll see that we use the "self" class member variables all over the place to persist these data and pass them between calling points. If you want to pass data between class instances, you might need to use global variables (gasp) or be clever with how you set up your classes and calling points.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Training Workshops


Question Tools



Asked: 2021-05-04 11:57:36 -0500

Seen: 952 times

Last updated: Jun 01 '21