A module for parsing EnergyPlus *.eso files

simulation, parsing, energyplus, pandas
pip install esoreader==1.2.3



A python module for reading *.eso files generated by EnergyPlus


The building simulation engine EnergyPlus stores its main output in a file with the ending '.eso'. This format makes it easy to log variable values during simulation, but is hard to use for post-processing. EnergyPlus offers a sqlite version of this data, but using it requires understanding the eso file format itself. EnergyPlus also can output a csv file, but that is limited in the number of columns.

The esoreader module makes it very easy to explore the output of EnergyPlus, say, in an IPython notebook interactive environment.


  • parse *.eso files to pandas DataFrames
  • search for output variables by substring


The easiest way to install esoreader ist to do:

$ pip install esoreader

Using esoreader with Pandas

In [1]: import esoreader

In [2]: eso = esoreader.read_from_path(r"C:\...\experiment01.eso")

In [3]: eso.find_variable('heating')
[('TimeStep', None, 'Heating:EnergyTransfer'),
  'Zone Ideal Loads Zone Total Heating Energy')]

In [4]: df = eso.to_frame('heating energy')

In [5]: df[:10]
0                            8596050.719384
1                            8672511.667988
2                            8737544.119096
3                            8799182.506582
4                            8862116.803218
5                            8928593.537248
6                            5296266.226576
7                                  0.000000
8                                  0.000002
9                                  0.000000

In [6]: df.plot()
Out[6]: <matplotlib.axes._subplots.AxesSubplot at 0x7854090>

In [7]: %matplotlib tk

In [8]: df.plot()
Out[8]: <matplotlib.axes._subplots.AxesSubplot at 0x7b66670>

Zone Ideal Loads Zone Total Heating Energy

Notice in the above example how the variable is matched by substring - you don't have to specify the whole variable name. Each matching variable will show up in the resulting DataFrame with the key used as the column name - in this case 'DEFAULT_ZONEZONEHVAC:IDEALLOADSAIRSYSTEM'.

Also, as this is an IPython session, I used the magic variable incantation %matplotlib tk to switch on the GUI loop that allowes plotting. You can choose another backend if you like, but I am pretty sure that tk should be available with your Python distribution.

An example with multiple columns:

In [1]: eso.find_variable('net thermal radiation heat gain energy')
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy'),
  'Surface Outside Face Net Thermal Radiation Heat Gain Energy')]

In [2]: df = eso.to_frame('net thermal radiation heat gain energy')

In [3]: df.plot()
Out[3]: <matplotlib.axes._subplots.AxesSubplot at 0xbd11150>

Net Thermal Radiation Heat Gain Energy

The key parameter to to_frame

You can use the key parameter to select a single column:

In [1]: df = eso.to_frame('net thermal radiation', key='DPVROOF:1157058.3')

In [2]: df[:10]
0    -8985934.016604
1    -8453530.628023
2    -7611418.498363
3    -6936246.291753
4    -6206109.857522
5    -5879653.262523
6    -5676601.453020
7    -5606988.050900
8    -5844912.195173
9    -4712551.701917

The index parameter to to_frame

You can use the index parameter to specify an index for the DataFrame. Since this is time-series data, a common pattern could be:

In [1]: hours_in_year = pd.date_range('2013-01-01', '2013-12-31 T23:00', freq='H')

In [2]: df = eso.to_frame('heating energy', index=hours_in_year)

In [3]: df[:10]
2013-01-01 00:00:00                            8596050.719384
2013-01-01 01:00:00                            8672511.667988
2013-01-01 02:00:00                            8737544.119096
2013-01-01 03:00:00                            8799182.506582
2013-01-01 04:00:00                            8862116.803218
2013-01-01 05:00:00                            8928593.537248
2013-01-01 06:00:00                            5296266.226576
2013-01-01 07:00:00                                  0.000000
2013-01-01 08:00:00                                  0.000002
2013-01-01 09:00:00                                  0.000000

Using esoreader without pandas

NOTE: This is an older API that requires a better understanding about the eso file structure than using the pandas interface explained above. It is cumbersome but might be of use to users not using pandas. If you come up with a nicer interface, send me a pull request.

The eso files generated by EnergyPlus contains a data dictionary, which describes the values reported by EnergyPlus. The list of values reported depends on the simulation input file, specifically the Output:Variable and Output:Meter objects. EnergyPlus can output the same variable at different frequencies and for different "keys", which are for instance surfaces or equipment names.

Following the data dictionary is a list of output variable values for each of the configured variable coordinates.

The output of the esoreader module is therefore a data dictionary object that contains a mapping of variable "coordinates" (grouping of reporting frequency, key and variable name) to the index used by EnergyPlus and a data object, which essentially just maps that index to the timeseries data.


import esoreader

PATH_TO_ESO = r'/Path/To/EnergyPlus/Output/eplusout.eso'
dd, data =
frequency, key, variable = dd.find_variable('Zone Ventilation Total Heat Loss Energy')[0]
idx = dd.index[frequency, key, variable]
time_series = data[idx]



If you are having issues, please let us know. We have a mailing list located at:

License & Credit

This project is licensed under the terms of the MIT license. See the file "LICENSE" in the project root for more information.

This module was developed by Daren Thomas at the chair for Architecture and Building Systems (A/S) at the Institute of Technology in Architecture, ETH Zürich, Switzerland.