topologicpy 0.3.6__py3-none-any.whl → 0.3.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,105 +10,102 @@ import os
10
10
  from os.path import exists
11
11
  import json
12
12
  from datetime import datetime
13
+ try:
14
+ from tqdm.auto import tqdm
15
+ except:
16
+ import sys, subprocess
17
+ call = [sys.executable, '-m', 'pip', 'install', 'tqdm', '-t', sys.path[0]]
18
+ subprocess.run(call)
19
+ from tqdm.auto import tqdm
13
20
 
14
21
  class EnergyModel:
15
22
  @staticmethod
16
- def EnergyModelByImportedOSM(item):
23
+ def ByImportedOSM(path: str):
17
24
  """
25
+ Creates an EnergyModel from the input OSM file path.
26
+
18
27
  Parameters
19
28
  ----------
20
- item : TYPE
21
- DESCRIPTION.
22
-
23
- Raises
24
- ------
25
- Exception
26
- DESCRIPTION.
29
+ path : string
30
+ The path to the input .OSM file.
27
31
 
28
32
  Returns
29
33
  -------
30
- model : TYPE
31
- DESCRIPTION.
34
+ openstudio.openstudiomodelcore.Model
35
+ The OSM model.
32
36
 
33
37
  """
38
+ if not path:
39
+ return None
34
40
  translator = openstudio.osversion.VersionTranslator()
35
- osmFile = openstudio.openstudioutilitiescore.toPath(item)
36
- model = translator.loadModel(osmFile)
37
- if model.isNull():
38
- raise Exception("File Path is not a valid path to an OpenStudio Model")
41
+ osmPath = openstudio.openstudioutilitiescore.toPath(path)
42
+ osModel = translator.loadModel(osmPath)
43
+ if osModel.isNull():
39
44
  return None
40
45
  else:
41
- model = model.get()
42
- return model
46
+ osModel = osModel.get()
47
+ return osModel
43
48
 
44
49
  @staticmethod
45
- def EnergyModelByTopology(osModelPath, weatherFilePath, designDayFilePath,
46
- buildingTopology, shadingSurfaces, floorLevels,
47
- buildingName, buildingType, defaultSpaceType,
48
- northAxis, glazingRatio, coolingTemp,
49
- heatingTemp, roomNameKey, roomTypeKey):
50
- """
50
+ def ByTopology(building : topologic.CellComplex,
51
+ shadingSurfaces : topologic.Topology = None,
52
+ osModelPath : str = None,
53
+ weatherFilePath : str = None,
54
+ designDayFilePath : str = None,
55
+ floorLevels : list = None,
56
+ buildingName : str = "TopologicBuilding",
57
+ buildingType : str = "Commercial",
58
+ northAxis : float = 0.0,
59
+ glazingRatio : float = 0.0,
60
+ coolingTemp : float = 25.0,
61
+ heatingTemp : float = 20.0,
62
+ defaultSpaceType : str = "189.1-2009 - Office - WholeBuilding - Lg Office - CZ4-8",
63
+ spaceNameKey : str = "TOPOLOGIC_name",
64
+ spaceTypeKey : str = "TOPOLOGIC_type"):
65
+ """
66
+ Creates an EnergyModel from the input topology and parameters.
67
+
51
68
  Parameters
52
69
  ----------
53
- osModelPath : TYPE
54
- DESCRIPTION.
55
- weatherFilePath : TYPE
56
- DESCRIPTION.
57
- designDayFilePath : TYPE
58
- DESCRIPTION.
59
- buildingTopology : TYPE
60
- DESCRIPTION.
61
- shadingSurfaces : TYPE
62
- DESCRIPTION.
63
- floorLevels : TYPE
64
- DESCRIPTION.
65
- buildingName : TYPE
66
- DESCRIPTION.
67
- buildingType : TYPE
68
- DESCRIPTION.
69
- defaultSpaceType : TYPE
70
- DESCRIPTION.
71
- northAxis : TYPE
72
- DESCRIPTION.
73
- glazingRatio : TYPE
74
- DESCRIPTION.
75
- coolingTemp : TYPE
76
- DESCRIPTION.
77
- heatingTemp : TYPE
78
- DESCRIPTION.
79
- roomNameKey : TYPE
80
- DESCRIPTION.
81
- roomTypeKey : TYPE
82
- DESCRIPTION.
83
-
84
- Raises
85
- ------
86
- Exception
87
- DESCRIPTION.
70
+ building : topologic.CellComplex
71
+ The input building topology.
72
+ shadingSurfaces : topologic.Topology , optional
73
+ The input topology for shading surfaces. The default is None.
74
+ osModelPath : str , optional
75
+ The path to the template OSM file. The default is "./assets/EnergyModel/OSMTemplate-OfficeBuilding-3.5.0.osm".
76
+ weatherFilePath : str , optional
77
+ The input energy plus weather (epw) file. The default is "./assets/EnergyModel/GBR_London.Gatwick.037760_IWEC.epw".
78
+ designDayFilePath : str , optional
79
+ The input design day (ddy) file path. The default is "./assets/EnergyModel/GBR_London.Gatwick.037760_IWEC.ddy",
80
+ floorLevels : list , optional
81
+ The list of floor level Z heights including the lowest most and the highest most levels. If set to None, this method will attempt to
82
+ find the floor levels from the horizontal faces of the input topology
83
+ buildingName : str , optional
84
+ The desired name of the building. The default is "TopologicBuilding".
85
+ buildingType : str , optional
86
+ The building type. The default is "Commercial".
87
+ defaultSpaceType : str , optional
88
+ The default space type to apply to spaces that do not have a type assigned in their dictionary. The default is "189.1-2009 - Office - WholeBuilding - Lg Office - CZ4-8".
89
+ northAxis : float , optional
90
+ The counter-clockwise angle in degrees from the positive Y-axis representing the direction of the north axis. The default is 0.0.
91
+ glazingRatio : float , optional
92
+ The glazing ratio (ratio of windows to wall) to use for exterior vertical walls that do not have apertures. If you do not wish to use a glazing ratio, set it to 0. The default is 0.
93
+ coolingTemp : float , optional
94
+ The desired temperature in degrees at which the cooling system should activate. The default is 25.0.
95
+ heatingTemp : float , optional
96
+ The desired temperature in degrees at which the heating system should activate. The default is 25.0..
97
+ spaceNameKey : str , optional
98
+ The dictionary key to use to find the space name value. The default is "Name".
99
+ spaceTypeKey : str , optional
100
+ The dictionary key to use to find the space type value. The default is "Type".
88
101
 
