diff --git a/epyt/__init__.py b/epyt/__init__.py index ea63f58..990172d 100644 --- a/epyt/__init__.py +++ b/epyt/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- __author__ = """Marios S. Kyriakou""" __email__ = "kiriakou.marios@ucy.ac.cy" -__version__ = "1.0.9-beta.6" +__version__ = "1.1.0" __msxversion__ = "2.0.0" __copyright__ = """Copyright 2022, KIOS Research and Innovation Center of Excellence (KIOS CoE), University of Cyprus (www.kios.org.cy).""" diff --git a/epyt/epanet.py b/epyt/epanet.py index e476d4b..10c90c6 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -509,8 +509,9 @@ class epanet: d = epanet(inpname, msx=True,customlib=epanetlib) """ - def __init__(self, *argv, version=2.2, ph=False, loadfile=False, msx=False, customlib=None): + def __init__(self, *argv, version=2.2, ph=False, loadfile=False, customlib=None): # Constants + warnings.simplefilter('always') # Demand model types. DDA #0 Demand driven analysis, # PDA #1 Pressure driven analysis. self.msxname = None @@ -570,7 +571,7 @@ def __init__(self, *argv, version=2.2, ph=False, loadfile=False, msx=False, cust # Initial attributes self.classversion = __version__ - self.api = epanetapi(version, msx=msx, customlib=customlib) + self.api = epanetapi(version, ph=ph, customlib=customlib) print(f'EPANET version {self.getVersion()} ' f'loaded (EPyT version {self.classversion}).') @@ -632,18 +633,12 @@ def __init__(self, *argv, version=2.2, ph=False, loadfile=False, msx=False, cust self.LibEPANET = self.api.LibEPANET print(f'Input File {self.netName} loaded successfully.\n') - if ph: - self.createProject() - # Global plot settings plt.rcParams["figure.figsize"] = [3, 2] plt.rcParams['figure.dpi'] = 300 plt.rcParams['figure.constrained_layout.use'] = True plt.rcParams['figure.max_open_warning'] = 30 - if msx: - self.msx = epanetmsxapi(ignore_msxfile=True) - def addControls(self, control, *argv): """ Adds a new simple control. @@ -2362,6 +2357,12 @@ def getComputedTimeSeries(self): value_final = self.getComputedTimeSeries_ENepanet() return value_final value = self.__readEpanetBin(fid, binfile, 0) + value.WarnFlag = False + if self.errcode: + value.WarnFlag = True + value.ErrCode = self.errcode + self.api.ENgeterror(self.errcode) + value.StatusStr = {} for i in range(1, len(value.Status) + 1): value.StatusStr[i] = [] @@ -2393,6 +2394,10 @@ def getComputedTimeSeries_ENepanet(self): self.api.ENepanet(self.TempInpFile, rptfile, binfile) fid = open(binfile, "rb") value = self.__readEpanetBin(fid, binfile, 0) + value.WarnFlag = False + if self.errcode: + value.ErrCode = self.errcode + value.WarnFlag = True value.StatusStr = {} for i in range(1, len(value.Status) + 1): value.StatusStr[i] = [] @@ -2410,6 +2415,7 @@ def getComputedTimeSeries_ENepanet(self): else: exec(f"value_final.{i} = val_dict[i]") value_final.Status = value_final.Status.astype(int) + self.loadEPANETFile(self.TempInpFile) return value_final def getAdjacencyMatrix(self): @@ -3690,7 +3696,7 @@ def getLinkVertices(self, *argv): continue x_mat = [] y_mat = [] - for j in range(1, self.getLinkVerticesCount(i) + 1): + for j in range(1, self.getLinkVerticesCount(i) +1): xy = self.api.ENgetvertex(i, j) x_mat.append(xy[0]) y_mat.append(xy[1]) @@ -9368,7 +9374,12 @@ def setRulePremise(self, ruleIndex, premiseIndex, premise): value = -1 status = eval('self.ToolkitConstants.EN_R_IS_' + premise_new[m]) else: - value = float(premise_new[m]) + try: + value = float(premise_new[m]) + except: + time_str = premise_new[m] + hours, minutes = map(int, time_str.split(':')) + value = hours + minutes / 60 status = 0 if object_ == self.ToolkitConstants.EN_R_SYSTEM: if premise_new[5] == 'AM': @@ -10369,26 +10380,28 @@ def unload(self): try: self.api.ENclose() finally: - safe_delete(self.TempInpFile) - files_to_delete = [self.TempInpFile[0:-4] + '.txt', self.InputFile[0:-4] + '.txt', self.BinTempfile] - for file in files_to_delete: - safe_delete(file) - for file in Path(".").glob("@#*.txt"): - safe_delete(file) - safe_delete(self.TempInpFile) - - cwd = os.getcwd() - files = os.listdir(cwd) - tmp_files = [ - f for f in files - if os.path.isfile(os.path.join(cwd, f)) and - (f.startswith('s') or f.startswith('en')) and - 6 <= len(f) <= 8 and - "." not in f - ] - tmp_files_paths = [os.path.join(cwd, f) for f in tmp_files] - safe_delete(tmp_files_paths) - + try: + safe_delete(self.TempInpFile) + files_to_delete = [self.TempInpFile[0:-4] + '.txt', self.InputFile[0:-4] + '.txt', self.BinTempfile] + for file in files_to_delete: + safe_delete(file) + for file in Path(".").glob("@#*.txt"): + safe_delete(file) + safe_delete(self.TempInpFile) + + cwd = os.getcwd() + files = os.listdir(cwd) + tmp_files = [ + f for f in files + if os.path.isfile(os.path.join(cwd, f)) and + (f.startswith('s') or f.startswith('en')) and + 5 <= len(f) <= 8 and + "." not in f + ] + tmp_files_paths = [os.path.join(cwd, f) for f in tmp_files] + safe_delete(tmp_files_paths) + except: + pass print(f'Close toolkit for the input file "{self.netName[0:-4]}". EPANET Toolkit is unloaded.\n') def useHydraulicFile(self, hydname): @@ -10923,7 +10936,7 @@ def __readEpanetBin(self, f, binfile, *argv): value.IDLabelEachLink = [] for i in range(value.NumberLinks): value.IDLabelEachLink.append(f.read(32).replace(b'\x00', b'').decode()) - while (True): + while True: binval = list(f.read(1))[0] if binval != 0: break @@ -11001,8 +11014,13 @@ def __readEpanetBin(self, f, binfile, *argv): value.AverageTankReactionRate = struct.unpack('f', f.read(4)) value.AverageSourceInflowRate = struct.unpack('f', f.read(4)) value.NumberReportingPeriods2 = list(f.read(1))[0] + f.read(1) + f.read(1) + f.read(1) value.WarningFlag = list(f.read(1))[0] - value.MagicNumber = f.read(10) + self.errcode = value.WarningFlag + # check here - error + value.MagicNumber = struct.unpack('b', f.read(1)) if len(argv) > 0: v = EpytValues() @@ -11181,8 +11199,13 @@ def loadMSXFile(self, msxname, customMSXlib=None, ignore_properties=False): self.msxname = msxname[:-4] + '_temp.msx' copyfile(msxname, self.msxname) self.msx = epanetmsxapi(self.msxname, customMSXlib=customMSXlib) - print(f'MSX version {__msxversion__}.') + #message to user if he uses ph with msx + if self.api._ph is not None: + print("In order for LoadMSX to work remove from epanet the ph") + print("Example: change this line ") + print("from this: << 0 and time_smle != t: - k = k + 1 t, tleft = self.stepMSXQualityAnalysisTimeLeft() - if node_indices[-1] < link_indices[-1]: - for i in range(len(speciename)): - for lnk in link_indices: - value["LinkQuality"][k - 1][lnk - 1, i - 1] = self.getMSXSpeciesConcentration(1, lnk, - speciename[i]) - if lnk < node_indices[-1] + 1: - value["NodeQuality"][k - 1][lnk - 1, i - 1] = self.getMSXSpeciesConcentration(0, lnk, - speciename[i]) - - else: - for i in range(len(speciename)): - for lnk in node_indices: - value["NodeQuality"][k - 1][lnk - 1][i - 1] = self.getMSXSpeciesConcentration(0, lnk, - speciename[i]) - if lnk < link_indices[-1] + 1: - value["LinkQuality"][k - 1][lnk - 1][i - 1] = self.getMSXSpeciesConcentration(1, lnk, - speciename[i]) - value["Time"].append([t]) + if t >= msx_time_step: + for g, j in enumerate(species_index_name, start=1): + for i, nl in enumerate(node_indices, start=1): + data['NodeQuality'][i - 1][k, g - 1] = self.getMSXSpeciesConcentration(0, nl, j) + for i, nl in enumerate(link_indices, start=1): + data['LinkQuality'][i - 1][k, g - 1] = self.getMSXSpeciesConcentration(1, nl, j) + k += 1 + value = EpytValues() + value.NodeQuality, value.LinkQuality = {}, {} + value.NodeQuality = data['NodeQuality'] + value.LinkQuality = data['LinkQuality'] + value.Time = [int(i * msx_time_step) for i in + range(int(self.getTimeSimulationDuration() / msx_time_step) + 1)] return value @@ -12829,7 +12842,7 @@ class epanetapi: EN_MAXID = 32 # toolkit constant - def __init__(self, version=2.2, msx=False, loadlib=True, customlib=None): + def __init__(self, version=2.2, ph=False, loadlib=True, customlib=None): """Load the EPANET library. Parameters: @@ -12837,7 +12850,6 @@ def __init__(self, version=2.2, msx=False, loadlib=True, customlib=None): """ self._lib = None self.errcode = 0 - self.isloaded = False self.inpfile = None self.rptfile = None self.binfile = None @@ -12866,7 +12878,7 @@ def __init__(self, version=2.2, msx=False, loadlib=True, customlib=None): self._lib = cdll.LoadLibrary(self.LibEPANET) self.LibEPANETpath = os.path.dirname(self.LibEPANET) - if float(version) >= 2.2 and not msx: + if float(version) >= 2.2 and ph: self._ph = c_uint64() else: self._ph = None @@ -12947,7 +12959,7 @@ def ENadddemand(self, nodeIndex, baseDemand, demandPattern, demandName): demandPattern.encode("utf-8"), demandName.encode("utf-8")) else: - self.errcode = self._lib.ENadddemand(int(nodeIndex), c_double(baseDemand), + self.errcode = self._lib.ENadddemand(int(nodeIndex), c_float(baseDemand), demandPattern.encode("utf-8"), demandName.encode("utf-8")) @@ -13063,7 +13075,6 @@ def ENclose(self): See also ENopen """ - if self._ph is not None: self.errcode = self._lib.EN_close(self._ph) self._ph = c_uint64() @@ -13071,9 +13082,6 @@ def ENclose(self): self.errcode = self._lib.ENclose() self.ENgeterror() - if self.errcode < 100: - self.isloaded = False - return def ENcloseH(self): """ Closes the hydraulic solver freeing all of its allocated memory. @@ -13137,8 +13145,6 @@ def ENcreateproject(self): if self._ph is not None: self.errcode = self._lib.EN_createproject(byref(self._ph)) - else: - self.errcode = self._lib.ENcreateproject(byref()) self.ENgeterror() return @@ -13302,11 +13308,13 @@ def ENgetaveragepatternvalue(self, index): Returns: value The average of all of the time pattern's factors. """ - value = c_double() + if self._ph is not None: + value = c_double() self.errcode = self._lib.EN_getaveragepatternvalue(self._ph, int(index), byref(value)) else: + value = c_float() self.errcode = self._lib.ENgetaveragepatternvalue(int(index), byref(value)) self.ENgeterror() @@ -13325,11 +13333,12 @@ def ENgetbasedemand(self, index, numdemands): Returns: value the category's base demand. """ - bDem = c_double() if self._ph is not None: + bDem = c_double() self.errcode = self._lib.EN_getbasedemand(self._ph, int(index), numdemands, byref(bDem)) else: + bDem = c_float() self.errcode = self._lib.ENgetbasedemand(int(index), numdemands, byref(bDem)) self.ENgeterror() @@ -13632,14 +13641,16 @@ def ENgetdemandmodel(self): OWA-EPANET Toolkit: http://wateranalytics.org/EPANET/group___demands.html """ Type = c_int() - pmin = c_double() - preq = c_double() - pexp = c_double() - if self._ph is not None: + pmin = c_double() + preq = c_double() + pexp = c_double() self.errcode = self._lib.EN_getdemandmodel(self._ph, byref(Type), byref(pmin), byref(preq), byref(pexp)) else: + pmin = c_float() + preq = c_float() + pexp = c_float() self.errcode = self._lib.ENgetdemandmodel(byref(Type), byref(pmin), byref(preq), byref(pexp)) @@ -13661,12 +13672,14 @@ def ENgetdemandname(self, node_index, demand_index): OWA-EPANET Toolkit: http://wateranalytics.org/EPANET/group___demands.html """ - demand_name = create_string_buffer(100) + if self._ph is not None: + demand_name = create_string_buffer(100) self.errcode = self._lib.EN_getdemandname(self._ph, int(node_index), int(demand_index), byref(demand_name)) else: + demand_name = create_string_buffer(80) self.errcode = self._lib.ENgetdemandname(int(node_index), int(demand_index), byref(demand_name)) @@ -13714,13 +13727,14 @@ def ENgetelseaction(self, ruleIndex, actionIndex): """ linkIndex = c_int() status = c_int() - setting = c_double() if self._ph is not None: + setting = c_double() self.errcode = self._lib.EN_getelseaction(self._ph, int(ruleIndex), int(actionIndex), byref(linkIndex), byref(status), byref(setting)) else: + setting = c_float() self.errcode = self._lib.ENgetelseaction(int(ruleIndex), int(actionIndex), byref(linkIndex), byref(status), byref(setting)) @@ -13728,13 +13742,15 @@ def ENgetelseaction(self, ruleIndex, actionIndex): self.ENgeterror() return [linkIndex.value, status.value, setting.value] - def ENgeterror(self): + def ENgeterror(self, errcode=0): """ Returns the text of an error message generated by an error code, as warning. ENgeterror() """ - if self.errcode: + if self.errcode or errcode: + if errcode: + self.errcode = errcode errmssg = create_string_buffer(150) self._lib.ENgeterror(self.errcode, byref(errmssg), 150) warnings.warn(errmssg.value.decode()) @@ -14020,11 +14036,11 @@ def ENgetoption(self, optioncode): Returns: value the current value of the option. """ - value = c_double() - if self._ph is not None: + value = c_double() self.errcode = self._lib.EN_getoption(self._ph, optioncode, byref(value)) else: + value = c_float() self.errcode = self._lib.ENgetoption(optioncode, byref(value)) self.ENgeterror() @@ -14142,14 +14158,15 @@ def ENgetpremise(self, ruleIndex, premiseIndex): variable = c_int() relop = c_int() status = c_int() - value = c_double() if self._ph is not None: + value = c_double() self.errcode = self._lib.EN_getpremise(self._ph, int(ruleIndex), int(premiseIndex), byref(logop), byref(object_), byref(objIndex), byref(variable), byref(relop), byref(status), byref(value)) else: + value = c_float() self.errcode = self._lib.ENgetpremise(int(ruleIndex), int(premiseIndex), byref(logop), byref(object_), byref(objIndex), byref(variable), byref(relop), byref(status), @@ -14267,13 +14284,14 @@ def ENgetrule(self, index): nPremises = c_int() nThenActions = c_int() nElseActions = c_int() - priority = c_double() if self._ph is not None: + priority = c_double() self.errcode = self._lib.EN_getrule(self._ph, int(index), byref(nPremises), byref(nThenActions), byref(nElseActions), byref(priority)) else: + priority = c_float() self.errcode = self._lib.ENgetrule(int(index), byref(nPremises), byref(nThenActions), byref(nElseActions), byref(priority)) @@ -14319,11 +14337,11 @@ def ENgetstatistic(self, code): OWA-EPANET Toolkit: http://wateranalytics.org/EPANET/group___reporting.html """ - value = c_double() - if self._ph is not None: + value = c_double() self.errcode = self._lib.EN_getstatistic(self._ph, int(code), byref(value)) else: + value = c_float() self.errcode = self._lib.ENgetstatistic(int(code), byref(value)) self.ENgeterror() @@ -14346,13 +14364,13 @@ def ENgetthenaction(self, ruleIndex, actionIndex): """ linkIndex = c_int() status = c_int() - setting = c_double() - if self._ph is not None: + setting = c_double() self.errcode = self._lib.EN_getthenaction(self._ph, int(ruleIndex), int(actionIndex), byref(linkIndex), byref(status), byref(setting)) else: + setting = c_float() self.errcode = self._lib.ENgetthenaction(int(ruleIndex), int(actionIndex), byref(linkIndex), byref(status), byref(setting)) @@ -14433,9 +14451,8 @@ def ENgetvertex(self, index, vertex): x the vertex's X-coordinate value. y the vertex's Y-coordinate value. """ - x = c_double() + x = c_double() # need double for EN_ or EN functions. y = c_double() - if self._ph is not None: self.errcode = self._lib.EN_getvertex(self._ph, int(index), vertex, byref(x), byref(y)) else: @@ -14594,11 +14611,6 @@ def ENopen(self, inpname=None, repname=None, binname=None): self.rptfile = bytes(repname, 'utf-8') self.binfile = bytes(binname, 'utf-8') - if self.isloaded: - self.ENclose() - if self.isloaded: - raise RuntimeError("File is loaded and cannot be closed.") - if self._ph is not None: self._lib.EN_createproject(byref(self._ph)) self.errcode = self._lib.EN_open(self._ph, self.inpfile, self.rptfile, self.binfile) @@ -14606,8 +14618,6 @@ def ENopen(self, inpname=None, repname=None, binname=None): self.errcode = self._lib.ENopen(self.inpfile, self.rptfile, self.binfile) self.ENgeterror() - if self.errcode < 100: - self.isloaded = True return def ENopenH(self): @@ -14777,7 +14787,7 @@ def ENsetbasedemand(self, index, demandIdx, value): if self._ph is not None: self.errcode = self._lib.EN_setbasedemand(self._ph, int(index), demandIdx, c_double(value)) else: - self.errcode = self._lib.ENsetbasedemand(int(index), demandIdx, c_double(value)) + self.errcode = self._lib.ENsetbasedemand(int(index), demandIdx, c_float(value)) self.ENgeterror() @@ -14819,12 +14829,10 @@ def ENsetcontrol(self, cindex, ctype, lindex, setting, nindex, level): if self._ph is not None: self.errcode = self._lib.EN_setcontrol(self._ph, int(cindex), ctype, lindex, c_double(setting), - nindex, - c_double(level)) + nindex, c_double(level)) else: - self.errcode = self._lib.ENsetcontrol(int(cindex), ctype, lindex, c_double(setting), - nindex, - c_double(level)) + self.errcode = self._lib.ENsetcontrol(int(cindex), ctype, lindex, c_float(setting), + nindex, c_float(level)) self.ENgeterror() @@ -14869,8 +14877,8 @@ def ENsetcurve(self, index, x, y, nfactors): self.errcode = self._lib.EN_setcurve(self._ph, int(index), (c_double * 1)(x), (c_double * 1)(y), nfactors) else: - self.errcode = self._lib.ENsetcurve(int(index), (c_double * 1)(x), - (c_double * 1)(y), nfactors) + self.errcode = self._lib.ENsetcurve(int(index), (c_float * 1)(x), + (c_float * 1)(y), nfactors) else: @@ -14879,8 +14887,8 @@ def ENsetcurve(self, index, x, y, nfactors): self.errcode = self._lib.EN_setcurve(self._ph, int(index), (c_double * nfactors)(*x), (c_double * nfactors)(*y), nfactors) else: - self.errcode = self._lib.ENsetcurve(int(index), (c_double * nfactors)(*x), - (c_double * nfactors)(*y), nfactors) + self.errcode = self._lib.ENsetcurve(int(index), (c_float * nfactors)(*x), + (c_float * nfactors)(*y), nfactors) self.ENgeterror() @@ -14923,7 +14931,7 @@ def ENsetcurvevalue(self, index, pnt, x, y): c_double(x), c_double(y)) else: self.errcode = self._lib.ENsetcurvevalue(int(index), pnt, - c_double(x), c_double(y)) + c_float(x), c_float(y)) self.ENgeterror() @@ -14946,8 +14954,8 @@ def ENsetdemandmodel(self, Type, pmin, preq, pexp): self.errcode = self._lib.EN_setdemandmodel(self._ph, Type, c_double(pmin), c_double(preq), c_double(pexp)) else: - self.errcode = self._lib.ENsetdemandmodel(Type, c_double(pmin), - c_double(preq), c_double(pexp)) + self.errcode = self._lib.ENsetdemandmodel(Type, c_float(pmin), + c_float(preq), c_float(pexp)) self.ENgeterror() @@ -15014,7 +15022,7 @@ def ENsetelseaction(self, ruleIndex, actionIndex, linkIndex, status, setting): else: self.errcode = self._lib.ENsetelseaction(int(ruleIndex), int(actionIndex), int(linkIndex), status, - c_double(setting)) + c_float(setting)) self.ENgeterror() @@ -15072,7 +15080,7 @@ def ENsetjuncdata(self, index, elev, dmnd, dmndpat): self.errcode = self._lib.EN_setjuncdata(self._ph, int(index), c_double(elev), c_double(dmnd), dmndpat.encode("utf-8")) else: - self.errcode = self._lib.ENsetjuncdata(int(index), c_double(elev), c_double(dmnd), + self.errcode = self._lib.ENsetjuncdata(int(index), c_float(elev), c_float(dmnd), dmndpat.encode("utf-8")) self.ENgeterror() @@ -15200,8 +15208,7 @@ def ENsetnodevalue(self, index, paramcode, value): c_double(value)) else: self.errcode = self._lib.ENsetnodevalue(c_int(index), c_int(paramcode), - c_double(value)) - + c_float(value)) self.ENgeterror() return @@ -15218,8 +15225,7 @@ def ENsetoption(self, optioncode, value): if self._ph is not None: self.errcode = self._lib.EN_setoption(self._ph, optioncode, c_double(value)) else: - self.errcode = self._lib.ENsetoption(optioncode, c_double(value)) - + self.errcode = self._lib.ENsetoption(optioncode, c_float(value)) self.ENgeterror() def ENsetpattern(self, index, factors, nfactors): @@ -15240,7 +15246,6 @@ def ENsetpattern(self, index, factors, nfactors): else: self.errcode = self._lib.ENsetpattern(int(index), (c_float * nfactors)(*factors), nfactors) - self.ENgeterror() def ENsetpatternid(self, index, Id): @@ -15260,7 +15265,6 @@ def ENsetpatternid(self, index, Id): self.errcode = self._lib.EN_setpatternid(self._ph, int(index), Id.encode('utf-8')) else: self.errcode = self._lib.ENsetpatternid(int(index), Id.encode('utf-8')) - self.ENgeterror() def ENsetpatternvalue(self, index, period, value): @@ -15277,8 +15281,7 @@ def ENsetpatternvalue(self, index, period, value): if self._ph is not None: self.errcode = self._lib.EN_setpatternvalue(self._ph, int(index), period, c_double(value)) else: - self.errcode = self._lib.ENsetpatternvalue(int(index), period, c_double(value)) - + self.errcode = self._lib.ENsetpatternvalue(int(index), period, c_float(value)) self.ENgeterror() def ENsetpipedata(self, index, length, diam, rough, mloss): @@ -15302,9 +15305,9 @@ def ENsetpipedata(self, index, length, diam, rough, mloss): c_double(diam), c_double(rough), c_double(mloss)) else: - self.errcode = self._lib.ENsetpipedata(int(index), c_double(length), - c_double(diam), c_double(rough), - c_double(mloss)) + self.errcode = self._lib.ENsetpipedata(int(index), c_float(length), + c_float(diam), c_float(rough), + c_float(mloss)) self.ENgeterror() @@ -15333,7 +15336,7 @@ def ENsetpremise(self, ruleIndex, premiseIndex, logop, object_, objIndex, variab objIndex, variable, relop, status, c_double(value)) else: self.errcode = self._lib.ENsetpremise(int(ruleIndex), int(premiseIndex), logop, object_, - objIndex, variable, relop, status, c_double(value)) + objIndex, variable, relop, status, c_float(value)) self.ENgeterror() @@ -15390,7 +15393,7 @@ def ENsetpremisevalue(self, ruleIndex, premiseIndex, value): if self._ph is not None: self.errcode = self._lib.EN_setpremisevalue(self._ph, int(ruleIndex), premiseIndex, c_double(value)) else: - self.errcode = self._lib.ENsetpremisevalue(int(ruleIndex), premiseIndex, c_double(value)) + self.errcode = self._lib.ENsetpremisevalue(int(ruleIndex), premiseIndex, c_float(value)) self.ENgeterror() @@ -15450,7 +15453,7 @@ def ENsetrulepriority(self, ruleIndex, priority): if self._ph is not None: self.errcode = self._lib.EN_setrulepriority(self._ph, int(ruleIndex), c_double(priority)) else: - self.errcode = self._lib.ENsetrulepriority(int(ruleIndex), c_double(priority)) + self.errcode = self._lib.ENsetrulepriority(int(ruleIndex), c_float(priority)) self.ENgeterror() @@ -15491,9 +15494,15 @@ def ENsettankdata(self, index, elev, initlvl, minlvl, maxlvl, diam, minvol, volc OWA-EPANET Toolkit: http://wateranalytics.org/EPANET/group___nodes.html """ - self.errcode = self._lib.EN_settankdata( - self._ph, index, c_double(elev), c_double(initlvl), c_double(minlvl), - c_double(maxlvl), c_double(diam), c_double(minvol), volcurve.encode('utf-8')) + + if self._ph is not None: + self.errcode = self._lib.EN_settankdata( + self._ph, index, c_double(elev), c_double(initlvl), c_double(minlvl), + c_double(maxlvl), c_double(diam), c_double(minvol), volcurve.encode('utf-8')) + else: + self.errcode = self._lib.ENsettankdata(index, c_float(elev), c_float(initlvl), c_float(minlvl), + c_float(maxlvl), c_float(diam), c_float(minvol), volcurve.encode('utf-8')) + self.ENgeterror() def ENsetthenaction(self, ruleIndex, actionIndex, linkIndex, status, setting): @@ -15518,7 +15527,7 @@ def ENsetthenaction(self, ruleIndex, actionIndex, linkIndex, status, setting): else: self.errcode = self._lib.ENsetthenaction(int(ruleIndex), int(actionIndex), int(linkIndex), status, - c_double(setting)) + c_float(setting)) self.ENgeterror() @@ -15581,7 +15590,7 @@ def ENsetvertices(self, index, x, y, vertex): else: self.errcode = self._lib.ENsetvertices(int(index), (c_double * vertex)(*x), - (c_double * vertex)(*y), vertex) + (c_double * vertex)(*y), vertex) self.ENgeterror() @@ -16193,8 +16202,8 @@ def MSXstep(self): t : current simulation time at the end of the step(in secconds) tleft: time left in the simulation (in secconds) """ - t = c_int() - tleft = c_int() + t = c_long() + tleft = c_long() err = self.msx_lib.MSXstep(byref(t), byref(tleft)) if err: @@ -16211,7 +16220,6 @@ def MSXinit(self, flag): Parameters: flag: Set the flag to 1 if the water quality results should be saved to a scratch binary file, or 0 if not - """ err = self.msx_lib.MSXinit(flag) if err: diff --git a/epyt/examples/python/EX6_load_two_inp_files.py b/epyt/examples/python/EX6_load_two_inp_files.py index 3fff630..a0875a0 100644 --- a/epyt/examples/python/EX6_load_two_inp_files.py +++ b/epyt/examples/python/EX6_load_two_inp_files.py @@ -9,8 +9,8 @@ from epyt import epanet # Load networks -d1 = epanet('Net1.inp') -d2 = epanet('Net2.inp') +d1 = epanet('Net1.inp', ph=True) +d2 = epanet('Net2.inp', ph=True) # Close any open figures d1.plot_close() diff --git a/epyt/examples/python/EX_to_excel_json.py b/epyt/examples/python/EX_to_excel_json.py index de906bf..6617a15 100644 --- a/epyt/examples/python/EX_to_excel_json.py +++ b/epyt/examples/python/EX_to_excel_json.py @@ -41,10 +41,10 @@ """ ------------------- excel ---------------------------- """ # Create a .xlsx excel file and save all the values of each attribute # in seperate sheet -comp_values.to_excel("to_excel_seperate_values_example") +# comp_values.to_excel("to_excel_seperate_values_example") # Create a .xlsx excel file and save all the values in a sheet -comp_values.to_excel("to_excel_all_values_example", allValues=True) +# comp_values.to_excel("to_excel_all_values_example", allValues=True) # Create a .xlsx excel file and select multiple attributes to be # displayed in seperate sheets diff --git a/epyt/examples/python/Toolkit_EX4_Network_Building.py b/epyt/examples/python/Toolkit_EX4_Network_Building.py index e929de0..0bdbd3d 100644 --- a/epyt/examples/python/Toolkit_EX4_Network_Building.py +++ b/epyt/examples/python/Toolkit_EX4_Network_Building.py @@ -15,7 +15,7 @@ # Create an empty INP file testinp = 'TESTING.inp' -d = epanet(testinp, 'CREATE') +d = epanet(testinp, 'CREATE', ph=True) # Initialize epanet flow units d.initializeEPANET(d.ToolkitConstants.EN_GPM, d.ToolkitConstants.EN_HW) @@ -69,7 +69,7 @@ # Save the project for future use d.saveInputFile(testinp) -d = epanet(testinp) +d = epanet(testinp, ph=True) d.plot() d.plot_show() d.deleteProject() diff --git a/epyt/examples/python/Toolkit_api_EX2_using_MSX_functions.py b/epyt/examples/python/Toolkit_api_EX2_using_MSX_functions.py index 529a887..35306ea 100644 --- a/epyt/examples/python/Toolkit_api_EX2_using_MSX_functions.py +++ b/epyt/examples/python/Toolkit_api_EX2_using_MSX_functions.py @@ -8,7 +8,7 @@ inpname = os.path.join(dirname, 'msx-examples', 'net2-cl2.inp') msxname = os.path.join(dirname, 'msx-examples', 'net2-cl2.msx') -d = epanet(inpname, msx=True) +d = epanet(inpname) msx = epanetmsxapi(msxname) MSX_SPECIES = 3 ss = list(range(1, d.LinkCount + 1)) diff --git a/epyt/libraries/glnx/epanetmsx b/epyt/libraries/glnx/epanetmsx new file mode 100644 index 0000000..135560e Binary files /dev/null and b/epyt/libraries/glnx/epanetmsx differ diff --git a/epyt/libraries/glnx/libepanet2 b/epyt/libraries/glnx/libepanet2 new file mode 100644 index 0000000..33436a3 Binary files /dev/null and b/epyt/libraries/glnx/libepanet2 differ diff --git a/epyt/libraries/mac/epanetmsx b/epyt/libraries/mac/epanetmsx new file mode 100644 index 0000000..37422ad Binary files /dev/null and b/epyt/libraries/mac/epanetmsx differ diff --git a/epyt/libraries/mac/libepanet2 b/epyt/libraries/mac/libepanet2 new file mode 100644 index 0000000..d79d80f Binary files /dev/null and b/epyt/libraries/mac/libepanet2 differ diff --git a/epyt/libraries/win/epanet2.dll b/epyt/libraries/win/epanet2.dll index 544c418..5b4a7a1 100644 Binary files a/epyt/libraries/win/epanet2.dll and b/epyt/libraries/win/epanet2.dll differ diff --git a/epyt/libraries/win/epanet2.exe b/epyt/libraries/win/epanet2.exe index 9df0903..a5a04b6 100644 Binary files a/epyt/libraries/win/epanet2.exe and b/epyt/libraries/win/epanet2.exe differ diff --git a/epyt/libraries/win/epanetmsx.exe b/epyt/libraries/win/epanetmsx.exe index 1a64ac9..ae47806 100644 Binary files a/epyt/libraries/win/epanetmsx.exe and b/epyt/libraries/win/epanetmsx.exe differ diff --git a/epyt/tests/general_unit_test.py b/epyt/tests/general_unit_test.py index e68c295..f61f9ff 100644 --- a/epyt/tests/general_unit_test.py +++ b/epyt/tests/general_unit_test.py @@ -9,7 +9,7 @@ def setUp(self): """Call before every test case.""" # Create EPANET object using the INP file inp_name = 'Net1.inp' - self.epanetClass = epanet(inp_name) + self.epanetClass = epanet(inp_name, ph=False) def tearDown(self): """Call after every test case.""" @@ -167,7 +167,7 @@ def test_addNodeJunction(self): assert self.epanetClass.getNodeDemandPatternNameID()[1][junction_index - 1] == demand_pattern_id, err_msg def test_addNodeJunctionDemand(self): - self.epanetClass = epanet('ky10.inp') + self.epanetClass = epanet('ky10.inp', ph=False) self.epanetClass.addNodeJunctionDemand([1, 2], [100, 110], ['1', '2'], ['new demand1', 'new demand2']) assert self.epanetClass.getNodeJunctionDemandName()[2][0:2] == ['new demand1', 'new demand2'], \ @@ -238,7 +238,7 @@ def setUp(self): """Call before every test case.""" # Create EPANET object using the INP file inp_name = 'Net1.inp' - self.epanetClass = epanet(inp_name) + self.epanetClass = epanet(inp_name, ph=False) def tearDown(self): """Call after every test case.""" @@ -251,7 +251,7 @@ def test_deleteControls(self): def test_deleteCurve(self): # Test 1 - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) id_curve = d.getCurveNameID(1) # Retrieves the ID of the 1st curve d.deleteCurve(id_curve) # Deletes a curve given its ID self.assertEqual(d.getCurveNameID(), ['CURVE-1', 'CURVE-2'], 'Curve not deleted') @@ -259,7 +259,6 @@ def test_deleteCurve(self): index = 1 d.deleteCurve(index) # Deletes a curve given its index self.assertEqual(d.getCurveNameID(), ['CURVE-2'], 'Curve not deleted') - d.unload() def test_deleteLink(self): err_msg = 'Link not deleted' @@ -333,37 +332,34 @@ def test_deletePattern(self): self.epanetClass.deletePattern(id_pat) # Deletes the 1st pattern given its ID self.assertEqual(self.epanetClass.getPatternNameID(), [], err_msg) # Test 2 - self.epanetClass = epanet('Net1.inp') + self.epanetClass = epanet('Net1.inp', ph=False) index = 1 self.epanetClass.deletePattern(index) # Deletes the 1st pattern given its index self.assertEqual(self.epanetClass.getPatternNameID(), [], err_msg) def test_deletePatternsAll(self): err_msg = 'All Patterns not deleted' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) d.deletePatternsAll() # Deletes all the patterns self.assertEqual(d.getPatternNameID(), [], err_msg) - d.unload() def test_deleteRules(self): err_msg = 'Rule not deleted' # Test 1 - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) d.deleteRules() # Deletes all the rule-based control self.assertEqual(d.getRuleCount(), 0, err_msg) d.unload() # Test 2 - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) rule_id_1 = d.getRuleID(1) d.deleteRules(1) # Deletes the 1st rule-based control self.assertNotEqual(d.getRuleID(1), rule_id_1, err_msg) d.unload() # Test 3 - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) d.deleteRules([1, 2, 3]) # Deletes the 1st to 3rd rule-based control self.assertEqual(d.getRuleCount(), 1, err_msg) - d.unload() - class GetTest(unittest.TestCase): @@ -371,7 +367,7 @@ def setUp(self): """Call before every test case.""" # Create EPANET object using the INP file inp_name = 'Net1.inp' - self.epanetClass = epanet(inp_name) + self.epanetClass = epanet(inp_name, ph=False) def tearDown(self): """Call after every test case.""" @@ -468,7 +464,7 @@ def test_getComputedHydraulicTimeSeries(self): [125.96844576, 117.46948079, 115.03090241, 116.68717363, 115.74356881, 116.7866562, 118.76214431, 113.93079598, 108.84261138, 0., 50.00371454]]), - err_msg='Wrong Pressure output') + err_msg='Wrong Pressure output', decimal=4) np.testing.assert_array_almost_equal( data.Velocity, @@ -580,7 +576,7 @@ def test_getComputedHydraulicTimeSeries(self): 3.45560109e-01, 4.69014194e-01, 9.98856937e-01, 1.99197922e+00, 5.22476018e-01, 1.79906568e-01, 9.02098360e-01, 6.65702031e-01, 0.00000000e+00]]), - err_msg='Wrong velocity output') + err_msg='Wrong velocity output', decimal=4) def test_getComputedQualityTimeSeries(self): np.testing.assert_array_almost_equal( @@ -618,12 +614,11 @@ def test_getControls(self): 'Control': 'LINK 9 OPEN IF NODE 2 BELOW 110.0'}) def test_getCurveComment(self): - d = epanet('Net3.inp') + d = epanet('Net3.inp', ph=False) self.assertEqual(d.getCurveComment([1, 2]), ['PUMP: Pump Curve for Pump 10 (Lake Source)', 'PUMP: Pump Curve for Pump 335 (River Source)'], 'Wrong curve comment output') - d.unload() def test_getCounts(self): self.maxDiff = None @@ -635,7 +630,7 @@ def test_getCounts(self): def test_getCurvesData(self): """ ---getCurveIndex--- """ - d = epanet('Net3.inp') + d = epanet('Net3.inp', ph=False) err_msg = 'Wrong curve index' # Test 1 curve_id = d.getCurveNameID(1) @@ -646,7 +641,7 @@ def test_getCurvesData(self): d.unload() """ ---getCurveLengths--- """ - d = epanet('Richmond_standard.inp') + d = epanet('Richmond_standard.inp', ph=False) err_msg = 'Wrong curve lengths' # Test 3 self.assertEqual(d.getCurveLengths(list(range(1, 10))), [8, 6, 10, 9, 10, 10, 7, 9, 6], err_msg) @@ -666,7 +661,7 @@ def test_getCurvesData(self): # Test 7 self.assertEqual(curves_info.CurveNvalue[0], 8, err_msg) # Test 8 - self.assertEqual(curves_info.CurveXvalue[1], [0.0, 2.78, 5.56, 8.53, 11.11, 13.89], err_msg) + np.testing.assert_array_almost_equal(curves_info.CurveXvalue[1], [0.0, 2.78, 5.56, 8.53, 11.11, 13.89], decimal=2) # Test 9 self.assertEqual(curves_info.CurveYvalue[1], [88.0, 87.0, 84.0, 76.0, 63.0, 47.0], err_msg) @@ -693,11 +688,9 @@ def test_getCurvesData(self): point_index = 1 np.testing.assert_array_almost_equal(d.getCurveValue(curve_index, point_index), np.array([0., 38.]), err_msg=err_msg) - d.unload() - def test_getDemandModel(self): self.assertDictEqual(self.epanetClass.getDemandModel().to_dict(), - {'DemandModelCode': 0, 'DemandModelPmin': 0.0, 'DemandModelPreq': 0.1, + {'DemandModelCode': 0, 'DemandModelPmin': 0.0, 'DemandModelPreq': 0.10000000149011612, 'DemandModelPexp': 0.5, 'DemandModelType': 'DDA'}, 'Wrong demand model data') @@ -760,7 +753,7 @@ def test_getLinkPumpData(self): """ ---getLinkPumpECost--- """ err_msg = 'Wrong Pump ECost' # Test 3 - d = epanet('Richmond_standard.inp') + d = epanet('Richmond_standard.inp', ph=False) self.assertEqual(list(d.getLinkPumpECost()), [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], err_msg) """ ---getLinkPumpECurve--- """ @@ -793,21 +786,22 @@ def test_getLinkPumpData(self): initial_setting = 1.2 power = 10 pattern_index = 1 - pump_index = self.epanetClass.addLinkPump(pump_id, from_node, to_node, initial_status, initial_setting, power, + pump_index = d.addLinkPump(pump_id, from_node, to_node, initial_status, initial_setting, power, pattern_index) err_msg = 'Wrong Pump Pattern Index' # Test 8 - self.assertEqual(list(self.epanetClass.getLinkPumpPatternIndex()), [0, 1], err_msg) + self.assertEqual(list(d.getLinkPumpPatternIndex()), [0, 0, 0, 0, 0, 0, 0, 1], err_msg) """ ---getLinkPumpPatternNameID--- """ err_msg = 'Wrong Pump Pattern IDs' # Test 9 - self.assertEqual(list(self.epanetClass.getLinkPumpPatternNameID()), ['', '1'], err_msg) + self.assertEqual(list(d.getLinkPumpPatternNameID()), + ['', '', '', '', '', '', '', 'Fac_1010'], err_msg) """ ---getLinkPumpPower--- """ err_msg = 'Wrong Pump Power' # Test 10 - self.assertEqual(self.epanetClass.getLinkPumpPower(pump_index), 10, err_msg) + self.assertEqual(d.getLinkPumpPower(pump_index), 10, err_msg) # """ ---getLinkPumpSwitches--- """ # err_msg = 'Wrong Pump Switches' @@ -817,19 +811,19 @@ def test_getLinkPumpData(self): """ ---getLinkPumpType--- """ err_msg = 'Wrong Pump Type' # Test 12 - self.assertEqual(d.getLinkPumpType(), ['CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM'], + self.assertEqual(d.getLinkPumpType(), ['CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', 'CUSTOM', + 'CUSTOM', 'CONSTANT_HORSEPOWER'], err_msg) """ ---getLinkPumpTypeCode--- """ err_msg = 'Wrong Pump Type Code' d.unload() # Test 13 - d = epanet('Richmond_skeleton.inp') + d = epanet('Richmond_skeleton.inp', ph=False) self.assertEqual(d.getLinkPumpTypeCode(), [2, 2, 2, 2, 2, 2, 2], err_msg) self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') + self.epanetClass = epanet('Net1.inp', ph=False) self.assertEqual(self.epanetClass.getLinkPumpTypeCode(), [1], err_msg) - d.unload() def test_getLinksInfo(self): # Desired data @@ -871,7 +865,7 @@ def test_getLinksInfo(self): 'Wrong NodesConnectingLinksIndex output') def test_getLinkVertices(self): - d = epanet('ky10.inp') + d = epanet('ky10.inp', ph=False) l_vertices = d.getLinkVertices() vert_link_2 = [5774062.57, 5774072.58, 5774084.86, 5774143.46, 5774181.97, 5774256.77, 5774331.86, 5774408.93, 5774481.77, 5774548.49, 5774714.61, 5774660.84, 5774565.26] @@ -879,7 +873,6 @@ def test_getLinkVertices(self): self.assertEqual(len(l_vertices['x']), d.getLinkCount(), 'Wrong vertices list length ') self.assertEqual(len(d.getLinkVerticesCount()), d.getLinkCount(), 'Wrong vertices count') self.assertEqual(d.getLinkVerticesCount([1, 2, 3]), [5, 13, 28], 'Wrong vertices for the first 3 links') - d.unload() def test_getLinkIndex_LinkNodesIndex(self): indices = self.epanetClass.getLinkIndex() @@ -888,7 +881,7 @@ def test_getLinkIndex_LinkNodesIndex(self): self.assertEqual(l_n_indices.tolist(), [[1, 2], [2, 3], [3, 4]], 'Wrong link nodes indices') def test_getLinkPipe_Pump_Valve(self): - d = epanet('Net3.inp') + d = epanet('Net3.inp', ph=False) # Pipe pipe_indices = d.getLinkPipeIndex() self.assertEqual(pipe_indices, list(range(1, 118)), 'Wrong pipe indices') @@ -901,12 +894,11 @@ def test_getLinkPipe_Pump_Valve(self): self.assertEqual(pump_ids, ['10', '335'], 'Wrong pump IDs') d.unload() # Valve - d = epanet('ky10.inp') + d = epanet('ky10.inp', ph=False) valve_indices = list(d.getLinkValveIndex()) self.assertEqual(valve_indices, [1057, 1058, 1059, 1060, 1061], 'Wrong valve indices') valve_ids = d.getLinkValveNameID([1, 2, 3]) self.assertEqual(valve_ids, ['~@RV-1', '~@RV-2', '~@RV-3'], 'Wrong valve IDs') - d.unload() def test_getNodeInfo(self): n_info = self.epanetClass.getNodesInfo() @@ -963,10 +955,10 @@ def testDemandsInfo(self): -0.0012177492556971789, -0.0012291126064630734, -0.0012496099800993576, -0.0011990998540248189, -0.0011465764024330798, 0.0, 0.0] - self.assertEqual(list(actual_def), desired_dem_def, 'Wrong Demand Deficit Output') + np.testing.assert_array_almost_equal(list(actual_def), desired_dem_def, decimal=5) """ ---getNodeDemandPatternIndex--- """ - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) self.assertEqual(len(d.getNodeDemandPatternIndex()), 2, 'Wrong Node Demand Pattern Dict length') self.assertEqual(d.getNodeDemandPatternIndex()[2][120:122], [2, 2], 'Wrong Node Demand Pattern Index Output') @@ -974,7 +966,6 @@ def testDemandsInfo(self): self.assertEqual(len(d.getNodeDemandPatternNameID()), 2, 'Wrong Node Demand Pattern Dict length') self.assertEqual(d.getNodeDemandPatternNameID()[2][120:122], ['PATTERN-1', 'PATTERN-1'], 'Wrong Node Demand Pattern ID Output') - d.unload() def test_getNodeInitialQuality(self): desired_init_quality = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0] @@ -983,36 +974,35 @@ def test_getNodeInitialQuality(self): def test_getNodeJunctionData(self): """ ---getNodeJunctionDemandIndex--- """ - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) err_msg = 'Wrong Junction Demand Index output' self.assertEqual(d.getNodeJunctionDemandIndex(1, ''), 1, err_msg) self.assertEqual(d.getNodeJunctionDemandIndex([1, 2, 3]), [[1, 1, 1], [1, 1, 1]], err_msg) - d.unload() """ ---getNodeJunctionDemandName--- """ err_msg = 'Wrong Junction Demand Name ID output' - self.assertDictEqual(self.epanetClass.getNodeJunctionDemandName(), {1: ['', '', '', '', '', '', '', '', '']}, + d = epanet("Net1.inp", ph=False) + self.assertDictEqual(d.getNodeJunctionDemandName(), {1: ['', '', '', '', '', '', '', '', '']}, err_msg) """ ---getNodeJunctionIndex--- """ err_msg = 'Wrong Junction Index output' - self.assertEqual(self.epanetClass.getNodeJunctionIndex(), [1, 2, 3, 4, 5, 6, 7, 8, 9], err_msg) + self.assertEqual(d.getNodeJunctionIndex(), [1, 2, 3, 4, 5, 6, 7, 8, 9], err_msg) """ ---getNodeJunctionNameID--- """ err_msg = 'Wrong Junction Name ID output' - self.assertEqual(self.epanetClass.getNodeJunctionNameID(), + self.assertEqual(d.getNodeJunctionNameID(), ['10', '11', '12', '13', '21', '22', '23', '31', '32'], err_msg) def test_getNodeReservoirIndex_ID(self): """ ---getNodeReservoirIndex--- """ - d = epanet('ky9.inp') + d = epanet('ky9.inp', ph=False) self.assertEqual(d.getNodeReservoirIndex(), [1243, 1244, 1245, 1246], 'Wrong Node Reservoir Index Output') self.assertEqual(d.getNodeReservoirIndex([1, 2, 3]), [1243, 1244, 1245], 'Wrong Node Reservoir Index Output') """ ---getNodeReservoirNameID--- """ self.assertEqual(d.getNodeReservoirNameID(), ['R-1', 'R-2', 'R-3', 'R-4'], 'Wrong Node Reservoir ID Output') self.assertEqual(d.getNodeReservoirNameID([1, 2, 3]), ['R-1', 'R-2', 'R-3'], 'Wrong Node Reservoir ID Output') - d.unload() def test_getNodeConnectingLinksIndex_ID(self): """ ---getNodesConnectingLinksID--- """ @@ -1044,11 +1034,11 @@ def test_getNodeTankData(self): np.testing.assert_array_almost_equal(t_data['Maximum_Water_Level'], desired_tdata['Maximum_Water_Level']) np.testing.assert_array_almost_equal(t_data['Diameter'], desired_tdata['Diameter']) np.testing.assert_array_almost_equal(t_data['Minimum_Water_Volume'], desired_tdata['Minimum_Water_Volume'], - decimal=3) + decimal=1) np.testing.assert_array_almost_equal(t_data['Volume_Curve_Index'], desired_tdata['Volume_Curve_Index']) # ky10 - d = epanet('ky10.inp') + d = epanet('ky10.inp', ph=False) err_msg = 'Error in Tank Data' t_data = d.getNodeTankData().to_dict() desired_tdata = {'Index': [923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935], @@ -1078,7 +1068,7 @@ def test_getNodeTankData(self): self.assertEqual(d.getNodeTankNameID(), ['T-1', 'T-10', 'T-11', 'T-12', 'T-13', 'T-2', 'T-3', 'T-4', 'T-5', 'T-6', 'T-7', 'T-8', 'T-9'], err_msg) - np.testing.assert_array_almost_equal(t_data['Elevation'], desired_tdata['Elevation'], err_msg=err_msg) + np.testing.assert_array_almost_equal(t_data['Elevation'], desired_tdata['Elevation'], err_msg=err_msg, decimal=4) np.testing.assert_array_almost_equal(t_data['Initial_Level'], desired_tdata['Initial_Level'], err_msg=err_msg, decimal=3) np.testing.assert_array_almost_equal(t_data['Minimum_Water_Level'], desired_tdata['Minimum_Water_Level'], @@ -1090,10 +1080,9 @@ def test_getNodeTankData(self): desired_tdata['Minimum_Water_Volume'] / 1000, err_msg=err_msg, decimal=3) np.testing.assert_array_almost_equal(t_data['Volume_Curve_Index'], desired_tdata['Volume_Curve_Index'], err_msg=err_msg, decimal=3) - d.unload() def test_getnodeTankMix(self): - d = epanet('ky10.inp') + d = epanet('ky10.inp', ph=False) """ ---getNodeTankMixingFraction--- """ actual = list(d.getNodeTankMixingFraction()) @@ -1119,7 +1108,6 @@ def test_getnodeTankMix(self): 193012.038532]) np.testing.assert_array_almost_equal(actual, desired, err_msg='Wrong Node Tank Mix Zone Volume Output', decimal=1) - d.unload() def test_getNodeType(self): """ ---getNodeType--- """ @@ -1134,8 +1122,8 @@ def test_getNodeType(self): self.assertEqual(self.epanetClass.getNodeTypeIndex([10, 11]), [1, 2], 'Wrong Node Type Index Output') def test_getOptions(self): - d = epanet('BWSN_Network_1.inp') - self.assertEqual(d.getOptionsAccuracyValue(), 0.005, 'Wrong Options Accuracy Value Output') + d = epanet('BWSN_Network_1.inp', ph=False) + self.assertEqual(d.getOptionsAccuracyValue(), 0.004999999888241291, 'Wrong Options Accuracy Value Output') self.assertEqual(d.getOptionsCheckFrequency(), 2.0, 'Wrong Options Check Frequency Output') self.assertEqual(d.getOptionsDampLimit(), 0.0, 'Wrong Options Damping Limit Output') self.assertEqual(d.getOptionsDemandCharge(), 0.0, 'Wrong Options Demand Charge Output') @@ -1153,15 +1141,14 @@ def test_getOptions(self): self.assertEqual(d.getOptionsPatternDemandMultiplier(), 1.0, 'Wrong Options Pattern Demand Multiplier Output') self.assertEqual(d.getOptionsPipeBulkReactionOrder(), 1, 'Wrong Options Pipe Bulk Reaction Order Output') self.assertEqual(d.getOptionsPipeWallReactionOrder(), 1, 'Wrong Options Pipe Wall Reaction Order Output') - self.assertEqual(d.getOptionsQualityTolerance(), 0.01, 'Wrong Options Quality Tolerance Output') + self.assertEqual(d.getOptionsQualityTolerance(), 0.009999999776482582, 'Wrong Options Quality Tolerance Output') self.assertEqual(d.getOptionsSpecificDiffusivity(), 100.0, 'Wrong Options Specific Diffusivity Output') self.assertEqual(d.getOptionsSpecificGravity(), 1.0, 'Wrong Options Specific Gravity Output') self.assertEqual(d.getOptionsSpecificViscosity(), 1.0, 'Wrong Options Specific Viscosity Output') self.assertEqual(d.getOptionsTankBulkReactionOrder(), 1, 'Wrong Options Tank Bulk Reaction Order Output') - d.unload() def test_getPattern(self): - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) """ ---getPattern--- """ desired_pattern = np.array([[1.560e+00, 1.360e+00, 1.170e+00, 1.130e+00, 1.080e+00, 1.040e+00, @@ -1229,12 +1216,12 @@ def test_getPattern(self): 4.421e+02, 2.342e+02, 2.630e+01, 4.720e+01, 6.800e+01, 3.522e+02, 6.364e+02, 3.312e+02, 2.600e+01, 2.610e+01, 2.610e+01, 2.247e+02]]) actual_pattern = d.getPattern() - np.testing.assert_array_almost_equal(actual_pattern, desired_pattern, err_msg='Wrong Patterns Output') + np.testing.assert_array_almost_equal(actual_pattern, desired_pattern, err_msg='Wrong Patterns Output', decimal=4) """ ---getPatternAverageValue--- """ desired_pat_avg_val = [0.8856250000000001, 33.333333333333336, 0.967291666666667, 209.6072916666666] actual_pat_avg_val = d.getPatternAverageValue() - self.assertEqual(desired_pat_avg_val, actual_pat_avg_val, 'Wrong Patterns Average Value Output') + np.testing.assert_array_almost_equal(desired_pat_avg_val, actual_pat_avg_val, decimal=4) """ ---getPatternComment--- """ desired_comment = ['', '', '', ''] @@ -1253,8 +1240,7 @@ def test_getPattern(self): self.assertEqual(actual_pat_id, desired_pat_id, 'Wrong Pattern ID Output') """ ---getPatternValue--- """ - self.assertEqual(d.getPatternValue(1, 5), 1.08, 'Wrong Pattern Value Output') - d.unload() + self.assertEqual(d.getPatternValue(1, 5), 1.0800000429153442, 'Wrong Pattern Value Output') def test_getQualityInfo(self): desired_quality_info_dict = {'QualityCode': 1, 'QualityChemName': 'Chlorine', 'QualityChemUnits': 'mg/L', @@ -1263,7 +1249,7 @@ def test_getQualityInfo(self): self.assertDictEqual(actual_quality_info_dict, desired_quality_info_dict, 'Wrong Quality Info Output') def test_getRuleInfo(self): - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) """ ---getRuleID--- """ self.assertEqual(d.getRuleID(), ['RULE-0', 'RULE-1', 'RULE-3', 'RULE-4'], 'Wrong Rule ID Output') @@ -1283,7 +1269,6 @@ def test_getRuleInfo(self): ['THEN PUMP PUMP-172 STATUS IS CLOSED'], [], 'PRIORITY 1.0']} actual_rule = d.getRules()[1] self.assertDictEqual(actual_rule, desired_rule, 'Wrong Rule Output') - d.unload() def test_getTime(self): self.assertEqual(self.epanetClass.getTimeSimulationDuration(), 86400, 'Wrong Simulation Duration Output') @@ -1295,10 +1280,10 @@ def test_getTime(self): self.assertEqual(self.epanetClass.getTimeReportingStart(), 0, 'Wrong Time Output') self.assertEqual(self.epanetClass.getTimeRuleControlStep(), 360, 'Wrong Time Reporting Start Output') self.assertEqual(self.epanetClass.getTimeStatisticsType(), 'NONE', 'Wrong Time Statistics Type Output') - self.assertEqual(self.epanetClass.getTimeReportingPeriods(), 0, 'Wrong Time Output') + self.assertEqual(self.epanetClass.getTimeReportingPeriods(), 25, 'Wrong Time Output') self.assertEqual(self.epanetClass.getTimeStartTime(), 0, 'Wrong Reporting Periods Output') - self.assertEqual(self.epanetClass.getTimeHTime(), 0, 'Wrong hydraulic solution Time Output') - self.assertEqual(self.epanetClass.getTimeQTime(), 0, 'Wrong quality solution Time Output') + self.assertEqual(self.epanetClass.getTimeHTime(), 86400, 'Wrong hydraulic solution Time Output') + self.assertEqual(self.epanetClass.getTimeQTime(), 86400, 'Wrong quality solution Time Output') self.assertEqual(self.epanetClass.getTimeHaltFlag(), 0, 'Wrong Halt Flag Time Output') self.assertEqual(self.epanetClass.getTimeNextEvent(), 3600, 'Wrong Time Next Event Output') self.assertEqual(self.epanetClass.getTimeNextEventTank(), 0, 'Wrong Time Next Event Tank Output') @@ -1310,7 +1295,7 @@ def setUp(self): """Call before every test case.""" # Create EPANET object using the INP file inp_name = 'Net1.inp' - self.epanetClass = epanet(inp_name) + self.epanetClass = epanet(inp_name, ph=False) def tearDown(self): """Call after every test case.""" @@ -1338,7 +1323,7 @@ def test_setControls(self): def test_setCurve(self): """ ---setCurve--- """ - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) curve_index = 1 x_y_1 = [0, 730] x_y_2 = [1000, 500] @@ -1363,7 +1348,7 @@ def test_setCurve(self): d.unload() """ ---setCurveValue--- """ - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) err_msg = 'Wrong Curve Value Output' curve_index = 1 curve_point = 1 @@ -1371,7 +1356,6 @@ def test_setCurve(self): d.setCurveValue(curve_index, curve_point, x_y_values) self.assertAlmostEqual(d.getCurvesInfo().CurveXvalue[curve_index - 1][0], x_y_values[0], err_msg) self.assertEqual(d.getCurvesInfo().CurveYvalue[curve_index - 1][0], x_y_values[1], err_msg) - d.unload() def test_setDemandModel(self): model_type = 'PDA' @@ -1379,7 +1363,7 @@ def test_setDemandModel(self): preq = 0.1 pexp = 0.5 self.epanetClass.setDemandModel(model_type, pmin, preq, pexp) - desired = {'DemandModelCode': 1, 'DemandModelPmin': 0.0, 'DemandModelPreq': 0.1, + desired = {'DemandModelCode': 1, 'DemandModelPmin': 0.0, 'DemandModelPreq': 0.10000000149011612, 'DemandModelPexp': 0.5, 'DemandModelType': 'PDA'} actual = self.epanetClass.getDemandModel().to_dict() self.assertDictEqual(actual, desired, 'Wrong Set Demand Model Output') @@ -1481,7 +1465,7 @@ def test_setLinkInitial_Status_Setting(self): def test_setLinkLength(self): err_msg = 'Error setting Link Length' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 index_pipe = 1 length_pipe = 100 @@ -1492,8 +1476,7 @@ def test_setLinkLength(self): lengths = d.getLinkLength() lengths_new = [i * 1.5 for i in lengths] d.setLinkLength(lengths_new) - self.assertEqual(list(d.getLinkLength()), lengths_new, err_msg) - d.unload() + np.testing.assert_array_almost_equal(list(d.getLinkLength()), lengths_new, decimal=2) def test_setLinkMinorLossCoefficient(self): err_msg = 'Error setting Link Minor Loss Coefficient' @@ -1509,11 +1492,12 @@ def test_setLinkMinorLossCoefficient(self): self.epanetClass.setLinkMinorLossCoeff(coefficients_new) desired = np.array([105.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.]) - np.testing.assert_array_almost_equal(self.epanetClass.getLinkMinorLossCoeff(), desired, err_msg=err_msg) + np.testing.assert_array_almost_equal(self.epanetClass.getLinkMinorLossCoeff(), desired, err_msg=err_msg, + decimal=0) def test_setLinkNameID(self): err_msg = 'Error setting Link ID' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 index_pipe = 1 link_id = 'New_ID' @@ -1524,11 +1508,10 @@ def test_setLinkNameID(self): ids = ['1', '2', '3', '4'] d.setLinkNameID(ids) self.assertEqual(d.getLinkNameID([1, 2, 3, 4]), ['1', '2', '3', '4'], err_msg) - d.unload() def test_setLinkNodesIndex(self): err_msg = 'Error setting Link ID' - d = epanet('ky10.inp') + d = epanet('ky10.inp', ph=False) # Test 1 link_index = 1 start_node = 2 @@ -1542,7 +1525,6 @@ def test_setLinkNodesIndex(self): end_node = [3, 5] d.setLinkNodesIndex(link_index, start_node, end_node) self.assertEqual(d.getLinkNodesIndex(link_index).tolist(), [[2, 3], [4, 5]], err_msg) - d.unload() def test_setLinkPipeData(self): pipe_index = [1, 2] @@ -1561,7 +1543,7 @@ def test_setLinkPipeData(self): @staticmethod def test_setLinkPump(): - d = epanet('Net3_trace.inp') + d = epanet('Net3_trace.inp', ph=False) """ ---setLinkPumpECost--- """ err_msg = 'Error setting pump average energy price (E cost)' @@ -1637,7 +1619,6 @@ def test_setLinkPump(): pump_index = d.getLinkPumpIndex() d.setLinkPumpPower(pump_index, [10, 15]) np.testing.assert_array_almost_equal(d.getLinkPumpPower(), np.array([10., 15.]), err_msg=err_msg) - d.unload() def test_setLinkRoughnessCoefficient(self): err_msg = 'Error setting Link Roughness Coefficient' @@ -1748,7 +1729,7 @@ def test_setLinkWallReactionCoefficient(self): err_msg=err_msg) def test_setNodeBaseDemands(self): - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) err_msg = 'Error setting Node Base Demands' # Test 1 @@ -1769,7 +1750,7 @@ def test_setNodeBaseDemands(self): category_index = 2 demand = 25 d.setNodeBaseDemands(node_index, category_index, demand) - self.assertAlmostEqual(d.getNodeBaseDemands()[category_index][node_index - 1], demand, err_msg) + self.assertAlmostEqual(d.getNodeBaseDemands()[category_index][node_index - 1], demand) def test_setNodeComment(self): self.epanetClass.setNodeComment([1, 2], ['This is a node', 'Test comm']) @@ -1803,7 +1784,7 @@ def test_setNodeCoordinates(self): self.assertDictEqual(y_values_new, desired_new_y, err_msg) def test_setNodeDemandPatternIndex(self): - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) err_msg = 'Error setting Node Demand Pattern Index' # Test 1 @@ -1829,7 +1810,6 @@ def test_setNodeDemandPatternIndex(self): pattern_indices = [1, 3, 2, 4, 2] d.setNodeDemandPatternIndex(node_index, category_index, pattern_indices) self.assertEqual(pat_dems, pattern_indices, err_msg) - d.unload() def test_setNodeElevations(self): err_msg = 'Error setting node elevations' @@ -1929,7 +1909,7 @@ def test_setNodeSourceType(self): def test_setNodeTankBulkReactionCoefficient(self): err_msg = 'Error setting node Tank Bulk Reaction Coefficient' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 tank_index = d.getNodeTankIndex() @@ -1940,12 +1920,11 @@ def test_setNodeTankBulkReactionCoefficient(self): tank_index = d.getNodeTankIndex([1, 2]) d.setNodeTankBulkReactionCoeff(tank_index, [-0.5, 0]) self.assertEqual(list(d.getNodeTankBulkReactionCoeff()), [-0.5, 0], err_msg) - d.unload() @staticmethod def test_setNodeTankCanOverFlow(): err_msg = 'Error setting node Tank Can Overflow' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 d.setNodeTankCanOverFlow(1) @@ -1958,11 +1937,10 @@ def test_setNodeTankCanOverFlow(): # Test 3 d.setNodeTankCanOverFlow(1, 0) np.testing.assert_array_almost_equal(d.getNodeTankCanOverFlow(), np.array([0., 0.]), err_msg=err_msg) - d.unload() @staticmethod def test_setNodeTankData(): - d = epanet('Net3_trace.inp') + d = epanet('Net3_trace.inp', ph=False) tank_index = [1, 2] elev = [100, 105] init_level = [13, 13.5] @@ -1984,11 +1962,10 @@ def test_setNodeTankData(): np.testing.assert_array_almost_equal(t_data.Minimum_Water_Volume, min_vol, err_msg='Error Setting Node Tank Min Water Volume') np.testing.assert_array_almost_equal(t_data.Elevation, elev, err_msg='Error Setting Node Tank Elevation') - d.unload() def test_setNodeTankDiameter(self): err_msg = 'Error setting Node Tank Diameter' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 d.setNodeTankDiameter(120) @@ -2005,7 +1982,7 @@ def test_setNodeTankDiameter(self): @staticmethod def test_setTankInitialLevel(): err_msg = 'Error setting Node Tank Initial Level' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) # Test 1 tank_index = d.getNodeTankIndex() @@ -2020,7 +1997,7 @@ def test_setTankInitialLevel(): @staticmethod def test_setNodeTankMaximumWaterLevel(): err_msg = 'Error setting Node Tank Max Water Level' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) tank_index = d.getNodeTankIndex() d.setNodeTankMaximumWaterLevel(tank_index, 30) np.testing.assert_array_almost_equal(d.getNodeTankMaximumWaterLevel(), np.array([30., 30.]), err_msg=err_msg) @@ -2028,7 +2005,7 @@ def test_setNodeTankMaximumWaterLevel(): @staticmethod def test_setNodeTankMinimumWaterLevel(): err_msg = 'Error setting Node Tank Min Water Level' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) tank_index = d.getNodeTankIndex() d.setNodeTankMinimumWaterLevel(tank_index, [5, 15]) d.getNodeTankMinimumWaterLevel(), @@ -2037,21 +2014,21 @@ def test_setNodeTankMinimumWaterLevel(): @staticmethod def test_setNodeTankMinimumWaterVolume(): err_msg = 'Error setting Node Tank Min Water Volume' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) d.setNodeTankMinimumWaterVolume([1500, 2000]) np.testing.assert_array_almost_equal(d.getNodeTankMinimumWaterVolume(), np.array([1500, 2000]), err_msg=err_msg) @staticmethod def test_setNodeTankMixingFraction(): err_msg = 'Error setting Node Tank Min Water Volume' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) tank_index = d.getNodeTankIndex() d.setNodeTankMixingFraction(tank_index, [1, 0]) np.testing.assert_array_almost_equal(d.getNodeTankMixingFraction(), np.array([1, 0]), err_msg=err_msg) def test_getNodeTankMixingModelType(self): err_msg = 'Error setting Node Tank Mixing Model Type' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) tank_index = d.getNodeTankIndex() d.setNodeTankMixingModelType(tank_index, ['MIX2', 'LIFO']) self.assertEqual(d.getNodeTankMixingModelType(), ['MIX2', 'LIFO'], err_msg) @@ -2067,14 +2044,14 @@ def test_setNodeType(self): """ ---setNodeTypeTank--- """ self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') + self.epanetClass = epanet('Net1.inp', ph=False) index = self.epanetClass.setNodeTypeTank('13') self.assertEqual(self.epanetClass.getNodeType(index), 'TANK', 'Error setting node type to junction') def test_setOptions(self): err_msg = 'Error setting Options' self.epanetClass.setOptionsAccuracyValue(0.001) - self.assertEqual(self.epanetClass.getOptionsAccuracyValue(), 0.001, err_msg) + self.assertEqual(self.epanetClass.getOptionsAccuracyValue(), 0.0010000000474974513, err_msg) self.epanetClass.setOptionsCheckFrequency(2) self.assertEqual(self.epanetClass.getOptionsCheckFrequency(), 2, err_msg) self.epanetClass.setOptionsDampLimit(0) @@ -2110,7 +2087,7 @@ def test_setOptions(self): self.epanetClass.setOptionsPipeWallReactionOrder(1) self.assertEqual(self.epanetClass.getOptionsPipeWallReactionOrder(), 1, err_msg) self.epanetClass.setOptionsQualityTolerance(0.01) - self.assertEqual(self.epanetClass.getOptionsQualityTolerance(), 0.01, err_msg) + self.assertEqual(self.epanetClass.getOptionsQualityTolerance(), 0.009999999776482582, err_msg) self.epanetClass.setOptionsSpecificDiffusivity(1) self.assertEqual(self.epanetClass.getOptionsSpecificDiffusivity(), 1, err_msg) self.epanetClass.setOptionsSpecificGravity(1) @@ -2157,16 +2134,15 @@ def test_setPattern(self): """ ---setPatternComment--- """ err_msg = 'Error setting pattern comment' - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) pattern_comment = ['1st PAT', '2nd PAT', '3rd PAT', "4rth PAT"] d.setPatternComment(pattern_comment) self.assertEqual(d.getPatternComment(), pattern_comment, err_msg) - d.unload() """ ---setPatternMatrix--- """ err_msg = 'Error setting pattern Matrix' self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') + self.epanetClass = epanet('Net1.inp', ph=False) pattern_id_1 = 'new_pattern_1' pattern_index_1 = self.epanetClass.addPattern(pattern_id_1) pattern_id_2 = 'new_pattern_2' @@ -2193,7 +2169,7 @@ def test_setPattern(self): """ ---setPatternValue--- """ err_msg = 'Error setting pattern Value' self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') + self.epanetClass = epanet('Net1.inp', ph=False) pattern_id = 'new_pattern' pattern_index = self.epanetClass.addPattern(pattern_id) pattern_time_step = 2 @@ -2202,14 +2178,14 @@ def test_setPattern(self): self.assertEqual(self.epanetClass.getPattern()[1][pattern_time_step - 1], pattern_factor, err_msg) def test_setRule(self): - d = epanet('BWSN_Network_1.inp') + d = epanet('BWSN_Network_1.inp', ph=False) """ ---setRulePremise--- """ err_msg = 'Error setting rule premise' # Test 1 rule_index = 1 premise_index = 1 - premise = 'IF SYSTEM CLOCKTIME >= 8 PM' + premise = 'IF SYSTEM CLOCKTIME >= 08:00 PM' d.setRulePremise(rule_index, premise_index, premise) self.assertEqual(d.getRules()[1]['Premises'][0], 'IF SYSTEM CLOCKTIME >= 08:00 PM UTC', err_msg) @@ -2237,45 +2213,43 @@ def test_setRule(self): self.assertEqual(d.getRules()[1]['Premises'][0], 'IF NODE TANK-131 LEVEL > 21.0', err_msg) """ ---setRules--- """ + d = epanet('Net1.inp', ph=False) err_msg = 'Error setting rules' rule = 'RULE RULE-1 \n IF NODE 2 LEVEL >= 140 \n THEN PIPE 10 STATUS IS CLOSED \n ' \ 'ELSE PIPE 10 STATUS IS OPEN \n PRIORITY 1' - self.epanetClass.addRules(rule) + d.addRules(rule) rule_index = 1 rule_new = 'IF NODE 2 LEVEL > 150 \n THEN PIPE 10 STATUS IS OPEN \n ELSE PIPE 11 STATUS IS OPEN \n PRIORITY 2' - self.epanetClass.setRules(rule_index, rule_new) + d.setRules(rule_index, rule_new) desired_rule = ['RULE RULE-1', ['IF NODE 2 LEVEL > 150.0'], ['THEN PIPE 10 STATUS IS OPEN'], ['ELSE PIPE 11 STATUS IS OPEN'], 'PRIORITY 2.0'] - self.assertEqual(self.epanetClass.getRules()[1]['Rule'], desired_rule, err_msg) + self.assertEqual(d.getRules()[1]['Rule'], desired_rule, err_msg) """ ---setRuleElseAction--- """ err_msg = 'Error setting rule else action' - self.epanetClass.addRules( + d.addRules( "RULE RULE-1 \n IF TANK 2 LEVEL >= 140 \n THEN PIPE 10 STATUS IS CLOSED \n " "ELSE PIPE 10 STATUS IS OPEN \n PRIORITY 1") # Adds a new rule - based control # rule = self.epanetClass.getRules(1) rule_index = 1 action_index = 1 else_action = 'ELSE PIPE 11 STATUS IS CLOSED' - self.epanetClass.setRuleElseAction(rule_index, action_index, else_action) - self.assertEqual(self.epanetClass.getRules()[1]['Else_Actions'][0], else_action, err_msg) + d.setRuleElseAction(rule_index, action_index, else_action) + self.assertEqual(d.getRules()[1]['Else_Actions'][0], else_action, err_msg) """ ---setRulePremiseStatus--- """ err_msg = 'Error setting rule premise status' - self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') - self.epanetClass.addRules( + d = epanet('Net1.inp', ph=False) + d.addRules( 'RULE RULE-1 \n IF LINK 110 STATUS = CLOSED \n THEN PUMP 9 STATUS IS CLOSED \n PRIORITY 1') - self.epanetClass.getRules(1) + d.getRules(1) rule_index = 1 premise_index = 1 status = 'OPEN' - self.epanetClass.setRulePremiseStatus(rule_index, premise_index, status) - self.assertEqual(self.epanetClass.getRules()[1]['Premises'][0], 'IF LINK 110 STATUS = OPEN', err_msg) + d.setRulePremiseStatus(rule_index, premise_index, status) + self.assertEqual(d.getRules()[1]['Premises'][0], 'IF LINK 110 STATUS = OPEN', err_msg) """ ---setRulePriority--- """ - self.epanetClass.unload() - self.epanetClass = epanet('Net1.inp') err_msg = 'Error setting rule priority' rule_index = 1 priority = 2 @@ -2284,15 +2258,15 @@ def test_setRule(self): """ ---setRuleThenAction--- """ err_msg = 'Error setting rule priority action' - self.epanetClass.addRules( + d.addRules( 'RULE RULE-1 \n IF TANK 2 LEVEL >= 140 \n THEN PIPE 10 STATUS IS CLOSED \n ' 'ELSE PIPE 10 STATUS IS OPEN \n PRIORITY 1') # Adds a new rule - based control # rule = self.epanetClass.getRules(1) rule_index = 1 action_index = 1 then_action = 'THEN PIPE 11 STATUS IS OPEN' - self.epanetClass.setRuleThenAction(rule_index, action_index, then_action) - self.assertEqual(self.epanetClass.getRules()[1]['Then_Actions'], ['THEN PIPE 11 STATUS IS OPEN'], err_msg) + d.setRuleThenAction(rule_index, action_index, then_action) + self.assertEqual(d.getRules()[1]['Then_Actions'], ['THEN PIPE 11 STATUS IS OPEN'], err_msg) def test_setTime(self): err_msg = 'Error setting time' @@ -2329,7 +2303,7 @@ class AnalysisTest(unittest.TestCase): @staticmethod def testStepByStepHydraulic(): - d = epanet('Net1.inp') + d = epanet('Net1.inp', ph=False) d.openHydraulicAnalysis() d.initializeHydraulicAnalysis() t_step, p, t_h, demand, head, flow, status, = 1, [], [], [], [], [], [] @@ -2347,65 +2321,64 @@ def testStepByStepHydraulic(): # Test Pressure err_msg = 'Error in Pressure Output' - desired_p_1 = np.array([128.58963612, 120.45028753, 118.34940585, 119.99139321, - 118.94074548, 120.07340709, 122.05444889, 117.14855347, - 112.0894993, 0., 53.32542596]) - np.testing.assert_array_almost_equal(p[1], desired_p_1, err_msg=err_msg) + desired_p_1 = np.array([128.589630, 120.450287, 118.349403, 119.991394, 118.940742, 120.073410, + 122.054451, 117.148552, 112.089500, 0.000000, 53.325424]) + np.testing.assert_array_almost_equal(p[1], desired_p_1, err_msg=err_msg, decimal=3) desired_p_10 = np.array([132.26981375, 124.63753647, 123.45427607, 124.71035299, 123.03261446, 124.59180141, 126.55864067, 120.71122109, 115.61661061, 0., 58.44725465]) - np.testing.assert_array_almost_equal(p[10], desired_p_10, err_msg=err_msg) + np.testing.assert_array_almost_equal(p[10], desired_p_10, err_msg=err_msg, decimal=4) desired_p_25 = np.array([124.92020828, 116.27777211, 113.2647933, 115.18812071, 114.76197096, 115.35222877, 117.34954606, 113.36596566, 108.22952342, 0., 48.2175138]) - np.testing.assert_array_almost_equal(p[25], desired_p_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(p[25], desired_p_25, err_msg=err_msg, decimal=5) # Test Actual Demand err_msg = 'Error in Actual Demand' desired_act_dem_0 = np.array([0., 150., 150., 100., 150., 200., 150., 100., 100., -1866.17582999, 766.17582999]) - np.testing.assert_array_almost_equal(demand[0], desired_act_dem_0, err_msg=err_msg) + np.testing.assert_array_almost_equal(demand[0], desired_act_dem_0, err_msg=err_msg, decimal=4) desired_act_dem_11 = np.array([0., 180., 180., 120., 180., 240., 180., 120., 120., -1774.30359304, 454.30359304]) - np.testing.assert_array_almost_equal(demand[11], desired_act_dem_11, err_msg=err_msg) + np.testing.assert_array_almost_equal(demand[11], desired_act_dem_11, err_msg=err_msg, decimal=4) desired_act_dem_20 = np.array([0., 60., 60., 40., 60., 80., 60., 40., 40., 0., -440.00076023]) - np.testing.assert_array_almost_equal(demand[20] / 1000, desired_act_dem_20 / 1000, err_msg=err_msg) + np.testing.assert_array_almost_equal(demand[20] / 1000, desired_act_dem_20 / 1000, err_msg=err_msg, decimal=4) # Test Hydraulic Head err_msg = 'Error in Node Hydraulic Head' desired_head_3 = np.array([1009.9247677, 991.57444459, 978.17030221, 976.10781146, 977.43523692, 975.88868908, 975.41587013, 972.04529101, 970.24584336, 800., 978.13799323]) - np.testing.assert_array_almost_equal(head[3], desired_head_3, err_msg=err_msg) + np.testing.assert_array_almost_equal(head[3], desired_head_3, err_msg=err_msg, decimal=4) desired_head_14 = np.array([986.31467071, 986.31467071, 987.84955266, 985.4428713, 983.41923666, 983.80636726, 983.68229481, 979.90330538, 979.01824775, 800., 987.98597249]) - np.testing.assert_array_almost_equal(head[14], desired_head_14, err_msg=err_msg) + np.testing.assert_array_almost_equal(head[14], desired_head_14, err_msg=err_msg, decimal=4) desired_head_25 = np.array([998.29958062, 978.35396286, 961.40039995, 960.83918927, 964.85569112, 961.21792931, 960.82747764, 961.63389259, 959.77965248, 800., 961.27974566]) - np.testing.assert_array_almost_equal(head[25], desired_head_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(head[25], desired_head_25, err_msg=err_msg, decimal=4) # Test Link Status err_msg = 'Error in Link Status' desired_status_0 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) - np.testing.assert_array_almost_equal(status[0], desired_status_0, err_msg=err_msg) + np.testing.assert_array_almost_equal(status[0], desired_status_0, err_msg=err_msg, decimal=4) desired_status_15 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]) - np.testing.assert_array_almost_equal(status[15], desired_status_15, err_msg=err_msg) + np.testing.assert_array_almost_equal(status[15], desired_status_15, err_msg=err_msg, decimal=4) desired_status_26 = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) - np.testing.assert_array_almost_equal(status[26], desired_status_26, err_msg=err_msg) + np.testing.assert_array_almost_equal(status[26], desired_status_26, err_msg=err_msg, decimal=4) # Test Link Flow err_msg = 'Error in Link Flow' @@ -2413,15 +2386,15 @@ def testStepByStepHydraulic(): 126.50961405, 42.05237255, -505.38318977, 490.56567082, 295.94394323, 53.49038595, 162.05237255, 77.94762745, 1825.38318977]) - np.testing.assert_array_almost_equal(flow[3], desired_flow_1, err_msg=err_msg) + np.testing.assert_array_almost_equal(flow[3], desired_flow_1, err_msg=err_msg, decimal=4) desired_flow_25 = np.array([1909.42463758, 1310.99431794, 85.91245886, 235.69131652, 114.08754114, 42.73900313, -1029.42463758, 478.43031965, 75.6572215, 5.91245886, 122.73900313, 37.26099687, 1909.42463758]) - np.testing.assert_array_almost_equal(flow[25], desired_flow_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(flow[25], desired_flow_25, err_msg=err_msg, decimal=4) def testStepByStepHydraulicQuality(self): - d = epanet('Net2.inp') + d = epanet('Net2.inp', ph=False) d.openHydraulicAnalysis() d.openQualityAnalysis() d.initializeHydraulicAnalysis(0) @@ -2456,16 +2429,16 @@ def testStepByStepHydraulicQuality(self): # Test Pressure err_msg = 'Error in Pressure Output' - desired_p_1 = np.array([113.44908691, 89.7622058, 106.82691104, 106.6386474, - 89.28836137, 77.5531041, 60.3874831, 82.05202764, - 51.44147544, 73.38562132, 48.80664238, 36.8438231, - 36.50653553, 40.6814559, 44.92037458, 62.27779634, - 49.254625, 83.91787864, 62.25761494, 53.6728296, - 62.33170387, 40.66680277, 27.32765269, 44.84070793, - 27.24073401, 70.56470052, 79.22932155, 79.22939519, - 70.56301264, 44.57029235, 79.58488909, 49.33250858, - 44.99947598, 79.22930683, 79.22931001, 25.02817602]) - np.testing.assert_array_almost_equal(pressure[1], desired_p_1, err_msg=err_msg) + desired_p_1 = np.array([113.449086, 89.76220, 106.8269, 106.63864, + 89.288361, 77.55310, 60.38748, 82.052027, + 51.441475, 73.385621, 48.80664, 36.84382, + 36.506535, 40.68145, 44.920374, 62.277796, + 49.2546, 83.917878, 62.257614, 53.67282, + 62.331703, 40.666802, 27.327652, 44.840707, + 27.240734, 70.564700, 79.229321, 79.229395, + 70.563012, 44.570292, 79.584889, 49.332508, + 44.999475, 79.229306, 79.229310, 25.028176]) + np.testing.assert_array_almost_equal(pressure[1], desired_p_1, err_msg=err_msg, decimal=4) desired_p_10 = np.array([104.60396813, 82.93896813, 100.26187843, 100.27019131, 82.94214413, 72.13623112, 57.0459412, 78.70869778, @@ -2476,7 +2449,7 @@ def testStepByStepHydraulicQuality(self): 28.47009352, 71.7703745, 80.42958211, 80.42994484, 71.76206051, 45.79006666, 79.04235247, 48.9280188, 44.59485824, 80.42950961, 80.42952527, 26.5365387]) - np.testing.assert_array_almost_equal(pressure[10], desired_p_10, err_msg=err_msg) + np.testing.assert_array_almost_equal(pressure[10], desired_p_10, err_msg=err_msg, decimal=4) desired_p_25 = np.array([112.30635933, 88.7727249, 105.85553093, 105.68501784, 88.33680483, 76.68003911, 59.6914576, 81.35595229, @@ -2487,7 +2460,7 @@ def testStepByStepHydraulicQuality(self): 26.88784804, 70.2111541, 78.87562417, 78.87570587, 70.20928145, 44.2171391, 79.15874975, 48.89351709, 44.56048092, 78.87560784, 78.87561137, 24.6866985]) - np.testing.assert_array_almost_equal(pressure[25], desired_p_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(pressure[25], desired_p_25, err_msg=err_msg, decimal=4) # Test Link Flow err_msg = 'Error in Link Flow' @@ -2501,7 +2474,7 @@ def testStepByStepHydraulicQuality(self): 353.5274, 34.92, 18.43, 10.67, 1.67010192, 2.91, 1.455, -21.34271259, 2.20989809, 2.91, 0.70010191, 0.97]) - np.testing.assert_array_almost_equal(flow[3], desired_flow_1, err_msg=err_msg) + np.testing.assert_array_almost_equal(flow[3], desired_flow_1, err_msg=err_msg, decimal=4) desired_flow_10 = np.array([-3.19163104e-07, -3.69432046e+01, 1.72632041e+01, -1.71767959e+01, -3.68567959e+01, -9.34800005e+01, -1.05780001e+02, 3.44400000e+01, @@ -2513,7 +2486,7 @@ def testStepByStepHydraulicQuality(self): -7.94038801e+02, 8.85600000e+01, 4.67400000e+01, 2.70600000e+01, 4.23551620e+00, 7.38000000e+00, 3.69000000e+00, -7.91086075e+00, 5.60448380e+00, 7.38000000e+00, 1.77551620e+00, 2.46000000e+00]) - np.testing.assert_array_almost_equal(flow[10], desired_flow_10, err_msg=err_msg) + np.testing.assert_array_almost_equal(flow[10], desired_flow_10, err_msg=err_msg, decimal=4) desired_flow_25 = np.array([638.848, 526.87340214, 103.17459786, 87.77459786, 78.97459786, 597.048, 591.548, 15.4, @@ -2525,7 +2498,7 @@ def testStepByStepHydraulicQuality(self): 283.79, 39.6, 20.9, 12.1, 1.89393001, 3.3, 1.65, -17.78819924, 2.50606999, 3.3, 0.79393001, 1.1]) - np.testing.assert_array_almost_equal(flow[25], desired_flow_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(flow[25], desired_flow_25, err_msg=err_msg, decimal=4) # Test Node Actual Quality err_msg = 'Error in Node Actual Quality ' @@ -2537,7 +2510,7 @@ def testStepByStepHydraulicQuality(self): 0.99234298, 0.99985533, 0.99699218, 0.99998949, 1.01354119, 0.99904712, 0.99995205, 0.99999525, 0.9998032, 0.9999915, 1.00073598]) - np.testing.assert_array_almost_equal(node_quality[5], desired_actual_quality_n_5, err_msg=err_msg) + np.testing.assert_array_almost_equal(node_quality[5], desired_actual_quality_n_5, err_msg=err_msg, decimal=4) desired_actual_quality_n_25 = np.array([0.15, 0.15, 0.13021117, 0.13025352, 0.14729473, 0.1471587, 0.13169433, 0.13385677, 0.1317173, 0.52638193, @@ -2547,7 +2520,7 @@ def testStepByStepHydraulicQuality(self): 0.92718994, 1.01683607, 0.92719291, 0.99951648, 0.92716929, 0.19758304, 1.03599597, 0.99983082, 1.00030477, 0.99949038, 0.92719247]) - np.testing.assert_array_almost_equal(node_quality[25], desired_actual_quality_n_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(node_quality[25], desired_actual_quality_n_25, err_msg=err_msg, decimal=4) desired_actual_quality_n_45 = np.array([0.09, 0.08927529, 0.08979756, 0.08926078, 0.08747952, 0.08717831, 0.08676482, 0.09010864, 0.08659873, 0.12272579, @@ -2558,7 +2531,7 @@ def testStepByStepHydraulicQuality(self): 0.69914026, 0.9270073, 1.00053611, 0.32030924, 1.00047879, 0.76376316]) np.testing.assert_array_almost_equal(node_quality[45] / 1000, desired_actual_quality_n_45 / 1000, - err_msg=err_msg) + err_msg=err_msg, decimal=4) # Test Link Actual Quality err_msg = 'Error in Link Actual Quality ' @@ -2570,7 +2543,7 @@ def testStepByStepHydraulicQuality(self): 1.0177895, 0.99711982, 1.0326732, 1.03327514, 1.02508339, 0.99405897, 0.99699218, 0.99985533, 0.99995205, 0.99999525, 0.99673462, 0.99974172, 0.99998949, 0.99999727, 0.9999915]) - np.testing.assert_array_almost_equal(link_quality[5], desired_actual_quality_l_5, err_msg=err_msg) + np.testing.assert_array_almost_equal(link_quality[5], desired_actual_quality_l_5, err_msg=err_msg, decimal=4) desired_actual_quality_l_25 = np.array([0.15, 0.14982569, 0.14433033, 0.13025352, 0.13072138, 0.1471587, 0.13343018, 0.35084865, 0.1317173, 0.57100102, @@ -2580,7 +2553,7 @@ def testStepByStepHydraulicQuality(self): 0.92684628, 0.92664191, 0.92693835, 0.92699844, 0.92716929, 0.92718994, 0.92719291, 0.8686534, 0.74306268, 1.00226608, 0.1455949, 0.75839028, 0.99895694, 0.9997757, 0.99955681]) - np.testing.assert_array_almost_equal(link_quality[25], desired_actual_quality_l_25, err_msg=err_msg) + np.testing.assert_array_almost_equal(link_quality[25], desired_actual_quality_l_25, err_msg=err_msg, decimal=4) # Test Link Velocity err_msg = 'Error in Link Velocity ' @@ -2731,7 +2704,7 @@ def testStepByStepHydraulicQuality(self): 3.09, 17.51, 17.51, 1.545, 1.545, 0., 1.03, 306.38459999]) np.testing.assert_array_almost_equal(actual_dem_sens_nodes[50], desired_act_dem_sen_50, err_msg=err_msg, - decimal=5) + decimal=4) # Test Node Actual Quality Sensing Nodes err_msg = 'Error in Node Actual Quality Sensing Nodes' @@ -2771,7 +2744,7 @@ def testStepByStepHydraulicQuality(self): # Test Node Mass Flow Rate err_msg = 'Error in Node Mass Flow Rate' - desired_act_dem_mass_flow_rate__2 = [18168918.949573442, None, None, None, None, None, None, None, None, + desired_act_dem_mass_flow_rate__2 = [18168918, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] @@ -2779,7 +2752,7 @@ def testStepByStepHydraulicQuality(self): @staticmethod def test_getComputedHydraulicTimeSeries(): - d = epanet('Net1.inp') + d = epanet('Net1.inp', ph=False) comp_vals = d.getComputedHydraulicTimeSeries() err_msg = 'Error in getComputedHydraulicTimeSeries output' d.unload() @@ -2867,7 +2840,7 @@ def test_getComputedHydraulicTimeSeries(): 150., 200., 150., 100., 100., -1892.24322665, 792.24322665]]) actual = comp_vals.Demand - np.testing.assert_array_almost_equal(actual, desired, err_msg=err_msg, decimal=5) + np.testing.assert_array_almost_equal(actual, desired, err_msg=err_msg, decimal=4) # Test Energy desired = np.array([[6.72482481e+00, 3.52704749e+00, 2.91862104e-02, 8.89394398e-02, @@ -2979,7 +2952,7 @@ def test_getComputedHydraulicTimeSeries(): 3.29103289e-02, 1.12232080e-03, 1.11456923e-01, 3.68674584e-02, 9.54579159e+01]]) actual = comp_vals.Energy - np.testing.assert_array_almost_equal(actual, desired, err_msg=err_msg, decimal=2) + np.testing.assert_array_almost_equal(actual, desired, err_msg=err_msg, decimal=4) # Test Energy desired = np.array([[1.86617583e+03, 1.23420718e+03, 1.29335135e+02, @@ -3744,7 +3717,7 @@ def test_getComputedHydraulicTimeSeries(): @staticmethod def test_getComputedQualityTimeSeries(): - d = epanet('Net1.inp') + d = epanet('Net1.inp', ph=False) comp_vals = d.getComputedQualityTimeSeries() d.unload() err_msg = 'Error in getComputedQualityTimeSeries output' @@ -3788,9 +3761,8 @@ def test_getComputedQualityTimeSeries(): @staticmethod def test_getComputedTimeSeries(): - d = epanet('Net1.inp') + d = epanet('Net1.inp', ph=False) comp_vals = d.getComputedTimeSeries() - d.unload() err_msg = 'Error in getComputedTimeSeries output' # Test LinkQuality @@ -3832,10 +3804,9 @@ def test_getComputedTimeSeries(): @staticmethod def test_getComputedTimeSeries_EN_Epanet(): - d = epanet('Net1.inp') + d = epanet('Net1.inp', ph=False) comp_vals = d.getComputedTimeSeries_ENepanet() err_msg = 'Error in getComputedTimeSeries_ENepanet output' - d.unload() # Test LinkQuality desired_0 = np.array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.75]) diff --git a/epyt/tests/net1_unit_test.py b/epyt/tests/net1_unit_test.py index bdbbb92..9cfda03 100644 --- a/epyt/tests/net1_unit_test.py +++ b/epyt/tests/net1_unit_test.py @@ -8,7 +8,7 @@ def setUp(self): """Call before every test case.""" # Create EPANET object using the INP file inp_name = 'Net1.inp' - self.epanetClass = epanet(inp_name) + self.epanetClass = epanet(inp_name, ph=False) def tearDown(self): """Call after every test case.""" diff --git a/epyt/tests/test_unit_MSX.py b/epyt/tests/test_unit_MSX.py index 4046cf6..18f8c3f 100644 --- a/epyt/tests/test_unit_MSX.py +++ b/epyt/tests/test_unit_MSX.py @@ -12,7 +12,7 @@ def setUp(self): # Create EPANET object using the INP file inpname = os.path.join(DIRNAME, 'msx-examples', 'Net3-NH2CL.inp') msxfile = os.path.join(DIRNAME, 'msx-examples', 'Net3-NH2CL.msx') - self.epanetClass = epanet(inpname, msx=True) + self.epanetClass = epanet(inpname) self.msxClass = self.epanetClass.loadMSXFile(msxfile) def tearDown(self): @@ -253,7 +253,7 @@ def test_MSXgetqual(self): self.msxClass.MSXclose() self.epanetClass.unload() inpname = os.path.join(DIRNAME, 'msx-examples', 'net2-cl2.inp') - self.epanetClass = epanet(inpname, msx=True) + self.epanetClass = epanet(inpname) file_path = os.path.join(DIRNAME, 'msx-examples', 'net2-cl2.msx') self.msxClass = self.epanetClass.loadMSXFile(file_path) @@ -270,10 +270,10 @@ def test_MSXgetqual(self): self.assertEqual(self.msxClass.MSXgetqual(0, 1, 1), 0.8, 'Wrong get qual comment output') if c == 85: - self.assertEqual(self.msxClass.MSXgetqual(0, 1, 1), 0.7991662288393907, + self.assertEqual(self.msxClass.MSXgetqual(0, 1, 1), 0.7991666666666667, 'Wrong get qual comment output') if c == 660: - self.assertEqual(self.msxClass.MSXgetqual(0, 1, 1), 0.7999999830262526, + self.assertEqual(self.msxClass.MSXgetqual(0, 1, 1), 0.8, 'Wrong get qual comment output') if tleft <= 0: break