Skip to content

Commit c695cec

Browse files
author
xavfa
committed
This is a merge action from the ForDevelopment Branch to the main one. the merge is done in a hard way.
lots of improvement and robustness done from the former main branch. some improvement could still be made on the geometry and cleaning side to make it faster for cleanner geometries and more in depth for rough ones. It will be handles in the future. Improvement goes along improvements on geomeppy ForMUBES branch !
1 parent d3a3a8b commit c695cec

17 files changed

+979
-463
lines changed

BuildObject/BuildingObject.py

+193-92
Large diffs are not rendered by default.

BuildObject/GeomUtilities.py

+265-34
Large diffs are not rendered by default.

CoreFiles/CaseBuilder_OAT.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ def LaunchProcess(SimDir,FirstRun,TotNbRun,currentRun,keyPath,nbcase,CorePerim,F
7070
if not DataBaseInput:
7171
# Buildingobjects from reading the geojson file as input for further functions if not given as arguments
7272
DataBaseInput = GrlFct.ReadGeoJsonFile(keyPath)
73-
Buildingsfile = DataBaseInput['Build']
7473
epluspath = keyPath['epluspath']
7574
os.chdir(SimDir)
7675
start = time.time()
@@ -114,7 +113,15 @@ def LaunchProcess(SimDir,FirstRun,TotNbRun,currentRun,keyPath,nbcase,CorePerim,F
114113
str(round(time.time()-startIniti,2))+' sec\n', LogFile)
115114
# The simulation parameters are assigned here
116115
if not MakePlotOnly:
117-
GrlFct.setSimLevel(idf, building)
116+
try: GrlFct.setSimLevel(idf, building)
117+
except:
118+
msg = '[Error] The SimLevel has failed...\n'
119+
if Verbose: print(msg[:-1])
120+
os.chdir(MainPath)
121+
if FirstRun:
122+
GrlFct.Write2LogFile(msg, LogFile)
123+
GrlFct.Write2LogFile('##############################################################\n', LogFile)
124+
118125
# The geometry is assigned here
119126
try:
120127
if DebugMode: startIniti = time.time()
@@ -158,7 +165,7 @@ def LaunchProcess(SimDir,FirstRun,TotNbRun,currentRun,keyPath,nbcase,CorePerim,F
158165

159166
if DebugMode: startIniti = time.time()
160167
if not MakePlotOnly: #in order to make parametric simulation, lets go along the VarName2Change list and change the building object attributes accordingly
161-
GrlFct.setChangedParam(building, ParamVal, VarName2Change, MainPath, Buildingsfile, nbcase)
168+
GrlFct.setChangedParam(building, ParamVal, VarName2Change, MainPath, DataBaseInput, nbcase)
162169

163170
# lets assign the material and finalize the envelope definition
164171
try:
@@ -179,6 +186,7 @@ def LaunchProcess(SimDir,FirstRun,TotNbRun,currentRun,keyPath,nbcase,CorePerim,F
179186
str(round(time.time() - startIniti, 2)) + ' sec\n', LogFile)
180187

181188
if MakePlotOnly:
189+
idf.idfname += ' / ' +building.BuildID['BldIDKey']+' : '+ str(building.BuildID[building.BuildID['BldIDKey']])
182190
return building,idf, 'OK'
183191

184192
# lets define the zone level now

CoreFiles/DefaultConfig.yml

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
PATH_TO_RESULTS : ../../MUBES_SimResults/ #[Str] this is the main folder where the results will be stored. it will be created if not exists
77

88
1_DATA :
9-
PATH_TO_DATA : '../ModelerFolder/Minneberg_Buildings_v1.geojson' #[Str] Input file or folder in case of several files
9+
PATH_TO_DATA : ../ModelerFolder/Minneberg_Buildings_v1.geojson #[Str] Input file or folder in case of several files
10+
EPSG_REF : None #[int], is 4326 for US East coast, 3950 for EU, some other for elsewhere, leave None if no conversion is wanted
1011

1112
2_CASE :
1213
0_GrlChoices :
@@ -20,7 +21,7 @@
2021
DebugMode : False #[Bool] The log file will be feeded by detailed information along the process
2122
1_SimChoices :
2223
ZoneOfInterest : '' #[Str] BldID can be given from an external file if generated by a third program.
23-
BldID : [] #[List of Str] list of Building's ID if defined as attribute in the geojson file, index of the building in the geojson file otherwise
24+
BldID : [] #[List of Str or int] list of Building's ID if defined as attribute in the geojson file, index of the building in the geojson file otherwise
2425
DESO : [] #[List of Str] not currently used
2526
VarName2Change : [] #[List of Str] parameters to be changed for parametric simulations
2627
Bounds : [] #[List of list of 2 floats] bounds between the parameter are to be changed [Lower Bound,Upper Bounds] a pair of value is to be given for each parameter in VarName2Change
@@ -42,6 +43,7 @@
4243
PassBldObject : True #[Bool] key word for reading only once the geojson file. but no launch through consol then for each bld
4344
RefBuildNum : None #[Int] building number (order of the GeoJson file) taken as a reference to pick other within the RefPerimeter distance. useful for large DataSets if None it will be ignored
4445
RefPerimeter : 500 #[int] Distance threshold for which all building farer then this threshold for the RefBuildNum are ignored
46+
MakePolygonPlots : False #[Bool] Distance threshold for which all building farer then this threshold for the RefBuildNum are ignored
4547
3_SIM :
4648
#files are needed to be located in the eather folder of EnergyPlus asthe same path is used afterward to launch the simulation
4749
1_WeatherData :
@@ -192,6 +194,8 @@
192194
VertexKey : 'geometries' #[str] key for the attribute of the coordinates given in the geojson file only
193195
MaxShadingDist : 200 #[Float] Maximum distance allowed to consider shadowing walls
194196
DistanceTolerance : 0.2 #[Float] Geometric threshold from which below every edge are removed and vertexes merged
197+
AltitudeTolerance : 3 #[float] Threshold below wich altitude will be merged. it should be the heigh of a storey
198+
VertexPrecision : 5 #[int] precision of the round function for vertex coordinates
195199

196200

197201
# definition of person/m2...complytely abritrary, but we still need some vaalues

CoreFiles/DefaultConfigKeyUnit.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
1_DATA :
99
PATH_TO_DATA : [str] #Input file or folder in case of several files
10+
EPSG_REF : [int,str] #[int or 'None'], is 4326 for US East coast, 3950 for EU, some other for elsewhere
1011

1112
2_CASE:
1213
0_GrlChoices :
@@ -20,7 +21,7 @@
2021
DebugMode : [bool] #[Bool] The log file will be feeded by detailed information along the process
2122
1_SimChoices:
2223
ZoneOfInterest : [str] #[Str] BldID can be given from an external file if generated by a third program.
23-
BldID : [str] #[List of Str] list of Building's ID if defined as attribute in the geojson file, index of the building in the geojson file otherwise
24+
BldID : [int,str] #[List of Str] list of Building's ID if defined as attribute in the geojson file, index of the building in the geojson file otherwise
2425
DESO : [str] #[Str] not currently used
2526
VarName2Change : [str] #[List of Str] parameters to be changed for parametric simulations
2627
Bounds : [float,int] #[List of list of 2 floats] bounds between the parameter are to be changed [Lower Bound,Upper Bounds] a pair of value is to be given for each parameter in VarName2Change
@@ -42,6 +43,7 @@
4243
PassBldObject: [bool] #[Bool] key word for reading only once the geojson file. but no launch through consol then for each bld
4344
RefBuildNum: [int,str] #[Int] building number (order of the GeoJson file) taken as a reference to pick other within the RefPerimeter distance. useful for large DataSets
4445
RefPerimeter: [int] #[int] Distance threshold for which all building farer then this threshold for the RefBuildNum are ignored
46+
MakePolygonPlots : [bool] #[Bool] Distance threshold for which all building farer then this threshold for the RefBuildNum are ignored
4547
3_SIM :
4648
#files are needed to be located in the eather folder of EnergyPlus asthe same path is used afterward to launch the simulation
4749
1_WeatherData :
@@ -190,6 +192,8 @@
190192
VertexKey : [str] #[str] key for the attribute of the coordinates given in the geojson file only
191193
MaxShadingDist : [float,int] #[Float] Maximum distance allowed to consider shadowing walls
192194
DistanceTolerance : [float,int] #[Float] Geometric threshold from which below every edge are removed and vertexes merged
195+
VertexPrecision : [int] #[int] precision of the round function for vertex coordinates
196+
AltitudeTolerance : [float,int] #[float] Threshold below wich altitude will be merged
193197

194198

195199
# definition of person/m2...complytely abritrary, but we still need some vaalues

CoreFiles/GeneralFunctions.py

+65-29
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
import CoreFiles.DomesticHotWater as DomesticHotWater
1010
import CoreFiles.MUBES_pygeoj as MUBES_pygeoj
1111
import CoreFiles.BuildFMUs as BuildFMUs
12+
import ReadResults.Utilities as Utilities
1213
from openpyxl import load_workbook
1314
import openturns as ot
1415
import shutil
1516
import pickle
1617
import pyproj
1718
import numpy as np
19+
import json
1820

1921
def appendBuildCase(StudiedCase,keypath,nbcase,DataBaseInput,MainPath,LogFile,PlotOnly = False, DebugMode = False):
2022
StudiedCase.addBuilding('Building'+str(nbcase),DataBaseInput,nbcase,MainPath,keypath,LogFile,PlotOnly, DebugMode)
@@ -68,21 +70,47 @@ def readPathfile(Pathways):
6870
keyPath[key] = os.path.normcase(line[line.find(':') + 1:-1])
6971
return keyPath
7072

71-
def ReadGeoJsonFile(keyPath,toBuildPool = False):
73+
def ReadGeoJsonFile(keyPath,CoordSys = '',toBuildPool = False):
7274
#print('Reading Input files,...')
7375
try:
7476
BuildObjectDict = ReadGeojsonKeyNames(keyPath['GeojsonProperties'])
7577
Buildingsfile = MUBES_pygeoj.load(keyPath['Buildingsfile'])
76-
#Shadingsfile = MUBES_pygeoj.load(keyPath['Shadingsfile'])
77-
if not toBuildPool: Buildingsfile = checkRefCoordinates(Buildingsfile)
78+
if not toBuildPool: Buildingsfile = checkRefCoordinates(Buildingsfile,CoordSys)
79+
Shadingsfile = getShadowingFile(keyPath['Buildingsfile'],CoordSys)
7880
#if not toBuildPool: Shadingsfile = checkRefCoordinates(Shadingsfile)
79-
return {'BuildObjDict':BuildObjectDict,'Build' :Buildingsfile}#, 'Shades': Shadingsfile}
81+
return {'BuildObjDict':BuildObjectDict,'Build' :Buildingsfile, 'Shades': Shadingsfile}
8082
except:
8183
Buildingsfile = MUBES_pygeoj.load(keyPath['Buildingsfile'])
82-
#Shadingsfile = MUBES_pygeoj.load(keyPath['Shadingsfile'])
83-
if not toBuildPool: Buildingsfile = checkRefCoordinates(Buildingsfile)
84+
if not toBuildPool: Buildingsfile = checkRefCoordinates(Buildingsfile,CoordSys)
85+
Shadingsfile = getShadowingFile(keyPath['Buildingsfile'],CoordSys)
8486
#if not toBuildPool: Shadingsfile = checkRefCoordinates(Shadingsfile)
85-
return {'Build': Buildingsfile}#, 'Shades': Shadingsfile}
87+
return {'Build': Buildingsfile, 'Shades': Shadingsfile}
88+
89+
def getShadowingFile(BuildingFilePath,CoordSys):
90+
Shadingsfile = []
91+
JSONFile = []
92+
GeJsonFile = []
93+
BuildingFileName = os.path.basename(BuildingFilePath)
94+
JSonTest = os.path.join(os.path.dirname(BuildingFilePath),
95+
BuildingFileName[:BuildingFileName.index('.')] + '_Walls.json')
96+
GeoJsonTest = os.path.join(os.path.dirname(BuildingFilePath), BuildingFileName.replace('Buildings', 'Walls'))
97+
GeoJsonTest1 = True if 'Walls' in GeoJsonTest else False
98+
if os.path.isfile(JSonTest):
99+
JSONFile = JSonTest
100+
elif os.path.isfile(GeoJsonTest) and GeoJsonTest1:
101+
GeJsonFile = GeoJsonTest
102+
else:
103+
msg = '[Prep. Info] No shadowing wall file found'
104+
if JSONFile:
105+
msg = '[Prep. Info] json shadowing walls file found'
106+
with open(JSONFile) as json_file:
107+
Shadingsfile = json.load(json_file)
108+
if GeJsonFile:
109+
msg = '[Prep. Info] Geojson shadowing walls file found'
110+
Shadingsfile = MUBES_pygeoj.load(GeJsonFile)
111+
Shadingsfile = checkRefCoordinates(Shadingsfile,CoordSys)
112+
print(msg)
113+
return Shadingsfile
86114

87115
def ListAvailableFiles(keyPath):
88116
# reading the pathfiles and the geojsonfile
@@ -112,30 +140,42 @@ def ReadGeoJsonDir(keyPath):
112140
BuildingFiles.append(file)
113141
return BuildingFiles
114142

115-
def checkRefCoordinates(GeojsonFile):
143+
def checkRefCoordinates(GeojsonFile,CoordSys):
116144
if not GeojsonFile:
117145
return GeojsonFile
118-
if 'EPSG' in GeojsonFile.crs['properties']['name']:
119-
return GeojsonFile
120-
##The coordinate system depends on the input file, thus, if specific filter or conversion from one to another,
121-
# it should be done here
122-
if "CRS84" in GeojsonFile.crs['properties']['name']:
123-
print('Projecting coordinates of Input file,...')
124-
transformer = pyproj.Transformer.from_crs("CRS84", "epsg:3950") #this transformation if done for the France's reference
125-
for idx,obj in enumerate(GeojsonFile):
126-
newCoord = []
127-
for poly in obj.geometry.coordinates:
128-
newpoly = []
129-
for vertex in poly:
130-
newpoly.append(list(transformer.transform(vertex[0], vertex[1])))
131-
newCoord.append(newpoly)
132-
obj.geometry.coordinates = newCoord
133-
return GeojsonFile
146+
# if 'EPSG' in GeojsonFile.crs['properties']['name']:
147+
# return GeojsonFile
148+
# ##The coordinate system depends on the input file, thus, if specific filter or conversion from one to another,
149+
# # it should be done here
150+
if type(CoordSys)==int:
151+
GeojsonFile = MakeCoordConversion(GeojsonFile, CoordSys)
152+
#GeojsonFile = MakeCoordConversion(GeojsonFile, CoordSys)
134153
return GeojsonFile
135154

155+
def MakeCoordConversion(GeojsonFile,CoordSys):
156+
print('Projecting coordinates of Input file,...')
157+
transformer = pyproj.Transformer.from_crs("CRS84", "epsg:" + str(
158+
CoordSys)) # this transformation if done for the France's reference
159+
for idx, obj in enumerate(GeojsonFile):
160+
newCoord = []
161+
for poly in obj.geometry.coordinates:
162+
newpoly = []
163+
for vertex in poly:
164+
newvertex = list(transformer.transform(vertex[0], vertex[1]))
165+
newpoly.append(
166+
newvertex) # the reversed list and this signe were added after looking at google map and the plot for boston city
167+
newCoord.append(newpoly)
168+
obj.geometry.coordinates = newCoord
169+
obj.geometry.update_centroid()
170+
return GeojsonFile
171+
172+
136173
def ComputeDistance(v1,v2):
137174
return ((v2[0]-v1[0])**2+(v2[1]-v1[1])**2)**0.5
138175

176+
def MakePolygonPlots(CaseChoices,Pool2Launch):
177+
Utilities.makePolyPlots(CaseChoices,Pool2Launch)
178+
139179
def MakeAbsoluteCoord(building,idf = [],roundfactor = 8):
140180
# we need to convert change the reference coordinate because precision is needed for boundary conditions definition:
141181
newfoot = []
@@ -388,7 +428,7 @@ def AppendLogFiles(MainPath,BldIDKey):
388428
os.remove(os.path.join(MainPath, file2del))
389429

390430
#def setChangedParam(building,ParamVal,VarName2Change,MainPath,Buildingsfile,Shadingsfile,nbcase,LogFile=[]):
391-
def setChangedParam(building, ParamVal, VarName2Change, MainPath, Buildingsfile, nbcase, LogFile=[]):
431+
def setChangedParam(building, ParamVal, VarName2Change, MainPath, DataBaseInput, nbcase, LogFile=[]):
392432
#there is a loop file along the variable name to change and if specific ation are required it should be define here
393433
# if the variable to change are embedded into several layer of dictionnaries than there is a need to make checks and change accordingly to the correct element
394434
# here are examples for InternalMass impact using 'InternalMass' keyword in the VarName2Change list to play with the 'WeightperZoneArea' parameter
@@ -417,8 +457,6 @@ def setChangedParam(building, ParamVal, VarName2Change, MainPath, Buildingsfile,
417457
setattr(building, var, exttmass)
418458
elif 'MaxShadingDist' in var:
419459
building.MaxShadingDist = round(ParamVal[varnum], roundVal)
420-
#building.shades = building.getshade(Buildingsfile[nbcase], Shadingsfile, Buildingsfile,LogFile,PlotOnly = False)
421-
building.shades = building.getshade(nbcase, Buildingsfile, LogFile,PlotOnly=False)
422460
elif 'IntLoadCurveShape' in var:
423461
building.IntLoadCurveShape = max(round(ParamVal[varnum], roundVal),1e-6)
424462
building.IntLoad = building.getIntLoad(MainPath, LogFile)
@@ -545,8 +583,6 @@ def ManageGlobalPlots(BldObj,IdfObj,FigCenter,WindSize, PlotBldOnly,nbcase = [],
545583
adiabsurf.append(s.Name[:s.Name.index('_')])
546584
nbadiab += 1
547585
RoofSpecialColor = "firebrick"
548-
if nbcase in [39]:
549-
RoofSpecialColor = 'limegreen'
550586
IdfObj.view_model(test= True if PlotBldOnly+LastBld>0 else False, FigCenter=FigCentroid, WindSize=2 * WindSize,
551587
RoofSpecialColor=RoofSpecialColor)
552588
return FigCenter,WindSize

0 commit comments

Comments
 (0)