89
102
  Returns
90
103
  -------
91
- osModel : TYPE
92
- DESCRIPTION.
104
+ openstudio.openstudiomodelcore.Model
105
+ The created OSM model.
93
106
 
94
107
  """
95
108
 
96
- # osModelPath = item[0]
97
- # weatherFilePath = item[1]
98
- # designDayFilePath = item[2]
99
- # buildingTopology = item[3]
100
- # shadingSurfaces = item[4]
101
- # floorLevels = item[5]
102
- # buildingName = item[6]
103
- # buildingType = item[7]
104
- # defaultSpaceType = item[8]
105
- # northAxis = item[9]
106
- # glazingRatio = item[10]
107
- # coolingTemp = item[11]
108
- # heatingTemp = item[12]
109
- # roomNameKey = item[13]
110
- # roomTypeKey = item[14]
111
-
112
109
  def getKeyName(d, keyName):
113
110
  keys = d.Keys()
114
111
  for key in keys:
@@ -124,11 +121,32 @@ class EnergyModel:
124
121
  else:
125
122
  return createUniqueName(name,nameList, number+1)
126
123
 
124
+ def getFloorLevels(building):
125
+ from topologicpy.Vertex import Vertex
126
+ from topologicpy.CellComplex import CellComplex
127
+ from topologicpy.Dictionary import Dictionary
128
+
129
+ d = CellComplex.Decompose(building)
130
+ bhf = d['bottomHorizontalFaces']
131
+ ihf = d['internalHorizontalFaces']
132
+ thf = d ['topHorizontalFaces']
133
+ hf = bhf+ihf+thf
134
+ floorLevels = [Vertex.Z(Topology.Centroid(f)) for f in hf]
135
+ floorLevels = list(set(floorLevels))
136
+ floorLevels.sort()
137
+ return floorLevels
138
+
139
+ if not osModelPath:
140
+ import os
141
+ osModelPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "OSMTemplate-OfficeBuilding-3.5.0.osm")
142
+ if not weatherFilePath or not designDayFilePath:
143
+ import os
144
+ weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
145
+ designDayFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.ddy")
127
146
  translator = openstudio.osversion.VersionTranslator()
128
147
  osmFile = openstudio.openstudioutilitiescore.toPath(osModelPath)
129
148
  osModel = translator.loadModel(osmFile)
130
149
  if osModel.isNull():
131
- raise Exception("File Path is not a valid path to an OpenStudio Model")
132
150
  return None
133
151
  else:
134
152
  osModel = osModel.get()
@@ -141,8 +159,13 @@ class EnergyModel:
141
159
  ddyModel = ddyModel.get()
142
160
  for ddy in ddyModel.getObjectsByType(openstudio.IddObjectType("OS:SizingPeriod:DesignDay")):
143
161
  osModel.addObject(ddy.clone())
162
+ else:
163
+ print("Could not load the DesignDay file")
164
+ return None
144
165
 
145
166
  osBuilding = osModel.getBuilding()
167
+ if not floorLevels:
168
+ floorLevels = getFloorLevels(building)
146
169
  osBuilding.setStandardsNumberOfStories(len(floorLevels) - 1)
147
170
  osBuilding.setNominalFloortoFloorHeight(max(floorLevels) / osBuilding.standardsNumberOfStories().get())
148
171
  osBuilding.setDefaultConstructionSet(osModel.getDefaultConstructionSets()[0])
@@ -169,7 +192,7 @@ class EnergyModel:
169
192
  osBuildingStorys.sort(key=lambda x: x.nominalZCoordinate().get())
170
193
  osSpaces = []
171
194
  spaceNames = []
172
- for spaceNumber, buildingCell in enumerate(Topology.SubTopologies(buildingTopology, "Cell")):
195
+ for spaceNumber, buildingCell in enumerate(Topology.SubTopologies(building, "Cell")):
173
196
  osSpace = openstudio.model.Space(osModel)
174
197
  osSpaceZ = buildingCell.CenterOfMass().Z()
175
198
  osBuildingStory = osBuildingStorys[0]
@@ -183,17 +206,20 @@ class EnergyModel:
183
206
  osSpace.setBuildingStory(osBuildingStory)
184
207
  cellDictionary = buildingCell.GetDictionary()
185
208
  if cellDictionary:
186
- if roomTypeKey:
187
- keyType = getKeyName(cellDictionary, roomTypeKey)
209
+ if spaceTypeKey:
210
+ keyType = getKeyName(cellDictionary, spaceTypeKey)
188
211
  else:
189
212
  keyType = getKeyName(cellDictionary, 'type')
190
- osSpaceTypeName = Dictionary.ValueAtKey(cellDictionary,keyType)
213
+ if keyType:
214
+ osSpaceTypeName = Dictionary.ValueAtKey(cellDictionary,keyType)
215
+ else:
216
+ osSpaceTypeName = defaultSpaceType
191
217
  if osSpaceTypeName:
192
218
  sp_ = osModel.getSpaceTypeByName(osSpaceTypeName)
193
219
  if sp_.is_initialized():
194
220
  osSpace.setSpaceType(sp_.get())
195
- if roomNameKey:
196
- keyName = getKeyName(cellDictionary, roomNameKey)
221
+ if spaceNameKey:
222
+ keyName = getKeyName(cellDictionary, spaceNameKey)
197
223
 
198
224
  else:
199
225
  keyName = getKeyName(cellDictionary, 'name')
@@ -223,7 +249,7 @@ class EnergyModel:
223
249
  osSurface.setVertices(list(reversed(osFacePoints)))
224
250
  osSurface.setSpace(osSpace)
225
251
  faceCells = []
226
- _ = topologic.FaceUtility.AdjacentCells(buildingFace, buildingTopology, faceCells)
252
+ _ = topologic.FaceUtility.AdjacentCells(buildingFace, building, faceCells)
227
253
  if len(faceCells) == 1: #Exterior Surfaces
228
254
  osSurface.setOutsideBoundaryCondition("Outdoors")
229
255
  if (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) > 135) or (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) < 45):
@@ -310,8 +336,9 @@ class EnergyModel:
310
336
  osSpace.matchSurfaces(x)
311
337
  osSpaces.append(osSpace)
312
338
 
313
- osShadingGroup = openstudio.model.ShadingSurfaceGroup(osModel)
314
- if not isinstance(shadingSurfaces,int):
339
+
340
+ if shadingSurfaces:
341
+ osShadingGroup = openstudio.model.ShadingSurfaceGroup(osModel)
315
342
  for faceIndex, shadingFace in enumerate(Topology.SubTopologies(shadingSurfaces, "Face")):
316
343
  facePoints = []
317
344
  for aVertex in Topology.SubTopologies(shadingFace.ExternalBoundary(), "Vertex"):
@@ -329,446 +356,460 @@ class EnergyModel:
329
356
  return osModel
330
357
 
331
358
  @staticmethod
332
- def EnergyModelColumnNames(model, reportName, tableName):
359
+ def ColumnNames(model, reportName, tableName):
333
360
  """
