Source code for eppySupport

import os
from eppy import modeleditor
from eppy.modeleditor import IDF
from eppy.results import readhtml
import inspect
import subprocess

[docs]def listify_idf_objects(idf: IDF, objects: list): """ listify_idf_objects(idf, objects) Takes the passed idf, and grabs the objects out of it that are specified in objects Args: idf(IDF): The idf to grab the objects from objects(list): A list generated from a yaml file that specifies how and what to read from the idf file """ objects_list = [] #: For every set of object information in objects, and for #: every attribute in that object, check if it's in the variables #: dictionary, and if it is, and its a float, then append it to #: objects_list for objectset in objects: #: If the name of the object is "Run_Parameters", then its #: not an object, its actually something in the config file #: used to setup some run inputs. if objectset[0] == "Run_Parameters": continue #: Get the idf object from the idf based off its name (objectset[0]) current_object = get_idfobject_from_name(idf, objectset[0]) #: Loop through the attributes and check if both the attribute #: is in the Variables dictionary, and that it's float for attribute in current_object.fieldnames: #: Catch value errors to check if attributes are floats. try: #: Check that the attribute is in the Variables dictionary, #: if its not, raise a ValueError to move on. if attribute not in objectset[1]["Variables"]: raise ValueError #: Store a float of the attribute (if it cannot #: be converted to a float, then it will raise a #: ValueError, and move on. val = float(getattr(current_object, attribute)) #: Append the value to the objects_list objects_list.append(val) #: Except the ValueError, and pass except ValueError as e: pass #: Return the list of objects return objects_list
[docs]def rebuild_idf(idd_path: str, idf_path: str, epw_path: str, w_objects: list, build_list: list): """ rebuild_idf(idd_path, idf_path, epw_path, w_objects, build_list) Builds an idf based off of a passed config file, and a list of values that was passed. Args: idd_path(str): The absolute path to the idd file to be run. idf_path(str): The absolute path to the idf file to be run. epw_path(str): The absolute path to the epw file to be run. w_objects(list): A list generated from a yaml file that specifies how and what to read from the idf file build_list(list): A list of values which will be assigned to values in objects in the idf. """ #: Get an idf object from the passed idd, idf, and epw idf = create_idf_object(idd_path, idf_path, epw_path) i = 0 #: For every set of object information in w_objects, #: and for every attribute in the object described if that attribute #: is in the Variables dictionary, and the attribute is a float, AND the #: value for this entry in build_list is between the max and min values #: described in the object's information then set the attribute to the #: value in build_list. (Note, the first object's first valid field is #: equivellant to the first item in build_list, the second field to the #: second item in build_list, etc) for object in w_objects: #: If the name of the object is "Run_Parameters", then #: this is not an idf object, it's an informatic field #: from the config, so ignore it. if object[0] == "Run_Parameters": continue #: Get the object from the idf based off its name (object[0] holds #: the name of the object) current_object = get_idfobject_from_name(idf, object[0]) #: For each attribute in the object, check if the attribute is a #: float, and check that the value that the attribute that is to be #: set to is within the range given, and if both are true, then set #: the attribute to that value for attribute in current_object.fieldnames: #: Try catch block to catch ValueErrors that float(getattr) raises #: if the attribute is not a float (to check if the attribute is float) try: #: Check if the attribute is in the Variables dictionary #: and if its not, raise a ValueError to skip this attribute. if attribute not in object[1]["Variables"]: raise ValueError #: Attempt to get the attribute to check if its a float or not. val = float(getattr(current_object, attribute)) #: If we should check max/mins if dict(w_objects)["Run_Parameters"][1]: #: If the attribute has specific max/mins, #: then check if its within those limits if attribute in object[1].keys(): #: If the value is less than the min if build_list[i] < float(object[1][attribute][1]): #: return None as this idf is invalid return None #: If the value is more than the max elif build_list[i] > float(object[1][attribute][0]): #: return None as this idf is invalid return None #: Otherwise check it against the defaults else: #: If the value is less than the default min if build_list[i] < float(object[1]["Default"][1]): #: return None as this idf is invalid return None #: If the value is more than the default max elif build_list[i] > float(object[1]["Default"][0]): #: return None as this idf is invalid return None #: If we get to this point, then the attribute is valid, and the #: value is valid, so set the attribute to that value setattr(current_object, attribute, round(build_list[i], 2)) #: Add 1 to i, so that we can assign the next value to the next #: attribute i += 1 #: Except ValueErrors incase the attribute is not a float, or it is not in Variables except ValueError as e: for key, value in object[1]["Abstracts"].items(): if attribute == key: print(attribute, " ==> ", value) setattr(current_object, attribute, round(value, 2)) #: Return the idf with all the new attributes. return idf
[docs]def get_idfobject_from_name(idf: IDF, name: str): """ get_idfobject_from_name(idf, name) Gets an object from the passed idf where it's name value is equal to the passed string, if none are found then this method returns None Args: idf(IDF): The idf to find the object from. name(str): The string to find that is equal to the name field of the object. """ #: For every object in the idf. for idfobject in idf.idfobjects: #: For field in this object for object in idf.idfobjects[idfobject]: #: Try except block incase object does not #: have a .Name attribute try: #: If object.Name == name, then return #: the object, as that is the object #: we're looking at. if object.Name == name: return object #: Move on to the next object if an exception is #: raised. except: pass #: If this is enocuntered then no match was found, so we return None. return None
[docs]def create_idf_object(idd: str, idf: str, epw: str): """ create_idf_object(idd, idf, epw) Returns an idf object generated from the passed idd, idf, and epw Args: idd(str): The directory to the idd idf(str): The directory to the idf epw(str): The directory to the epw """ #: Try to set the idd attribute for the IDF class. try: IDF.setiddname(idd) except: pass #: Create an idf object based off the passed idf and epw. idf = IDF(idf, epw) #: return the created idf object return idf
[docs]def printErr(msg: str): """ printErr(msg) Prints the message in an error red on unicode supported consoles. Args: msg(str): The string to print """ #: print(red_colour + msg + end_colour) print('\033[91m' + msg + '\033[0m')
[docs]def printSuccess(msg: str): """ printSuccess(msg) Prints the message in a success green on unicode supported consoles. Args: msg(str): The string to print """ #: print(green_colour + msg + end_colour) print('\033[92m' + msg + '\033[0m')
[docs]def get_energy_usage(idf: IDF, obj_list= None) -> float: """ get_energy_usage(idf, obj_list) Runs an idf, and extracts the building's energy usage from that run. Args: idf(IDF): The idf to be run. obj_list(list): ONLY USED IF VERBOSE IS TRUE FOR DEBUGGING PURPOSES. This variable prints the final state of each of the idf's objects that are being changed. """ #: Verbose is used to help debug, when true it prints #: additional information about each run. verbose = False #: Try to run the idf. If an error is caught during this execution #: then the idf is unrunable, and we will return an energy usage of inf try: #: Run the idf. if Verbose is False, then we log that we're running #: the idf, and when it's finished, but we suppress the output from #: the idf's actual run. If verbose is True, we instead run the idf #: without suppressing its objectives if not verbose: print("Running idf...") idf.run(verbose='q') #: verbose='q' suppresses objectives printSuccess("Done.") else: idf.run() except: #: If an exception is raised, then print that we failed to run #: the idf, and return inf. NOTE, if verbose is true, we will also #: print all of the objects being looked at, so that we can analize #: why the idf is unrunable printErr("Failed to run idf. Is it valid?") if verbose == True and obj_list is not None: for object in obj_list: print(get_idfobject_from_name(idf, object[0])) #: return inf return float("inf") #: Create a variable to hold the sum of the energy used. energy_used = 0.0 #: Open the meter file to read what the energy usages were. with open("eplusout.mtr", 'r') as filestring: #: Read all the lines in the file, and split them into seperate string #: in a list. This way we can analize each line seperately. strings = filestring.read().split('\n') for line in strings[35:]: #: If the line has the id 13 (ie the first entry is 13) then #: this is one of the objectives we want to look at, so grab the #: float value from the line (which will be in the second #: position of the csv) and read it as a float. Add that float #: to the total energy used. if line[:3] == "13,": energy_used += float(line[3:line[3:].find(',')]) #: If the line has the id 274 (ie the first entry is 274) then #: this is one of the objectives we want to look at, so grab the #: float value from the line (which will be in the second #: position of the csv) and read it as a float. Add that float #: to the total energy used. elif line[:4] == "274,": energy_used += float(line[4:line[4:].find(',')]) #: Return the total amount of energy used. return energy_used
def main(): """ main() This method will not be documented as it is not meant to be run. This method is used for debugging and testing only, and thus it may change from commit to commit without any mention. """ IDF.setiddname("EP.idd") idf = IDF("input.idf", "t.epw") myWindow = idf.idfobjects['FENESTRATIONSURFACE:DETAILED'] for window in myWindow: print(window) exit() print(get_idfobject_from_name(idf, "Perimeter_ZN_3_wall_north_Window_6")) energies_used = [] min_height = 0.91 denom = 100 for i in range(200, -1, -1): idf.idfobjects['FENESTRATIONSURFACE:DETAILED'][0].Vertex_1_Zcoordinate = round(min_height + (i / denom), 2) idf.idfobjects['FENESTRATIONSURFACE:DETAILED'][0].Vertex_4_Zcoordinate = round(min_height + (i / denom), 2) print("Running with window height {}".format(round(min_height + (i/denom), 2))) energies_used.append((round(min_height + (i / denom), 2), get_energy_usage(idf))) energies_used = sorted(energies_used, key= lambda x: x[1]) for index, use in enumerate(energies_used): print("{}th best solution has window height {}".format(index + 1, use[0]), end='\n\t') print(use[1]) print("Best window size is: ", end='\n\t') print(min(energies_used, key=lambda x: x[1])) if __name__ == "__main__": main()