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

built in method to merge idfs with eppy?

asked 2021-03-09 11:18:49 -0500

bbrannon4 gravatar image

updated 2021-03-09 15:19:19 -0500

I've got a script that does various things with idf file snippets and ends up with a few distinct idf objects. Does anyone have a suggestion on simple ways to merge/copy/concatenate one into the other? I could always just convert them to text and do it that way, but I was hoping for something more eppy-ish.

I'm aware of the copyidfobjects method, but I'm hoping for something that doesn't require looping through every object.

For reference, I've got a model split into idf file chunks (because they are part of a larger workflow and coming from various places) such as main file with geometry, envelope, hvac, internal gains, outputs, etc. Then I've loaded each of these files individually with eppy and made various modifications (choosing the correct envelope, mapping the hvac system to the relevant zones, etc). So now I'm at the end of the script and have 6 or so objects sitting in memory that I'd like to combine into a single idf file for simulation.

as a simple example:

idf1 = IDF(model_part_1.idf)
idf1 = IDF(model_part_1.idf)

# fancy stuff to alter the above

# I'm hoping for something on the order of
idf_all = idf1.idfconcatenate(idf2)

idf_all.idfname = "model_complete.idf"
idf_all.save()
edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
3

answered 2021-03-12 22:02:14 -0500

santoshphilip gravatar image

updated 2021-03-12 22:44:53 -0500

This code will do the trick

import eppy

# open some files from the example folder
fname1 = "/Applications/EnergyPlus-9-3-0/ExampleFiles/1ZoneEvapCooler.idf"
idf1 = eppy.openidf(fname1) # will search and find the IDD file if it can :-)
fname2 = "/Applications/EnergyPlus-9-3-0/ExampleFiles/1ZoneParameterAspect.idf"
idf2 = eppy.openidf(fname2)  # will search and find the IDD file if it can :-)

# code to merge the idf2 into idf1
for key in idf2.idfobjects:
    for idfobject in idf2.idfobjects[key]:
        idf1.copyidfobject(idfobject)

idf1.saveas('a.idf') # maybe ....

I just noticed that your question says that you do not want to loop thru using copyidfobject(). I can't think of any way of doing the merge without looping through. There is no merge function in eppy. That looping thru is your merge function. I guess eppy is not as eppy-sh as it should be.

# if you have 5 or 6 idfs
# idfs = [idf1, idf2m idf3, idf4, idf5, idf6]

from eppy.modeleditor import IDF
idftxt = "" # empty string
from io import StringIO
fhandle = StringIO(idftxt) # we can make a file handle of a string
idf_merged = IDF(fhandle) # initialize the IDF object with the file handle

for idf in idfs:
    for key in idf.idfobjects:
        for idfobject in idf.idfobjects[key]:
            idf_merged.copyidfobject(idfobject)

idf_merged.saveas('merged.idf')   # save() won't work, since you don't have a file name
edit flag offensive delete link more

Comments

Thanks for confirming that what I'm looking for isn't exactly doable, but this makes sense as the bast way to do it while staying within the eppy universe. Maybe I'll try converting that to a list comprehension to test the speed, but for now I think the idfstr() method and a regular text concat seems to be the most efficient.

bbrannon4 gravatar image bbrannon4  ( 2021-03-13 21:57:43 -0500 )edit

You make a good case to include such functionality in eppy. I have opened an issue https://github.com/santoshphilip/eppy... in the issue-tracker. Please comment there to help shape the API and it's implementation

santoshphilip gravatar image santoshphilip  ( 2021-03-14 18:04:14 -0500 )edit
1

answered 2021-03-09 14:23:03 -0500

If you're just combining text files together, the simplest method, especially if you're already using Python, is just to use a Python script that merges text files. This one will merge all .idf files in the directory (including subfolders) into a single file called merge.idf. Just copy the script into whatever directory in which you want to combine all the IDFs.

# This script copies all .idf files in dir and writes them into a new file called merge.idf
import os
dir = os.path.dirname(os.path.realpath(__file__))

mereged_text = ""

for path, subdirs, files in os.walk(dir):
    for name in files:
        ext = os.path.splitext(name)[-1].lower()
        if ext == ".idf":
            with open(name) as fp:
                text = fp.read()
            mereged_text += text
            mereged_text += "\n" # if new line is desired
with open ('merge.idf', 'w') as fp:
    fp.write(mereged_text)
edit flag offensive delete link more

Comments

of course, you can also do this using Modelkit or Eppy, but honestly a generic script is simpler and doesn't require additional software.

ericmartinpe gravatar image ericmartinpe  ( 2021-03-09 14:25:34 -0500 )edit

Yea, I just already have all the IDFs loaded in my script because I've had to do some other manipulation, and if there is something quick like idf_complete = idf1.idfconcatenate(idf2) that I could just export that's marginally simpler than first converting them to text and exporting from there, plus it keeps the classes in IDF Editor pretty order.

bbrannon4 gravatar image bbrannon4  ( 2021-03-09 14:34:09 -0500 )edit

Oh so the objects are saved in memory within your Eppy script, not already in separate text files? In terms of the sorting/ordering, Eppy should always sort objects per the IDD upon savings, just by doing idf.saveas(idf_filename). But to merge the objects before savings, I'd need to know more about the types of objects and/or how they're named in order to do a concatenation scheme within Eppy. I don't know of a concatenate function within Eppy. Can you share more about how the objects are saved or provide an example file?

ericmartinpe gravatar image ericmartinpe  ( 2021-03-09 14:43:05 -0500 )edit

I have never tried it but I would guess there is an easy way to do it. Have you just tried .extend() like it was a list? or maybe .update() like it was a dictionary?

JasonGlazer gravatar image JasonGlazer  ( 2021-03-09 14:45:51 -0500 )edit

Eric I just updated my question with some more context, but yes, they are already in memory for other reasons. Jason, I hadn't, but I just did and no luck.

bbrannon4 gravatar image bbrannon4  ( 2021-03-09 15:11:05 -0500 )edit
1

answered 2021-03-12 11:03:09 -0500

updated 2021-03-12 11:12:16 -0500

@bbrannon4, you could do it in a few line by retrieving the standard output. This would involve no text manipulation per se and no loops but it is not a full "eppy" solution.

stdout = sys.stdout
sys.stdout = six.StringIO()
idf1.printidf()
idf2.printidf()
idf_all = sys.stdout.getvalue()
sys.stdout = stdout
edit flag offensive delete link more

Comments

1

That's an interesting idea. I was just using idf_str = idf_object.idfstr() to print everything to strings and then concatenate and export to a file. Are you aware of any performance differences between these two methods?

bbrannon4 gravatar image bbrannon4  ( 2021-03-12 12:24:27 -0500 )edit

I have not done so, I'd be curious to know though!

Jeremy gravatar image Jeremy  ( 2021-03-12 12:26:41 -0500 )edit

Your Answer

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

Add Answer

 

Question Tools

1 follower

Stats

Asked: 2021-03-09 11:18:49 -0500

Seen: 88 times

Last updated: Mar 12