361
+ Returns the list of column names given an OSM model, report name, and table name.
362
+
334
363
  Parameters
335
364
  ----------
336
- model : TYPE
337
- DESCRIPTION.
338
- reportName : TYPE
339
- DESCRIPTION.
340
- tableName : TYPE
341
- DESCRIPTION.
365
+ model : openstudio.openstudiomodelcore.Model
366
+ The input OSM model.
367
+ reportName : str
368
+ The input report name.
369
+ tableName : str
370
+ The input table name.
342
371
 
343
372
  Returns
344
373
  -------
345
- TYPE
346
- DESCRIPTION.
374
+ list
375
+ the list of column names.
347
376
 
348
377
  """
349
- # model = item[0]
350
- # reportName = item[1]
351
- # tableName = item[2]
352
378
  sql = model.sqlFile().get()
353
379
  query = "SELECT ColumnName FROM tabulardatawithstrings WHERE ReportName = '"+reportName+"' AND TableName = '"+tableName+"'"
354
380
  columnNames = sql.execAndReturnVectorOfString(query).get()
355
381
  return list(OrderedDict( (x,1) for x in columnNames ).keys()) #Making a unique list and keeping its order
356
382
 
357
383
  @staticmethod
358
- def EnergyModelDefaultConstructionSets(item):
384
+ def DefaultConstructionSets(model):
359
385
  """
386
+ Returns the default construction sets in the input OSM model.
387
+
360
388
  Parameters
361
389
  ----------
362
- item : TYPE
363
- DESCRIPTION.
390
+ model : openstudio.openstudiomodelcore.Model
391
+ The input OSM model.
364
392
 
365
393
  Returns
366
394
  -------
367
395
  list
368
- DESCRIPTION.
396
+ The default construction sets.
369
397
 
