As described in previous sections, eppy was built on EplusInterface
Let us open a small idf file to explore the data structure
In [1]:
# you would normaly install eppy by doing
# python setup.py install
# or
# pip install eppy
# or
# easy_install eppy
# if you have not done so, uncomment the following three lines
import sys
# pathnameto_eppy = 'c:/eppy'
pathnameto_eppy = '../../../'
sys.path.append(pathnameto_eppy)
In [2]:
from eppy import modeleditor
from eppy.modeleditor import IDF
iddfile = "../../../eppy/resources/iddfiles/Energy+V7_2_0.idd"
fname1 = "../../../eppy/resources/idffiles/V_7_2/dev1.idf"
IDF.setiddname(iddfile)
idf1 = IDF(fname1)
idf1.printidf()
The original data structure in EPlusInterface was stupidly simple and robust. In fact attributes stupidly simple and robust seem to go together. Eppy evolved in such a way that this data structure is still retained. The rest of eppy is simply syntactic sugar for this data structure.
from: https://www.princeton.edu/~achaney/tmve/wiki100k/docs/Syntactic_sugar.html "Syntactic sugar is a computer science term that refers to syntax within a programming language that is designed to make things easier to read or to express, while alternative ways of expressing them exist. Syntactic sugar"
Let us take a look at this data structure. If we open an idf file with eppy we can explore the original data structure that comes from EPlusInterface.
Note The variable names are not very intuitive at this level. I did not know what I was doing when I wrote this code and now we are stuck with it
There are three varaibles that hold all the data we need. They are:
idf1.model.dtlsidf1.model.dt idf1.idd_info
In [3]:
dtls = idf1.model.dtls # names of all the idf objects
dt = idf1.model.dt # the idf model
idd_info = idf1.idd_info # all the idd data
In [4]:
dtls = idf1.model.dtls # names of all the idf objects
print type(dtls)
In [5]:
# dtls is a list
print dtls[:10] # print the first ten items
In [6]:
print len(dtls) # print the numer of items in the list
Couple of points to note about dtls:
In [7]:
dt = idf1.model.dt # the idf model
print type(dt)
In [9]:
# print 10 of the keys
print dt.keys()[:10]
In [8]:
# dt is a dict
number_of_keys = len(dt.keys())
print number_of_keys
We'll look at dt in further detail later
In [10]:
idd_info = idf1.idd_info # all the idd data
print type(idd_info)
In [11]:
print len(idd_info) # number of items in the list
In [41]:
# print the first three items
idd_info[:3]
Out[41]:
In [40]:
# print the first three items in seperate lines
for i, item in enumerate(idd_info[:3]):
print "%s. %s" % (i, item)
That does not make much sense. Below is the first 3 items from the idd file ::
In [37]:
# the object "VERSION" is the third item in idd_info
# to get to "VERSION" we need to find it's location in the list
# we use "dtls" to do this
location_of_version = dtls.index("version".upper())
print location_of_version
In [42]:
# print idd_info of "VERSION"
idd_info[location_of_version]
Out[42]:
NOTE:
Let us look at a specific object, say MATERIAL:AIRGAP in idf1.model.dt
In [15]:
dt = idf1.model.dt
In [23]:
airgaps = dt['MATERIAL:AIRGAP'.upper()]
print type(airgaps)
In [43]:
airgaps
Out[43]:
A snippet of the idf text file shows this ::
Notice the following things about idf1.model.dt:
What about an Energyplus object that does not exist in the idf file ?
In [30]:
roofs = dt['ROOF']
print roofs
You get an empty list, meaning there are no roof items within roofs
Let us find the idd_info for airgaps
In [44]:
location_of_airgaps = dtls.index("material:airgap".upper())
print location_of_airgaps
In [45]:
idd_airgaps = idd_info[location_of_airgaps]
idd_airgaps
Out[45]:
Compare to text in idd file::
from: https://www.princeton.edu/~achaney/tmve/wiki100k/docs/Syntactic_sugar.html "Syntactic sugar is a computer science term that refers to syntax within a programming language that is designed to make things easier to read or to express, while alternative ways of expressing them exist"
Wikipedia article on syntactic sugar
All the rest of the code in eppy is simply syntactic sugar over the data structure in model.dtls, model.dt and idd_info
Of course, the above statement is a gross exageration, but it gives you a basis for understanding the code that comes later. At the end of the day, any further code is simply a means for changing the data within model.dt. And you need to access the data within model.dtls and idd_info to do so.
Bunch is a great library that subclasses dict. You can see it at:
Let us first take a look at a dict
In [56]:
adict = {'a':1, 'b':2, 'c':3}
adict
Out[56]:
In [57]:
# one would access the values in this dict by:
print adict
print adict['a']
print adict['b']
print adict['c']
Bunch allows us to do this with a lot less typing
In [58]:
from bunch import Bunch
bunchdict = Bunch(adict)
print bunchdict
print bunchdict.a
print bunchdict.b
print bunchdict.c
Let us take a look at variable airgaps from the previous section.
In [59]:
airgaps
Out[59]:
In [60]:
airgap1, airgap2 = airgaps[0], airgaps[1]
In [61]:
airgap1
Out[61]:
We are going to subclass bunch so that we can do the following to airgap1 from the previous section:
to remind you, the text file we are reading looks like this::
It is a little tricky tring to use bunch with airgap, because:
So we do it in the following way:
Note: Some simplifications were made in the explanations above. So take it with a pinch of salt :-)
The code of EpBunch is in eppy/bunch_subclass.py. If you look at the code you will see The subclassing happening in the following manner:
Question: Are you demented ? Why don't you just subclass Bunch -> EpBunch ?
Answer: One can get demented trying to subclass from dict. This is pretty tricky coding and testing-debugging is difficult, since we are overriding built-in functions of dict. When you make mistakes there, the subclassed dict just stops working, or does very strange things. So I built it in a carefull and incremental way, fully testing before subclassing again. Each subclass implements some functionality and the next one implements more.
EpBunch is described in more detail in the next section