370
398
  """
371
- sets = item.getDefaultConstructionSets()
399
+ sets = model.getDefaultConstructionSets()
372
400
  names = []
373
401
  for aSet in sets:
374
402
  names.append(aSet.name().get())
375
403
  return [sets, names]
376
404
 
377
405
  @staticmethod
378
- def EnergyModelDefaultScheduleSets(item):
406
+ def DefaultScheduleSets(model):
379
407
  """
408
+ Returns the default schedule sets found in the input OSM model.
409
+
380
410
  Parameters
381
411
  ----------
382
- item : TYPE
383
- DESCRIPTION.
412
+ model : openstudio.openstudiomodelcore.Model
413
+ The input OSM model.
384
414
 
385
415
  Returns
386
416
  -------
387
417
  list
388
- DESCRIPTION.
418
+ The list of default schedule sets.
389
419
 
390
420
  """
391
- sets = item.getDefaultScheduleSets()
421
+ sets = model.getDefaultScheduleSets()
392
422
  names = []
393
423
  for aSet in sets:
394
424
  names.append(aSet.name().get())
395
425
  return [sets, names]
396
426
 
397
427
  @staticmethod
398
- def EnergyModelExportToGbXML(osModel, filepath, overwrite):
428
+ def ExportToGbXML(model, path, overwrite=False):
399
429
  """
430
+ Exports the input OSM model to a gbxml file.
431
+
400
432
  Parameters
401
433
  ----------
402
- osModel : TYPE
403
- DESCRIPTION.
404
- filepath : TYPE
405
- DESCRIPTION.
406
- overwrite : TYPE
407
- DESCRIPTION.
408
-
409
- Raises
410
- ------
411
- Exception
412
- DESCRIPTION.
434
+ model : openstudio.openstudiomodelcore.Model
435
+ The input OSM model.
436
+ path : str
437
+ The path for saving the file.
438
+ overwrite : bool, optional
439
+ If set to True any file with the same name is over-written. The default is False.
413
440
 
414
441
  Returns
415
442
  -------
416
- TYPE
417
- DESCRIPTION.
443
+ bool
444
+ True if the file is written successfully. False otherwise.
418
445
 
419
446
  """
420
447
  # osModel = item[0]
421
448
  # filepath = item[1]
422
449
  # Make sure the file extension is .xml
423
- ext = filepath[len(filepath)-4:len(filepath)]
450
+ ext = path[len(path)-4:len(path)]
424
451
  if ext.lower() != ".xml":
425
- filepath = filepath+".xml"
426
- if(exists(filepath) and (overwrite == False)):
427
- raise Exception("Error: Could not create a new file at the following location: "+filepath)
428
- return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(osModel, openstudio.openstudioutilitiescore.toPath(filepath))
429
-
430
- @staticmethod
431
- def EnergyModelExportToHBJSON(hbjson, filepath, overwrite):
432
- """
433
- Parameters
434
- ----------
435
- hbjson : TYPE
436
- DESCRIPTION.
437
- filepath : TYPE
438
- DESCRIPTION.
439
- overwrite : TYPE
440
- DESCRIPTION.
441
-
442
- Raises
443
- ------
444
- Exception
445
- DESCRIPTION.
446
-
447
- Returns
448
- -------
449
- bool
450
- DESCRIPTION.
452
+ path = path+".xml"
453
+ if(exists(path) and (overwrite == False)):
454
+ return None
455
+ return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(model, openstudio.openstudioutilitiescore.toPath(path))
451
456
 
452
- """
453
- # hbjson = item[0]
454
- # filepath = item[1]
455
- # Make sure the file extension is .BREP
456
- ext = filepath[len(filepath)-7:len(filepath)]
457
- if ext.lower() != ".hbjson":
458
- filepath = filepath+".hbjson"
459
- f = None
460
- try:
461
- if overwrite == True:
462
- f = open(filepath, "w")
463
- else:
464
- f = open(filepath, "x") # Try to create a new File
465
- except:
466
- raise Exception("Error: Could not create a new file at the following location: "+filepath)
467
- if (f):
468
- json.dump(hbjson[0], f, indent=4)
469
- f.close()
470
- return True
471
- return False
472
457
 
473
458
  @staticmethod
474
- def EnergyModelExportToOSM(model, filePath, overwrite):
459
+ def ExportToOSM(model, path, overwrite=False):
475
460
  """
461
+ Exports the input OSM model to an OSM file.
462
+
476
463
  Parameters
477
464
  ----------
478
- model : TYPE
479
- DESCRIPTION.
480
- filePath : TYPE
481
- DESCRIPTION.
482
- overwrite : TYPE
483
- DESCRIPTION.
465
+ model : openstudio.openstudiomodelcore.Model
466
+ The input OSM model.
467
+ path : str
468
+ The path for saving the file.
469
+ overwrite : bool, optional
470
+ If set to True any file with the same name is over-written. The default is False.
484
471
 
485
472
  Returns
486
473
  -------
487
- osCondition : TYPE
488
- DESCRIPTION.
474
+ bool
475
+ True if the file is written successfully. False otherwise.
489
476
 
490
477
  """
491
- # model = item[0]
492
- # filePath = item[1]
493
- # Make sure the file extension is .OSM
494
- ext = filePath[len(filePath)-4:len(filePath)]
478
+ ext = path[len(path)-4:len(path)]
495
479
  if ext.lower() != ".osm":
496
- filePath = filePath+".osm"
480
+ path = path+".osm"
497
481
  osCondition = False
498
- osPath = openstudio.openstudioutilitiescore.toPath(filePath)
482
+ osPath = openstudio.openstudioutilitiescore.toPath(path)
499
483
  osCondition = model.save(osPath, overwrite)
500
484
  return osCondition
501
485
 
502
486
  @staticmethod
503
- def EnergyModelGbXMLString(item):
487
+ def GbXMLString(model):
504
488
  """
505
- Parameters
506
- ----------
507
- item : TYPE
508
- DESCRIPTION.
489
+ Returns the gbxml string of the input OSM model.
509
490
 
510
- Returns
511
- -------
512
- TYPE
513
- DESCRIPTION.
514
-
515
- """
516
- return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXMLString(item)
517
-
518
- @staticmethod
519
- def EnergyModelIFCToOSM(model, filePath):
520
- """
521
491
  Parameters
522
492
  ----------
523
- model : TYPE
524
- DESCRIPTION.
525
- filepath : TYPE
526
- DESCRIPTION.
493
+ model : openstudio.openstudiomodelcore.Model
494
+ The input OSM model.
527
495
 
528
496
  Returns
529
497
  -------
530
- osCondition : TYPE
531
- DESCRIPTION.
498
+ str
499
+ The gbxml string.
532
500
 
533
501
  """
534
- # model = item[0]
535
- # filePath = item[1]
536
- # Make sure the file extension is .OSM
537
- ext = filePath[len(filePath)-4:len(filePath)]
538
- if ext.lower() != ".osm":
539
- filePath = filePath+".osm"
540
- osCondition = False
541
- osPath = openstudio.openstudioutilitiescore.toPath(filePath)
542
- osCondition = model.save(osPath, True)
543
- return osCondition
502
+ return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXMLString(model)
544
503
 
545
504
  @staticmethod
546
- def EnergyModelQuery(model, EPReportName, EPReportForString, EPTableName,
547
- EPColumnName, EPRowName, EPUnits):
505
+ def Query(model,
506
+ reportName : str = "HVACSizingSummary",
507
+ reportForString : str = "Entire Facility",
508
+ tableName : str = "Zone Sensible Cooling",
509
+ columnName : str = "Calculated Design Load",
510
+ rowNames : list = [],
511
+ units : str = "W"):
548
512
  """
513
+ Queries the model for values.
514
+
549
515
  Parameters
550
516
  ----------
551
- model : TYPE
552
- DESCRIPTION.
553
- EPReportName : TYPE
554
- DESCRIPTION.
555
- EPReportForString : TYPE
556
- DESCRIPTION.
557
- EPTableName : TYPE
558
- DESCRIPTION.
559
- EPColumnName : TYPE
560
- DESCRIPTION.
561
- EPRowName : TYPE
562
- DESCRIPTION.
563
- EpUnits : TYPE
564
- DESCRIPTION.
517
+ model : openstudio.openstudiomodelcore.Model
518
+ The input OSM model.
519
+ reportName : str , optional
520
+ The input report name. The default is "HVACSizingSummary".
521
+ reportForString : str, optional
522
+ The input report for string. The default is "Entire Facility".
523
+ tableName : str , optional
524
+ The input table name. The default is "Zone Sensible Cooling".
525
+ columnName : str , optional
526
+ The input column name. The default is "Calculated Design Load".
527
+ rowNames : list , optional
528
+ The input list of row names. The default is [].
529
+ units : str , optional
530
+ The input units. The default is "W".
565
531
 
566
532
  Returns
567
533
  -------
568
- doubleValue : TYPE
569
- DESCRIPTION.
534
+ list
535
+ The list of values.
570
536
 
571
537
  """
572
- # model = item[0]
573
- # EPReportName = item[1]
574
- # EPReportForString = item[2]
575
- # EPTableName = item[3]
576
- # EPColumnName = item[4]
577
- # EPRowName = item[5]
578
- # EPUnits = item[6]
579
538
 
580
- def doubleValueFromQuery(sqlFile, EPReportName, EPReportForString,
581
- EPTableName, EPColumnName, EPRowName,
582
- EPUnits):
583
- doubleValue = 0.0
584
- query = "SELECT Value FROM tabulardatawithstrings WHERE ReportName='" + EPReportName + "' AND ReportForString='" + EPReportForString + "' AND TableName = '" + EPTableName + "' AND RowName = '" + EPRowName + "' AND ColumnName= '" + EPColumnName + "' AND Units='" + EPUnits + "'";
539
+ def doubleValueFromQuery(sqlFile, reportName, reportForString,
540
+ tableName, columnName, rowName,
541
+ units):
542
+ query = "SELECT Value FROM tabulardatawithstrings WHERE ReportName='" + reportName + "' AND ReportForString='" + reportForString + "' AND TableName = '" + tableName + "' AND RowName = '" + rowName + "' AND ColumnName= '" + columnName + "' AND Units='" + units + "'";
585
543
  osOptionalDoubleValue = sqlFile.execAndReturnFirstDouble(query)
586
544
  if (osOptionalDoubleValue.is_initialized()):
587
- doubleValue = osOptionalDoubleValue.get()
545
+ return osOptionalDoubleValue.get()
588
546
  else:
589
- raise Exception("Failed to get a double value from the SQL file.")
590
- return doubleValue
547
+ return None
591
548
 
592
549
  sqlFile = model.sqlFile().get()
593
- doubleValue = doubleValueFromQuery(sqlFile, EPReportName,
594
- EPReportForString, EPTableName,
595
- EPColumnName, EPRowName, EPUnits)
596
- return doubleValue
550
+ returnValues = []
551
+ for rowName in rowNames:
552
+ returnValues.append(doubleValueFromQuery(sqlFile, reportName, reportForString, tableName, columnName, rowName, units))
553
+ return returnValues
597
554
 
598
555
  @staticmethod
599
- def EnergyModelReportNames(model):
556
+ def ReportNames(model):
600
557
  """
558
+ Returns the report names found in the input OSM model.
559
+
601
560
  Parameters
602
561
  ----------
603
- model : TYPE
604
- DESCRIPTION.
562
+ model : openstudio.openstudiomodelcore.Model
563
+ The input OSM model.
605
564
 
606
565
  Returns
607
566
  -------
608
- TYPE
609
- DESCRIPTION.
567
+ list
568
+ The list of report names found in the input OSM model.
610
569
 
611
570
  """
612
- # model = item[0]
613
571
  sql = model.sqlFile().get()
614
572
  reportNames = sql.execAndReturnVectorOfString("SELECT ReportName FROM tabulardatawithstrings").get()
615
573
  return list(OrderedDict( (x,1) for x in reportNames ).keys()) #Making a unique list and keeping its order
616
574
 
617
575
  @staticmethod
618
- def EnergyModelRowNames(model, reportName, tableName):
576
+ def RowNames(model, reportName, tableName):
619
577
  """
578
+ Returns the list of row names given an OSM model, report name, and table name.
579
+
620
580
  Parameters
621
581
  ----------
622
- model : TYPE
623
- DESCRIPTION.
624
- reportName : TYPE
625
- DESCRIPTION.
626
- tableName : TYPE
627
- DESCRIPTION.
582
+ model : openstudio.openstudiomodelcore.Model
583
+ The input OSM model.
584
+ reportName : str
585
+ The input name of the report.
586
+ tableName : str
587
+ The input name of the table.
628
588
 
629
589
  Returns
630
590
  -------
631
- TYPE
632
- DESCRIPTION.
591
+ list
592
+ The list of row names.
633
593
 
634
594
  """
635
- # model = item[0]
636
- # reportName = item[1]
637
- # tableName = item[2]
638
595
  sql = model.sqlFile().get()
639
596
  query = "SELECT RowName FROM tabulardatawithstrings WHERE ReportName = '"+reportName+"' AND TableName = '"+tableName+"'"
640
597
  columnNames = sql.execAndReturnVectorOfString(query).get()
641
598
  return list(OrderedDict( (x,1) for x in columnNames ).keys()) #Making a unique list and keeping its order
642
599
 
643
600
  @staticmethod
644
- def EnergyModelRunSimulation(model, weatherFile, osBinaryPath,
645
- outputFolder, run):
601
+ def Run(model, weatherFilePath: str = None, osBinaryPath : str = None, outputFolder : str = None):
646
602
  """
603
+ Run an energy simulation.
604
+
647
605
  Parameters
648
606
  ----------
649
- model : TYPE
650
- DESCRIPTION.
651
- weatherFile : TYPE
652
- DESCRIPTION.
653
- osBinaryPath : TYPE
654
- DESCRIPTION.
655
- outputFolder : TYPE
656
- DESCRIPTION.
657
- run : TYPE
658
- DESCRIPTION.
607
+ model : openstudio.openstudiomodelcore.Model
608
+ The input OSM model.
609
+ weatherFilePath : str
610
+ The path to the epw weather file.
611
+ osBinaryPath : str
612
+ The path to the openstudio binary.
613
+ outputFolder : str
614
+ The path to the output folder.
659
615
 
660
616
  Returns
661
617
  -------
662
- model : TYPE
663
- DESCRIPTION.
618
+ model : openstudio.openstudiomodelcore.Model
619
+ The simulated OSM model.
664
620
 
665
621
  """
666
- # model = item[0]
667
- # weatherFile = item[1]
668
- # osBinaryPath = item[2]
669
- # outputFolder = item[3]
670
- # run = item[4]
671
- if not run:
672
- return None
622
+ import os
623
+ if not weatherFilePath:
624
+ weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
625
+ pbar = tqdm(desc='Running Simulation', total=100, leave=False)
673
626
  utcnow = datetime.utcnow()
674
627
  timestamp = utcnow.strftime("UTC-%Y-%m-%d-%H-%M-%S")
675
- outputFolder = os.path.join(outputFolder, timestamp)
628
+ if not outputFolder:
629
+ home = os.path.expanduser('~')
630
+ outputFolder = os.path.join(home, "EnergyModels", timestamp)
631
+ else:
632
+ outputFolder = os.path.join(outputFolder, timestamp)
676
633
  os.mkdir(outputFolder)
677
- osmPath = outputFolder + "/" + model.getBuilding().name().get() + ".osm"
634
+ pbar.update(10)
635
+ osmPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osm")
678
636
  model.save(openstudio.openstudioutilitiescore.toPath(osmPath), True)
679
637
  oswPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osw")
638
+ pbar.update(20)
680
639
  #print("oswPath = "+oswPath)
681
640
  workflow = model.workflowJSON()
682
641
  workflow.setSeedFile(openstudio.openstudioutilitiescore.toPath(osmPath))
642
+ pbar.update(30)
683
643
  #print("Seed File Set")
684
- workflow.setWeatherFile(openstudio.openstudioutilitiescore.toPath(weatherFile))
644
+ workflow.setWeatherFile(openstudio.openstudioutilitiescore.toPath(weatherFilePath))
645
+ pbar.update(40)
685
646
  #print("Weather File Set")
686
647
  workflow.saveAs(openstudio.openstudioutilitiescore.toPath(oswPath))
648
+ pbar.update(50)
687
649
  #print("OSW File Saved")
688
650
  cmd = osBinaryPath+" run -w " + "\"" + oswPath + "\""
651
+ pbar.update(60)
689
652
  os.system(cmd)
690
653
  #print("Simulation DONE")
691
654
  sqlPath = os.path.join(os.path.join(outputFolder,"run"), "eplusout.sql")
655
+ pbar.update(100)
692
656
  #print("sqlPath = "+sqlPath)
693
657
  osSqlFile = openstudio.SqlFile(openstudio.openstudioutilitiescore.toPath(sqlPath))
694
658
  model.setSqlFile(osSqlFile)
659
+ pbar.close()
695
660
  return model
696
661
 
697
662
  @staticmethod
698
- def EnergyModelSpaceTypes(item):
663
+ def SpaceDictionaries(model):
664
+ """
665
+ Return the space dictionaries found in the input OSM model.
666
+
667
+ Parameters
668
+ ----------
669
+ model : openstudio.openstudiomodelcore.Model
670
+ The input OSM model.
671
+
672
+ Returns
673
+ -------
674
+ dict
675
+ The dictionary of space types, names, and colors found in the input OSM model. The dictionary has the following keys:
676
+ - "types"
677
+ - "names"
678
+ - "colors"
679
+
680
+ """
681
+ types = model.getSpaceTypes()
682
+ names = []
683
+ colors = []
684
+ for aType in types:
685
+ names.append(aType.name().get())
686
+ red = aType.renderingColor().get().renderingRedValue()
687
+ green = aType.renderingColor().get().renderingGreenValue()
688
+ blue = aType.renderingColor().get().renderingBlueValue()
689
+ colors.append([red,green,blue])
690
+ return {'types': types, 'names': names, 'colors': colors}
691
+
692
+ @staticmethod
693
+ def SpaceTypes(model):
694
+ """
695
+ Return the space types found in the input OSM model.
696
+
697
+ Parameters
698
+ ----------
699
+ model : openstudio.openstudiomodelcore.Model
700
+ The input OSM model.
701
+
702
+ Returns
703
+ -------
704
+ list
705
+ The list of space types
706
+
707
+ """
708
+ return model.getSpaceTypes()
709
+
710
+ @staticmethod
711
+ def SpaceTypeNames(model):
699
712
  """
713
+ Return the space type names found in the input OSM model.
714
+
700
715
  Parameters
701
716
  ----------
702
- item : TYPE
703
- DESCRIPTION.
717
+ model : openstudio.openstudiomodelcore.Model
718
+ The input OSM model.
704
719
 
705
720
  Returns
706
721
  -------
707
722
  list
708
- DESCRIPTION.
723
+ The list of space type names
709
724
 
710
725
  """
711
- types = item.getSpaceTypes()
726
+ types = model.getSpaceTypes()
712
727
  names = []
713
728
  colors = []
714
729
  for aType in types:
715
730
  names.append(aType.name().get())
731
+ return names
732
+
733
+ @staticmethod
734
+ def SpaceColors(model):
735
+ """
736
+ Return the space colors found in the input OSM model.
737
+
738
+ Parameters
739
+ ----------
740
+ model : openstudio.openstudiomodelcore.Model
741
+ The input OSM model.
742
+
743
+ Returns
744
+ -------
745
+ list
746
+ The list of space colors. Each item is a three-item list representing the red, green, and blue values of the color.
747
+
748
+ """
749
+ types = model.getSpaceTypes()
750
+ colors = []
751
+ for aType in types:
716
752
  red = aType.renderingColor().get().renderingRedValue()
717
753
  green = aType.renderingColor().get().renderingGreenValue()
718
754
  blue = aType.renderingColor().get().renderingBlueValue()
719
755
  colors.append([red,green,blue])
720
- return [types, names, colors]
756
+ return colors
721
757
 
722
758
  @staticmethod
723
- def EnergyModelSqlFile(item):
759
+ def SqlFile(model):
724
760
  """
761
+ Returns the SQL file found in the input OSM model.
762
+
725
763
  Parameters
726
764
  ----------
727
- item : TYPE
728
- DESCRIPTION.
765
+ model : openstudio.openstudiomodelcore.Model
766
+ The input OSM model.
729
767
 
730
768
  Returns
731
769
  -------
732
- TYPE
733
- DESCRIPTION.
770
+ SQL file
771
+ The SQL file found in the input OSM model.
734
772
 
735
773
  """
736
- return item.sqlFile().get()
774
+ return model.sqlFile().get()
737
775
 
738
776
  @staticmethod
739
- def EnergyModelTableNames(model, reportName):
777
+ def TableNames(model, reportName):
740
778
  """
779
+ Returns the table names found in the input OSM model and report name.
780
+
741
781
  Parameters
742
782
  ----------
743
- model : TYPE
744
- DESCRIPTION.
745
- reportName : TYPE
746
- DESCRIPTION.
783
+ model : openstudio.openstudiomodelcore.Model
784
+ The input OSM model.
785
+ reportName : str
786
+ The input report name.
747
787
 
748
788
  Returns
749
789
  -------
750
- TYPE
751
- DESCRIPTION.
790
+ list
791
+ The list of table names found in the input OSM model and report name.
752
792
 
753
793
  """
754
- # model = item[0]
755
- # reportName = item[1]
756
794
  sql = model.sqlFile().get()
757
795
  tableNames = sql.execAndReturnVectorOfString("SELECT TableName FROM tabulardatawithstrings WHERE ReportName='"+reportName+"'").get()
758
796
  return list(OrderedDict( (x,1) for x in tableNames ).keys()) #Making a unique list and keeping its order
759
797
 
760
798
  @staticmethod
761
- def EnergyModelTopologies(item):
799
+ def Topologies(model):
762
800
  """
763
801
  Parameters
764
802
  ----------
765
- item : TYPE
766
- DESCRIPTION.
803
+ model : openstudio.openstudiomodelcore.Model
804
+ The input OSM model.
767
805
 
768
806
  Returns
769
807
  -------
770
- list
771
- DESCRIPTION.
808
+ dict
809
+ The dictionary of topologies found in the input OSM model. The keys of the dictionary are:
810
+ - "cells"
811
+ - "apertures"
812
+ - "shadingFaces"
772
813
 
773
814
  """
774
815
  def surfaceToFace(surface):
@@ -805,12 +846,12 @@ class EnergyModel:
805
846
  _ = topologic.Aperture.ByTopologyContext(aperture, context)
806
847
  return face
807
848
 
808
- spaces = item.getSpaces()
849
+ spaces = model.getSpaces()
809
850
  vertexIndex = 0
810
851
  cells = []
811
852
  apertures = []
812
853
  shadingFaces = []
813
- shadingSurfaces = item.getShadingSurfaces()
854
+ shadingSurfaces = model.getShadingSurfaces()
814
855
  for aShadingSurface in shadingSurfaces:
815
856
  shadingFaces.append(surfaceToFace(aShadingSurface))
816
857
  for count, aSpace in enumerate(spaces):
@@ -841,7 +882,6 @@ class EnergyModel:
841
882
  addApertures(aFace, apertures)
842
883
  spaceFaces.append(aFace)
843
884
  spaceCell = topologic.Cell.ByFaces(spaceFaces)
844
- print(count, spaceCell)
845
885
  if not spaceCell:
846
886
  spaceCell = topologic.Shell.ByFaces(spaceFaces)
847
887
  if not spaceCell:
@@ -877,31 +917,26 @@ class EnergyModel:
877
917
  dict = topologic.Dictionary.ByKeysValues(stl_keys, stl_values)
878
918
  _ = spaceCell.SetDictionary(dict)
879
919
  cells.append(spaceCell)
880
- return [cells, apertures, shadingFaces]
920
+ return {'cells':cells, 'apertures':apertures, 'shadingFaces': shadingFaces}
881
921
 
882
922
  @staticmethod
883
- def EnergyModelUnits(model, reportName, tableName, columnName):
923
+ def Units(model, reportName, tableName, columnName):
884
924
  """
885
925
  Parameters
886
926
  ----------
887
- model : TYPE
888
- DESCRIPTION.
889
- reportName : TYPE
890
- DESCRIPTION.
891
- tableName : TYPE
892
- DESCRIPTION.
893
- columnName : TYPE
894
- DESCRIPTION.
895
-
896
- Raises
897
- ------
898
- Exception
899
- DESCRIPTION.
927
+ model : openstudio.openstudiomodelcore.Model
928
+ The input OSM model.
929
+ reportName : str
930
+ The input report name.
931
+ tableName : str
932
+ The input table name.
933
+ columnName : str
934
+ The input column name.
900
935
 
901
936
  Returns
902
937
  -------
903
- units : TYPE
904
- DESCRIPTION.
938
+ str
939
+ The units string found in the input OSM model, report name, table name, and column name.
905
940
 
906
941
  """
907
942
  # model = item[0]
@@ -914,6 +949,6 @@ class EnergyModel:
914
949
  if (units.is_initialized()):
915
950
  units = units.get()
916
951
  else:
917
- raise Exception("Failed to get units from the SQL file.")
952
+ return None
918
953
  return units
919
954