topologicpy 0.7.42__py3-none-any.whl → 0.7.44__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.
- topologicpy/EnergyModel.py +34 -21
- topologicpy/Plotly.py +160 -5
- topologicpy/PyG.py +288 -30
- topologicpy/Shell.py +104 -0
- topologicpy/Topology.py +2 -2
- topologicpy/version.py +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.44.dist-info}/METADATA +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.44.dist-info}/RECORD +11 -11
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.44.dist-info}/WHEEL +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.44.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.44.dist-info}/top_level.txt +0 -0
topologicpy/EnergyModel.py
CHANGED
@@ -20,7 +20,7 @@ import math
|
|
20
20
|
from collections import OrderedDict
|
21
21
|
import os
|
22
22
|
from os.path import exists
|
23
|
-
from datetime import datetime
|
23
|
+
from datetime import datetime, timezone
|
24
24
|
import warnings
|
25
25
|
|
26
26
|
try:
|
@@ -249,18 +249,24 @@ class EnergyModel:
|
|
249
249
|
weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
|
250
250
|
designDayFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.ddy")
|
251
251
|
translator = openstudio.osversion.VersionTranslator()
|
252
|
-
|
253
|
-
|
252
|
+
# DEBUGGING
|
253
|
+
#osmFile = openstudio.openstudioutilitiescore.toPath(osModelPath)
|
254
|
+
#osModel = translator.loadModel(osmFile)
|
255
|
+
osModel = translator.loadModel(osModelPath)
|
254
256
|
if osModel.isNull():
|
255
257
|
print("EnergyModel.ByTopology - Error: The openstudio model is null. Returning None.")
|
256
258
|
return None
|
257
259
|
else:
|
258
260
|
osModel = osModel.get()
|
259
|
-
|
261
|
+
# DEBUGGING
|
262
|
+
#osEPWFile = openstudio.openstudioutilitiesfiletypes.EpwFile.load(openstudio.toPath(weatherFilePath))
|
263
|
+
osEPWFile = openstudio.openstudioutilitiesfiletypes.EpwFile.load(weatherFilePath)
|
260
264
|
if osEPWFile.is_initialized():
|
261
265
|
osEPWFile = osEPWFile.get()
|
262
266
|
openstudio.model.WeatherFile.setWeatherFile(osModel, osEPWFile)
|
263
|
-
|
267
|
+
# DEBUGGING
|
268
|
+
#ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(openstudio.toPath(designDayFilePath))
|
269
|
+
ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(designDayFilePath)
|
264
270
|
if ddyModel.is_initialized():
|
265
271
|
ddyModel = ddyModel.get()
|
266
272
|
for ddy in ddyModel.getObjectsByType(openstudio.IddObjectType("OS:SizingPeriod:DesignDay")):
|
@@ -578,8 +584,9 @@ class EnergyModel:
|
|
578
584
|
if not overwrite and exists(path):
|
579
585
|
print("EnergyModel.ExportToGBXML - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
|
580
586
|
return None
|
581
|
-
|
582
|
-
return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(model, openstudio.openstudioutilitiescore.toPath(path))
|
587
|
+
# DEBUGGING
|
588
|
+
#return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(model, openstudio.openstudioutilitiescore.toPath(path))
|
589
|
+
return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(model, path)
|
583
590
|
|
584
591
|
|
585
592
|
@staticmethod
|
@@ -629,8 +636,10 @@ class EnergyModel:
|
|
629
636
|
print("EnergyModel.ExportToOSM - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
|
630
637
|
return None
|
631
638
|
osCondition = False
|
632
|
-
|
633
|
-
|
639
|
+
# DEBUGGING
|
640
|
+
#osPath = openstudio.openstudioutilitiescore.toPath(path)
|
641
|
+
#osCondition = model.save(osPath, overwrite)
|
642
|
+
osCondition = model.save(path, overwrite)
|
634
643
|
return osCondition
|
635
644
|
|
636
645
|
@staticmethod
|
@@ -821,7 +830,7 @@ class EnergyModel:
|
|
821
830
|
if removeFiles:
|
822
831
|
deleteOldFiles(outputFolder)
|
823
832
|
pbar = tqdm(desc='Running Simulation', total=100, leave=False)
|
824
|
-
utcnow = datetime.
|
833
|
+
utcnow = datetime.now(timezone.utc)
|
825
834
|
timestamp = utcnow.strftime("UTC-%Y-%m-%d-%H-%M-%S")
|
826
835
|
if not outputFolder:
|
827
836
|
home = os.path.expanduser('~')
|
@@ -831,28 +840,32 @@ class EnergyModel:
|
|
831
840
|
os.mkdir(outputFolder)
|
832
841
|
pbar.update(10)
|
833
842
|
osmPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osm")
|
834
|
-
|
843
|
+
# DEBUGGING
|
844
|
+
#model.save(openstudio.openstudioutilitiescore.toPath(osmPath), True)
|
845
|
+
model.save(osmPath, True)
|
835
846
|
oswPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osw")
|
836
847
|
pbar.update(20)
|
837
|
-
#print("oswPath = "+oswPath)
|
838
848
|
workflow = model.workflowJSON()
|
839
|
-
|
849
|
+
# DEBUGGING
|
850
|
+
#workflow.setSeedFile(openstudio.openstudioutilitiescore.toPath(osmPath))
|
851
|
+
workflow.setSeedFile(osmPath)
|
840
852
|
pbar.update(30)
|
841
|
-
#
|
842
|
-
workflow.setWeatherFile(openstudio.openstudioutilitiescore.toPath(weatherFilePath))
|
853
|
+
# DEBUGGING
|
854
|
+
#workflow.setWeatherFile(openstudio.openstudioutilitiescore.toPath(weatherFilePath))
|
855
|
+
workflow.setWeatherFile(weatherFilePath)
|
843
856
|
pbar.update(40)
|
844
|
-
#
|
845
|
-
workflow.saveAs(openstudio.openstudioutilitiescore.toPath(oswPath))
|
857
|
+
# DEBUGGING
|
858
|
+
#workflow.saveAs(openstudio.openstudioutilitiescore.toPath(oswPath))
|
859
|
+
workflow.saveAs(oswPath)
|
846
860
|
pbar.update(50)
|
847
|
-
#print("OSW File Saved")
|
848
861
|
cmd = osBinaryPath+" run -w " + "\"" + oswPath + "\""
|
849
862
|
pbar.update(60)
|
850
863
|
os.system(cmd)
|
851
|
-
#print("Simulation DONE")
|
852
864
|
sqlPath = os.path.join(os.path.join(outputFolder,"run"), "eplusout.sql")
|
853
865
|
pbar.update(100)
|
854
|
-
#
|
855
|
-
osSqlFile = openstudio.SqlFile(openstudio.openstudioutilitiescore.toPath(sqlPath))
|
866
|
+
# DEBUGGING
|
867
|
+
#osSqlFile = openstudio.SqlFile(openstudio.openstudioutilitiescore.toPath(sqlPath))
|
868
|
+
osSqlFile = openstudio.SqlFile(sqlPath)
|
856
869
|
model.setSqlFile(osSqlFile)
|
857
870
|
pbar.close()
|
858
871
|
return model
|
topologicpy/Plotly.py
CHANGED
@@ -994,8 +994,8 @@ class Plotly:
|
|
994
994
|
minValue=None,
|
995
995
|
maxValue=None,
|
996
996
|
title="Confusion Matrix",
|
997
|
-
xTitle = "Actual",
|
998
|
-
yTitle = "Predicted",
|
997
|
+
xTitle = "Actual Categories",
|
998
|
+
yTitle = "Predicted Categories",
|
999
999
|
width=950,
|
1000
1000
|
height=500,
|
1001
1001
|
showScale = True,
|
@@ -1022,9 +1022,9 @@ class Plotly:
|
|
1022
1022
|
title : str , optional
|
1023
1023
|
The desired title to display. The default is "Confusion Matrix".
|
1024
1024
|
xTitle : str , optional
|
1025
|
-
The desired X-axis title to display. The default is "Actual".
|
1025
|
+
The desired X-axis title to display. The default is "Actual Categories".
|
1026
1026
|
yTitle : str , optional
|
1027
|
-
The desired Y-axis title to display. The default is "Predicted".
|
1027
|
+
The desired Y-axis title to display. The default is "Predicted Categories".
|
1028
1028
|
width : int , optional
|
1029
1029
|
The desired width of the figure. The default is 950.
|
1030
1030
|
height : int , optional
|
@@ -1051,7 +1051,11 @@ class Plotly:
|
|
1051
1051
|
The desired top margin in pixels. The default is 40.
|
1052
1052
|
marginBottom : int , optional
|
1053
1053
|
The desired bottom margin in pixels. The default is 0.
|
1054
|
-
|
1054
|
+
|
1055
|
+
Returns
|
1056
|
+
-------
|
1057
|
+
plotly.Figure
|
1058
|
+
The created plotly figure.
|
1055
1059
|
"""
|
1056
1060
|
try:
|
1057
1061
|
import numpy as np
|
@@ -1265,7 +1269,158 @@ class Plotly:
|
|
1265
1269
|
fig.update_xaxes( tickvals=xCategories)
|
1266
1270
|
fig.update_yaxes( tickvals=yCategories)
|
1267
1271
|
return fig
|
1272
|
+
|
1273
|
+
@staticmethod
|
1274
|
+
def FigureByCorrelation(actual,
|
1275
|
+
predicted,
|
1276
|
+
title="Correlation between Actual and Predicted Values",
|
1277
|
+
xTitle = "Actual Values",
|
1278
|
+
yTitle = "Predicted Values",
|
1279
|
+
dotColor = "blue",
|
1280
|
+
lineColor = "red",
|
1281
|
+
width=800,
|
1282
|
+
height=600,
|
1283
|
+
theme='default',
|
1284
|
+
backgroundColor='rgba(0,0,0,0)',
|
1285
|
+
marginLeft=0,
|
1286
|
+
marginRight=0,
|
1287
|
+
marginTop=40,
|
1288
|
+
marginBottom=0):
|
1289
|
+
"""
|
1290
|
+
Returns a Plotly Figure showing the correlation between the input actual and predicted values. Actual values are displayed on the X-Axis, Predicted values are displayed on the Y-Axis.
|
1291
|
+
|
1292
|
+
Parameters
|
1293
|
+
----------
|
1294
|
+
actual : list
|
1295
|
+
The actual values to display.
|
1296
|
+
predicted : list
|
1297
|
+
The predicted values to display.
|
1298
|
+
title : str , optional
|
1299
|
+
The desired title to display. The default is "Correlation between Actual and Predicted Values".
|
1300
|
+
xTitle : str , optional
|
1301
|
+
The desired X-axis title to display. The default is "Actual Values".
|
1302
|
+
yTitle : str , optional
|
1303
|
+
The desired Y-axis title to display. The default is "Predicted Values".
|
1304
|
+
dotColor : str , optional
|
1305
|
+
The desired color of the dots. This can be any plotly color string and may be specified as:
|
1306
|
+
- A hex string (e.g. '#ff0000')
|
1307
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
1308
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
1309
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
1310
|
+
- A named CSS color.
|
1311
|
+
The default is 'blue'.
|
1312
|
+
lineColor : str , optional
|
1313
|
+
The desired color of the best fit line. This can be any plotly color string and may be specified as:
|
1314
|
+
- A hex string (e.g. '#ff0000')
|
1315
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
1316
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
1317
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
1318
|
+
- A named CSS color.
|
1319
|
+
The default is 'red'.
|
1320
|
+
width : int , optional
|
1321
|
+
The desired width of the figure. The default is 800.
|
1322
|
+
height : int , optional
|
1323
|
+
The desired height of the figure. The default is 600.
|
1324
|
+
theme : str , optional
|
1325
|
+
The plotly color scheme to use. The options are "dark", "light", "default". The default is "default".
|
1326
|
+
backgroundColor : str , optional
|
1327
|
+
The desired background color. This can be any plotly color string and may be specified as:
|
1328
|
+
- A hex string (e.g. '#ff0000')
|
1329
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
1330
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
1331
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
1332
|
+
- A named CSS color.
|
1333
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
1334
|
+
marginLeft : int , optional
|
1335
|
+
The desired left margin in pixels. The default is 0.
|
1336
|
+
marginRight : int , optional
|
1337
|
+
The desired right margin in pixels. The default is 0.
|
1338
|
+
marginTop : int , optional
|
1339
|
+
The desired top margin in pixels. The default is 40.
|
1340
|
+
marginBottom : int , optional
|
1341
|
+
The desired bottom margin in pixels. The default is 0.
|
1342
|
+
|
1343
|
+
Returns
|
1344
|
+
-------
|
1345
|
+
plotly.Figure
|
1346
|
+
The created plotly figure.
|
1268
1347
|
|
1348
|
+
"""
|
1349
|
+
|
1350
|
+
import numpy as np
|
1351
|
+
import plotly.graph_objs as go
|
1352
|
+
from sklearn.linear_model import LinearRegression
|
1353
|
+
import plotly.io as pio
|
1354
|
+
actual_values = np.array(actual)
|
1355
|
+
predicted_values = np.array(predicted)
|
1356
|
+
|
1357
|
+
# Validate the theme input
|
1358
|
+
if theme == 'light':
|
1359
|
+
pio.templates.default = "plotly_white"
|
1360
|
+
backgroundColor='white'
|
1361
|
+
elif theme == 'dark':
|
1362
|
+
pio.templates.default = "plotly_dark"
|
1363
|
+
backgroundColor='black'
|
1364
|
+
else:
|
1365
|
+
pio.templates.default = None # Use default Plotly theme
|
1366
|
+
|
1367
|
+
# Calculate the best-fit line using linear regression
|
1368
|
+
regressor = LinearRegression()
|
1369
|
+
regressor.fit(np.array(actual_values).reshape(-1, 1), np.array(predicted_values))
|
1370
|
+
line = regressor.predict(np.array(actual_values).reshape(-1, 1))
|
1371
|
+
|
1372
|
+
# Determine the range and tick step
|
1373
|
+
combined_values = np.concatenate([actual_values, predicted_values])
|
1374
|
+
min_value = np.min(combined_values)
|
1375
|
+
max_value = np.max(combined_values)
|
1376
|
+
margin = 0.1 * (max_value - min_value)
|
1377
|
+
tick_range = [min_value - margin, max_value + margin]
|
1378
|
+
tick_step = (max_value - min_value) / 10 # Adjust as needed for a different number of ticks
|
1379
|
+
|
1380
|
+
# Create the scatter plot for actual vs predicted values
|
1381
|
+
scatter_trace = go.Scatter(
|
1382
|
+
x=actual_values,
|
1383
|
+
y=predicted_values,
|
1384
|
+
mode='markers',
|
1385
|
+
name='Actual vs. Predicted',
|
1386
|
+
marker=dict(color=dotColor)
|
1387
|
+
)
|
1388
|
+
|
1389
|
+
# Create the line of best fit
|
1390
|
+
line_trace = go.Scatter(
|
1391
|
+
x=actual_values,
|
1392
|
+
y=line,
|
1393
|
+
mode='lines',
|
1394
|
+
name='Best Fit Line',
|
1395
|
+
line=dict(color=lineColor)
|
1396
|
+
)
|
1397
|
+
|
1398
|
+
# Create the 45-degree line
|
1399
|
+
line_45_trace = go.Scatter(
|
1400
|
+
x=tick_range,
|
1401
|
+
y=tick_range,
|
1402
|
+
mode='lines',
|
1403
|
+
name='45-Degree Line',
|
1404
|
+
line=dict(color='green', dash='dash')
|
1405
|
+
)
|
1406
|
+
|
1407
|
+
# Combine the traces into a single figure
|
1408
|
+
layout = {
|
1409
|
+
"title": title,
|
1410
|
+
"width": width,
|
1411
|
+
"height": height,
|
1412
|
+
"xaxis": {"title": xTitle, "range":tick_range, "dtick":tick_step},
|
1413
|
+
"yaxis": {"title": yTitle, "range":tick_range, "dtick":tick_step},
|
1414
|
+
"showlegend": True,
|
1415
|
+
"paper_bgcolor": backgroundColor,
|
1416
|
+
"plot_bgcolor": backgroundColor,
|
1417
|
+
"margin":dict(l=marginLeft, r=marginRight, t=marginTop, b=marginBottom)
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
fig = go.Figure(data=[scatter_trace, line_trace, line_45_trace], layout=layout)
|
1421
|
+
|
1422
|
+
return fig
|
1423
|
+
|
1269
1424
|
@staticmethod
|
1270
1425
|
def FigureByDataFrame(dataFrame,
|
1271
1426
|
labels=[],
|
topologicpy/PyG.py
CHANGED
@@ -30,11 +30,27 @@ from sklearn.metrics import accuracy_score
|
|
30
30
|
from tqdm.auto import tqdm
|
31
31
|
import gc
|
32
32
|
|
33
|
+
import torch
|
34
|
+
from torch.utils.data import Dataset
|
35
|
+
|
36
|
+
import torch
|
37
|
+
from torch.utils.data import Dataset
|
33
38
|
|
34
39
|
class CustomGraphDataset(Dataset):
|
35
|
-
def __init__(self, root, node_level=False, graph_level=True,
|
36
|
-
|
37
|
-
|
40
|
+
def __init__(self, root=None, data_list=None, indices=None, node_level=False, graph_level=True,
|
41
|
+
node_attr_key='feat', edge_attr_key='feat'):
|
42
|
+
"""
|
43
|
+
Initializes the CustomGraphDataset.
|
44
|
+
|
45
|
+
Parameters:
|
46
|
+
- root: Root directory of the dataset (used only if data_list is None)
|
47
|
+
- data_list: List of preprocessed data objects (used if provided)
|
48
|
+
- indices: List of indices to select a subset of the data
|
49
|
+
- node_level: Boolean flag indicating if the dataset is node-level
|
50
|
+
- graph_level: Boolean flag indicating if the dataset is graph-level
|
51
|
+
- node_attr_key: Key for node attributes
|
52
|
+
- edge_attr_key: Key for edge attributes
|
53
|
+
"""
|
38
54
|
assert not (node_level and graph_level), "Both node_level and graph_level cannot be True at the same time"
|
39
55
|
assert node_level or graph_level, "Both node_level and graph_level cannot be False at the same time"
|
40
56
|
|
@@ -43,15 +59,20 @@ class CustomGraphDataset(Dataset):
|
|
43
59
|
self.node_attr_key = node_attr_key
|
44
60
|
self.edge_attr_key = edge_attr_key
|
45
61
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
62
|
+
if data_list is not None:
|
63
|
+
self.data_list = data_list # Use the provided data list
|
64
|
+
elif root is not None:
|
65
|
+
# Load and process data from root directory if data_list is not provided
|
66
|
+
self.graph_df = pd.read_csv(os.path.join(root, 'graphs.csv'))
|
67
|
+
self.nodes_df = pd.read_csv(os.path.join(root, 'nodes.csv'))
|
68
|
+
self.edges_df = pd.read_csv(os.path.join(root, 'edges.csv'))
|
69
|
+
self.data_list = self.process_all()
|
70
|
+
else:
|
71
|
+
raise ValueError("Either a root directory or a data_list must be provided.")
|
51
72
|
|
52
|
-
|
53
|
-
|
54
|
-
|
73
|
+
# Filter data_list based on indices if provided
|
74
|
+
if indices is not None:
|
75
|
+
self.data_list = [self.data_list[i] for i in indices]
|
55
76
|
|
56
77
|
def process_all(self):
|
57
78
|
data_list = []
|
@@ -74,9 +95,24 @@ class CustomGraphDataset(Dataset):
|
|
74
95
|
edge_attr = None
|
75
96
|
|
76
97
|
if self.graph_level:
|
77
|
-
|
98
|
+
label_value = self.graph_df[self.graph_df['graph_id'] == graph_id]['label'].values[0]
|
99
|
+
|
100
|
+
if isinstance(label_value, int):
|
101
|
+
y = torch.tensor([label_value], dtype=torch.long)
|
102
|
+
elif isinstance(label_value, float):
|
103
|
+
y = torch.tensor([label_value], dtype=torch.float)
|
104
|
+
else:
|
105
|
+
raise ValueError(f"Unexpected label type: {type(label_value)}. Expected int or float.")
|
106
|
+
|
78
107
|
elif self.node_level:
|
79
|
-
|
108
|
+
label_values = graph_nodes['label'].values
|
109
|
+
|
110
|
+
if issubclass(label_values.dtype.type, int):
|
111
|
+
y = torch.tensor(label_values, dtype=torch.long)
|
112
|
+
elif issubclass(label_values.dtype.type, float):
|
113
|
+
y = torch.tensor(label_values, dtype=torch.float)
|
114
|
+
else:
|
115
|
+
raise ValueError(f"Unexpected label types: {label_values.dtype}. Expected int or float.")
|
80
116
|
|
81
117
|
data = Data(x=x, edge_index=edge_index, y=y)
|
82
118
|
if edge_attr is not None:
|
@@ -86,14 +122,103 @@ class CustomGraphDataset(Dataset):
|
|
86
122
|
|
87
123
|
return data_list
|
88
124
|
|
89
|
-
def
|
125
|
+
def __len__(self):
|
90
126
|
return len(self.data_list)
|
91
127
|
|
92
|
-
def
|
128
|
+
def __getitem__(self, idx):
|
93
129
|
return self.data_list[idx]
|
94
130
|
|
95
|
-
|
96
|
-
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
# class CustomGraphDataset(Dataset):
|
135
|
+
# def __init__(self, root, node_level=False, graph_level=True, node_attr_key='feat',
|
136
|
+
# edge_attr_key='feat', transform=None, pre_transform=None):
|
137
|
+
# super(CustomGraphDataset, self).__init__(root, transform, pre_transform)
|
138
|
+
# assert not (node_level and graph_level), "Both node_level and graph_level cannot be True at the same time"
|
139
|
+
# assert node_level or graph_level, "Both node_level and graph_level cannot be False at the same time"
|
140
|
+
|
141
|
+
# self.node_level = node_level
|
142
|
+
# self.graph_level = graph_level
|
143
|
+
# self.node_attr_key = node_attr_key
|
144
|
+
# self.edge_attr_key = edge_attr_key
|
145
|
+
|
146
|
+
# self.graph_df = pd.read_csv(os.path.join(root, 'graphs.csv'))
|
147
|
+
# self.nodes_df = pd.read_csv(os.path.join(root, 'nodes.csv'))
|
148
|
+
# self.edges_df = pd.read_csv(os.path.join(root, 'edges.csv'))
|
149
|
+
|
150
|
+
# self.data_list = self.process_all()
|
151
|
+
|
152
|
+
# @property
|
153
|
+
# def raw_file_names(self):
|
154
|
+
# return ['graphs.csv', 'nodes.csv', 'edges.csv']
|
155
|
+
|
156
|
+
# def process_all(self):
|
157
|
+
# data_list = []
|
158
|
+
# for graph_id in self.graph_df['graph_id'].unique():
|
159
|
+
# graph_nodes = self.nodes_df[self.nodes_df['graph_id'] == graph_id]
|
160
|
+
# graph_edges = self.edges_df[self.edges_df['graph_id'] == graph_id]
|
161
|
+
|
162
|
+
# if self.node_attr_key in graph_nodes.columns and not graph_nodes[self.node_attr_key].isnull().all():
|
163
|
+
# x = torch.tensor(graph_nodes[self.node_attr_key].values.tolist(), dtype=torch.float)
|
164
|
+
# if x.ndim == 1:
|
165
|
+
# x = x.unsqueeze(1) # Ensure x has shape [num_nodes, *]
|
166
|
+
# else:
|
167
|
+
# x = None
|
168
|
+
|
169
|
+
# edge_index = torch.tensor(graph_edges[['src_id', 'dst_id']].values.T, dtype=torch.long)
|
170
|
+
|
171
|
+
# if self.edge_attr_key in graph_edges.columns and not graph_edges[self.edge_attr_key].isnull().all():
|
172
|
+
# edge_attr = torch.tensor(graph_edges[self.edge_attr_key].values.tolist(), dtype=torch.float)
|
173
|
+
# else:
|
174
|
+
# edge_attr = None
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
# if self.graph_level:
|
179
|
+
# label_value = self.graph_df[self.graph_df['graph_id'] == graph_id]['label'].values[0]
|
180
|
+
|
181
|
+
# # Check if the label is an integer or a float and cast accordingly
|
182
|
+
# if isinstance(label_value, int):
|
183
|
+
# y = torch.tensor([label_value], dtype=torch.long)
|
184
|
+
# elif isinstance(label_value, float):
|
185
|
+
# y = torch.tensor([label_value], dtype=torch.float)
|
186
|
+
# else:
|
187
|
+
# raise ValueError(f"Unexpected label type: {type(label_value)}. Expected int or float.")
|
188
|
+
|
189
|
+
# elif self.node_level:
|
190
|
+
# label_values = graph_nodes['label'].values
|
191
|
+
|
192
|
+
# # Check if the labels are integers or floats and cast accordingly
|
193
|
+
# if issubclass(label_values.dtype.type, int):
|
194
|
+
# y = torch.tensor(label_values, dtype=torch.long)
|
195
|
+
# elif issubclass(label_values.dtype.type, float):
|
196
|
+
# y = torch.tensor(label_values, dtype=torch.float)
|
197
|
+
# else:
|
198
|
+
# raise ValueError(f"Unexpected label types: {label_values.dtype}. Expected int or float.")
|
199
|
+
|
200
|
+
|
201
|
+
# # if self.graph_level:
|
202
|
+
# # y = torch.tensor([self.graph_df[self.graph_df['graph_id'] == graph_id]['label'].values[0]], dtype=torch.long)
|
203
|
+
# # elif self.node_level:
|
204
|
+
# # y = torch.tensor(graph_nodes['label'].values, dtype=torch.long)
|
205
|
+
|
206
|
+
# data = Data(x=x, edge_index=edge_index, y=y)
|
207
|
+
# if edge_attr is not None:
|
208
|
+
# data.edge_attr = edge_attr
|
209
|
+
|
210
|
+
# data_list.append(data)
|
211
|
+
|
212
|
+
# return data_list
|
213
|
+
|
214
|
+
# def len(self):
|
215
|
+
# return len(self.data_list)
|
216
|
+
|
217
|
+
# def get(self, idx):
|
218
|
+
# return self.data_list[idx]
|
219
|
+
|
220
|
+
# def __getitem__(self, idx):
|
221
|
+
# return self.get(idx)
|
97
222
|
|
98
223
|
class _Hparams:
|
99
224
|
def __init__(self, model_type="ClassifierHoldout", optimizer_str="Adam", amsgrad=False, betas=(0.9, 0.999), eps=1e-6, lr=0.001, lr_decay= 0, maximize=False, rho=0.9, weight_decay=0, cv_type="Holdout", split=[0.8,0.1, 0.1], k_folds=5, hl_widths=[32], conv_layer_type='SAGEConv', pooling="AvgPooling", batch_size=32, epochs=1,
|
@@ -350,7 +475,8 @@ class _GraphRegressorKFold:
|
|
350
475
|
|
351
476
|
def _initialize_model(self, hparams, dataset):
|
352
477
|
if hparams.conv_layer_type.lower() == 'sageconv':
|
353
|
-
return _SAGEConv(dataset.num_node_features, hparams.hl_widths, 1, hparams.pooling).to(self.device)
|
478
|
+
return _SAGEConv(dataset[0].num_node_features, hparams.hl_widths, 1, hparams.pooling).to(self.device)
|
479
|
+
#return _SAGEConv(dataset.num_node_features, hparams.hl_widths, 1, hparams.pooling).to(self.device)
|
354
480
|
else:
|
355
481
|
raise NotImplementedError
|
356
482
|
|
@@ -1411,6 +1537,83 @@ class PyG:
|
|
1411
1537
|
|
1412
1538
|
return CustomGraphDataset(root=path, node_level=node_level, graph_level=graph_level, node_attr_key=nodeATTRKey, edge_attr_key=edgeATTRKey)
|
1413
1539
|
|
1540
|
+
@staticmethod
|
1541
|
+
def DatasetGraphLabels(dataset, graphLabelHeader="label"):
|
1542
|
+
"""
|
1543
|
+
Returns the labels of the graphs in the input dataset
|
1544
|
+
|
1545
|
+
Parameters
|
1546
|
+
----------
|
1547
|
+
dataset : CustomDataset
|
1548
|
+
The input dataset
|
1549
|
+
graphLabelHeader: str , optional
|
1550
|
+
The key string under which the graph labels are stored. The default is "label".
|
1551
|
+
|
1552
|
+
Returns
|
1553
|
+
-------
|
1554
|
+
list
|
1555
|
+
The list of graph labels.
|
1556
|
+
"""
|
1557
|
+
import torch
|
1558
|
+
|
1559
|
+
graph_labels = []
|
1560
|
+
for g in dataset:
|
1561
|
+
# Get the label of the graph
|
1562
|
+
label = g.y
|
1563
|
+
graph_labels.append(label.item())
|
1564
|
+
return graph_labels
|
1565
|
+
|
1566
|
+
@staticmethod
|
1567
|
+
def DatasetSplit(dataset, split=[0.8,0.1,0.1], shuffle=True, randomState=42):
|
1568
|
+
"""
|
1569
|
+
Splits the dataset into three subsets.
|
1570
|
+
|
1571
|
+
Parameters
|
1572
|
+
----------
|
1573
|
+
dataset : CustomDataset
|
1574
|
+
The input dataset
|
1575
|
+
split: list , optional
|
1576
|
+
The list of ratios. This list must be made out of three numbers adding to 1.
|
1577
|
+
shuffle: boolean , optional
|
1578
|
+
If set to True, the subsets are created from random indices. Otherwise, they are split sequentially. The default is True.
|
1579
|
+
randomState : int , optional
|
1580
|
+
The random seed to use for reproducibility. The default is 42.
|
1581
|
+
|
1582
|
+
Returns
|
1583
|
+
-------
|
1584
|
+
list
|
1585
|
+
The list of three subset datasets.
|
1586
|
+
"""
|
1587
|
+
|
1588
|
+
import torch
|
1589
|
+
from torch.utils.data import random_split
|
1590
|
+
train_ratio, val_ratio, test_ratio = split
|
1591
|
+
assert abs(train_ratio + val_ratio + test_ratio - 1.0) < 1e-6, "Ratios must add up to 1."
|
1592
|
+
|
1593
|
+
# Calculate the number of samples for each split
|
1594
|
+
dataset_len = len(dataset)
|
1595
|
+
train_len = int(train_ratio * dataset_len)
|
1596
|
+
val_len = int(val_ratio * dataset_len)
|
1597
|
+
test_len = dataset_len - train_len - val_len # Ensure it adds up correctly
|
1598
|
+
|
1599
|
+
## Generate indices for the split
|
1600
|
+
indices = list(range(dataset_len))
|
1601
|
+
if shuffle:
|
1602
|
+
torch.manual_seed(randomState) # For reproducibility
|
1603
|
+
indices = torch.randperm(dataset_len).tolist() # Shuffled indices
|
1604
|
+
|
1605
|
+
# Create splits
|
1606
|
+
train_indices = indices[:train_len]
|
1607
|
+
val_indices = indices[train_len:train_len + val_len]
|
1608
|
+
test_indices = indices[train_len + val_len:train_len + val_len + test_len]
|
1609
|
+
|
1610
|
+
# Create new instances of CustomGraphDataset using the indices
|
1611
|
+
train_dataset = CustomGraphDataset(data_list=dataset.data_list, indices=train_indices)
|
1612
|
+
val_dataset = CustomGraphDataset(data_list=dataset.data_list, indices=val_indices)
|
1613
|
+
test_dataset = CustomGraphDataset(data_list=dataset.data_list, indices=test_indices)
|
1614
|
+
|
1615
|
+
return train_dataset, val_dataset, test_dataset
|
1616
|
+
|
1414
1617
|
@staticmethod
|
1415
1618
|
def Optimizer(name="Adam", amsgrad=True, betas=(0.9,0.999), eps=0.000001, lr=0.001, maximize=False, weightDecay=0.0, rho=0.9, lr_decay=0.0):
|
1416
1619
|
"""
|
@@ -1529,11 +1732,11 @@ class PyG:
|
|
1529
1732
|
----------
|
1530
1733
|
hparams : HParams
|
1531
1734
|
The input hyperparameters
|
1532
|
-
trainingDataset :
|
1735
|
+
trainingDataset : CustomDataset
|
1533
1736
|
The input training dataset.
|
1534
|
-
validationDataset :
|
1737
|
+
validationDataset : CustomDataset
|
1535
1738
|
The input validation dataset. If not specified, a portion of the trainingDataset will be used for validation according the to the split list as specified in the hyper-parameters.
|
1536
|
-
testingDataset :
|
1739
|
+
testingDataset : CustomDataset
|
1537
1740
|
The input testing dataset. If not specified, a portion of the trainingDataset will be used for testing according the to the split list as specified in the hyper-parameters.
|
1538
1741
|
|
1539
1742
|
Returns
|
@@ -1635,13 +1838,13 @@ class PyG:
|
|
1635
1838
|
import os
|
1636
1839
|
|
1637
1840
|
if model == None:
|
1638
|
-
print("
|
1841
|
+
print("PyG.ModelSave - Error: The input model parameter is invalid. Returning None.")
|
1639
1842
|
return None
|
1640
1843
|
if path == None:
|
1641
|
-
print("
|
1844
|
+
print("PyG.ModelSave - Error: The input path parameter is invalid. Returning None.")
|
1642
1845
|
return None
|
1643
1846
|
if not overwrite and os.path.exists(path):
|
1644
|
-
print("
|
1847
|
+
print("PyG.ModelSave - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
|
1645
1848
|
return None
|
1646
1849
|
if overwrite and os.path.exists(path):
|
1647
1850
|
os.remove(path)
|
@@ -1893,7 +2096,7 @@ class PyG:
|
|
1893
2096
|
from sklearn import metrics
|
1894
2097
|
from sklearn.metrics import accuracy_score
|
1895
2098
|
except:
|
1896
|
-
print("
|
2099
|
+
print("PyG - Installing required scikit-learn (sklearn) library.")
|
1897
2100
|
try:
|
1898
2101
|
os.system("pip install scikit-learn")
|
1899
2102
|
except:
|
@@ -1901,19 +2104,19 @@ class PyG:
|
|
1901
2104
|
try:
|
1902
2105
|
from sklearn import metrics
|
1903
2106
|
from sklearn.metrics import accuracy_score
|
1904
|
-
print("
|
2107
|
+
print("PyG - scikit-learn (sklearn) library installed correctly.")
|
1905
2108
|
except:
|
1906
|
-
warnings.warn("
|
2109
|
+
warnings.warn("PyG - Error: Could not import scikit-learn (sklearn). Please try to install scikit-learn manually. Returning None.")
|
1907
2110
|
return None
|
1908
2111
|
|
1909
2112
|
if not isinstance(actual, list):
|
1910
|
-
print("
|
2113
|
+
print("PyG.ConfusionMatrix - ERROR: The actual input is not a list. Returning None")
|
1911
2114
|
return None
|
1912
2115
|
if not isinstance(predicted, list):
|
1913
|
-
print("
|
2116
|
+
print("PyG.ConfusionMatrix - ERROR: The predicted input is not a list. Returning None")
|
1914
2117
|
return None
|
1915
2118
|
if len(actual) != len(predicted):
|
1916
|
-
print("
|
2119
|
+
print("PyG.ConfusionMatrix - ERROR: The two input lists do not have the same length. Returning None")
|
1917
2120
|
return None
|
1918
2121
|
if normalize:
|
1919
2122
|
cm = np.transpose(metrics.confusion_matrix(y_true=actual, y_pred=predicted, normalize="true"))
|
@@ -2065,3 +2268,58 @@ class PyG:
|
|
2065
2268
|
size = len(predicted)
|
2066
2269
|
|
2067
2270
|
return {"mse": mse, "size": size}
|
2271
|
+
|
2272
|
+
@staticmethod
|
2273
|
+
def Performance(actual, predicted, mantissa: int = 6):
|
2274
|
+
"""
|
2275
|
+
Computes regression model performance measures. This is to be used only with regression not with classification.
|
2276
|
+
|
2277
|
+
Parameters
|
2278
|
+
----------
|
2279
|
+
actual : list
|
2280
|
+
The input list of actual values.
|
2281
|
+
predicted : list
|
2282
|
+
The input list of predicted values.
|
2283
|
+
mantissa : int , optional
|
2284
|
+
The desired length of the mantissa. The default is 6.
|
2285
|
+
|
2286
|
+
Returns
|
2287
|
+
-------
|
2288
|
+
dict
|
2289
|
+
The dictionary containing the performance measures. The keys in the dictionary are: 'mae', 'mape', 'mse', 'r', 'r2', 'rmse'.
|
2290
|
+
"""
|
2291
|
+
|
2292
|
+
if not isinstance(actual, list):
|
2293
|
+
print("PyG.Performance - ERROR: The actual input is not a list. Returning None")
|
2294
|
+
return None
|
2295
|
+
if not isinstance(predicted, list):
|
2296
|
+
print("PyG.Performance - ERROR: The predicted input is not a list. Returning None")
|
2297
|
+
return None
|
2298
|
+
if not (len(actual) == len(predicted)):
|
2299
|
+
print("PyG.Performance - ERROR: The actual and predicted input lists have different lengths. Returning None")
|
2300
|
+
return None
|
2301
|
+
|
2302
|
+
predicted = np.array(predicted)
|
2303
|
+
actual = np.array(actual)
|
2304
|
+
|
2305
|
+
mae = np.mean(np.abs(predicted - actual))
|
2306
|
+
mape = np.mean(np.abs((actual - predicted) / actual))*100
|
2307
|
+
mse = np.mean((predicted - actual)**2)
|
2308
|
+
correlation_matrix = np.corrcoef(predicted, actual)
|
2309
|
+
r = correlation_matrix[0, 1]
|
2310
|
+
r2 = r**2
|
2311
|
+
absolute_errors = np.abs(predicted - actual)
|
2312
|
+
mean_actual = np.mean(actual)
|
2313
|
+
if mean_actual == 0:
|
2314
|
+
rae = None
|
2315
|
+
else:
|
2316
|
+
rae = np.mean(absolute_errors) / mean_actual
|
2317
|
+
rmse = np.sqrt(mse)
|
2318
|
+
return {'mae': round(mae, mantissa),
|
2319
|
+
'mape': round(mape, mantissa),
|
2320
|
+
'mse': round(mse, mantissa),
|
2321
|
+
'r': round(r, mantissa),
|
2322
|
+
'r2': round(r2, mantissa),
|
2323
|
+
'rae': round(rae, mantissa),
|
2324
|
+
'rmse': round(rmse, mantissa)
|
2325
|
+
}
|
topologicpy/Shell.py
CHANGED
@@ -1056,6 +1056,110 @@ class Shell():
|
|
1056
1056
|
"""
|
1057
1057
|
return shell.IsClosed()
|
1058
1058
|
|
1059
|
+
|
1060
|
+
@staticmethod
|
1061
|
+
def ParabolicSurface(origin= None, focalLength=0.125, width: float = 1, length: float = 1, uSides: int = 16, vSides: int = 16,
|
1062
|
+
direction: list = [0, 0, 1], placement: str ="center", mantissa: int = 6, tolerance: float = 0.0001):
|
1063
|
+
"""
|
1064
|
+
Creates a parabolic surface.
|
1065
|
+
|
1066
|
+
Parameters
|
1067
|
+
----------
|
1068
|
+
origin : topologic_core.Vertex , optional
|
1069
|
+
The origin location of the parabolic surface. The default is None which results in the parabolic surface being placed at (0, 0, 0).
|
1070
|
+
focalLength : float , optional
|
1071
|
+
The focal length of the parabola. The default is 1.
|
1072
|
+
width : float , optional
|
1073
|
+
The width of the parabolic surface. The default is 1.
|
1074
|
+
length : float , optional
|
1075
|
+
The length of the parabolic surface. The default is 1.
|
1076
|
+
uSides : int , optional
|
1077
|
+
The number of sides along the width. The default is 16.
|
1078
|
+
vSides : int , optional
|
1079
|
+
The number of sides along the length. The default is 16.
|
1080
|
+
direction : list , optional
|
1081
|
+
The vector representing the up direction of the parabolic surface. The default is [0, 0, 1].
|
1082
|
+
placement : str , optional
|
1083
|
+
The description of the placement of the origin of the parabolic surface. This can be "bottom", "center", or "lowerleft". It is case insensitive. The default is "center".
|
1084
|
+
mantissa : int , optional
|
1085
|
+
The desired length of the mantissa. The default is 6.
|
1086
|
+
tolerance : float , optional
|
1087
|
+
The desired tolerance. The default is 0.0001.
|
1088
|
+
|
1089
|
+
Returns
|
1090
|
+
-------
|
1091
|
+
topologic_core.Shell
|
1092
|
+
The created parabolic surface.
|
1093
|
+
|
1094
|
+
"""
|
1095
|
+
from topologicpy.Vertex import Vertex
|
1096
|
+
from topologicpy.Wire import Wire
|
1097
|
+
from topologicpy.Face import Face
|
1098
|
+
from topologicpy.Topology import Topology
|
1099
|
+
|
1100
|
+
def create_triangulated_mesh(vertices, uSides, vSides):
|
1101
|
+
faces = []
|
1102
|
+
|
1103
|
+
# Iterate over the grid of vertices to form triangular faces
|
1104
|
+
for i in range(uSides - 1):
|
1105
|
+
for j in range(vSides - 1):
|
1106
|
+
# Get the indices of the vertices forming the current grid cell
|
1107
|
+
v1 = vertices[i * vSides + j]
|
1108
|
+
v2 = vertices[i * vSides + (j + 1)]
|
1109
|
+
v3 = vertices[(i + 1) * vSides + j]
|
1110
|
+
v4 = vertices[(i + 1) * vSides + (j + 1)]
|
1111
|
+
|
1112
|
+
# Create two triangles for each grid cell
|
1113
|
+
# Triangle 1: (v1, v2, v3)
|
1114
|
+
wire1 = Wire.ByVertices([v1, v2, v3])
|
1115
|
+
face1 = Face.ByWire(wire1)
|
1116
|
+
faces.append(face1)
|
1117
|
+
|
1118
|
+
# Triangle 2: (v3, v2, v4)
|
1119
|
+
wire2 = Wire.ByVertices([v3, v2, v4])
|
1120
|
+
face2 = Face.ByWire(wire2)
|
1121
|
+
faces.append(face2)
|
1122
|
+
|
1123
|
+
# Create the mesh (Shell) from the list of faces
|
1124
|
+
mesh = Shell.ByFaces(faces)
|
1125
|
+
return mesh
|
1126
|
+
|
1127
|
+
if not Topology.IsInstance(origin, "Vertex"):
|
1128
|
+
origin = Vertex.Origin()
|
1129
|
+
|
1130
|
+
x_range = [-width*0.5, width*0.5]
|
1131
|
+
y_range = [-length*0.5, length*0.5]
|
1132
|
+
# Generate x and y values
|
1133
|
+
x_values = [x_range[0] + i * (x_range[1] - x_range[0]) / (uSides - 1) for i in range(uSides)]
|
1134
|
+
y_values = [y_range[0] + i * (y_range[1] - y_range[0]) / (vSides - 1) for i in range(vSides)]
|
1135
|
+
|
1136
|
+
# Create the grid and calculate Z values
|
1137
|
+
vertices = []
|
1138
|
+
|
1139
|
+
for x in x_values:
|
1140
|
+
for y in y_values:
|
1141
|
+
z = ((x)**2 + (y)**2) / (4 * focalLength)
|
1142
|
+
vertices.append(Vertex.ByCoordinates(x, y, z))
|
1143
|
+
|
1144
|
+
mesh = create_triangulated_mesh(vertices=vertices, uSides=uSides, vSides=vSides)
|
1145
|
+
if not placement.lower() == "bottom":
|
1146
|
+
x_list = [Vertex.X(v) for v in vertices]
|
1147
|
+
y_list = [Vertex.Y(v) for v in vertices]
|
1148
|
+
z_list = [Vertex.Z(v) for v in vertices]
|
1149
|
+
x_list.sort()
|
1150
|
+
y_list.sort()
|
1151
|
+
z_list.sort()
|
1152
|
+
width = abs(x_list[-1] - x_list[0])
|
1153
|
+
length = abs(y_list[-1] - y_list[0])
|
1154
|
+
height = abs(z_list[-1] - z_list[0])
|
1155
|
+
if placement.lower() == "center":
|
1156
|
+
mesh = Topology.Translate(mesh, 0, 0, -height*0.5)
|
1157
|
+
elif placement.lower() == "lowerleft":
|
1158
|
+
mesh = Topology.Translate(mesh, width*0.5, length*0.5, 0)
|
1159
|
+
|
1160
|
+
mesh = Topology.Orient(mesh, origin=origin, dirA=[0, 0, 1], dirB=direction, tolerance=tolerance)
|
1161
|
+
return mesh
|
1162
|
+
|
1059
1163
|
@staticmethod
|
1060
1164
|
def Pie(origin= None, radiusA: float = 0.5, radiusB: float = 0.0, sides: int = 32, rings: int = 1, fromAngle: float = 0.0, toAngle: float = 360.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
1061
1165
|
"""
|
topologicpy/Topology.py
CHANGED
@@ -2627,6 +2627,7 @@ class Topology():
|
|
2627
2627
|
if ap != None:
|
2628
2628
|
apertures.append(ap)
|
2629
2629
|
context = Context.ByTopologyParameters(topology, u=0.5, v=0.5, w=0.5)
|
2630
|
+
|
2630
2631
|
for ap in apertures:
|
2631
2632
|
_ = Aperture.ByTopologyContext(ap, context)
|
2632
2633
|
return topology
|
@@ -6308,7 +6309,7 @@ class Topology():
|
|
6308
6309
|
rot_vertices = [Vertex.ByCoordinates(rot_v) for rot_v in rot_vertices]
|
6309
6310
|
new_topology = Topology.ReplaceVertices(topology, verticesA=Topology.Vertices(topology), verticesB=rot_vertices)
|
6310
6311
|
new_topology = Topology.SelfMerge(new_topology, tolerance=tolerance)
|
6311
|
-
if len(Dictionary.Keys(d) > 0
|
6312
|
+
if len(Dictionary.Keys(d)) > 0:
|
6312
6313
|
new_topology = Topology.SetDictionary(new_topology, d)
|
6313
6314
|
return new_topology
|
6314
6315
|
if len(Dictionary.Keys(d)) > 0:
|
@@ -7875,7 +7876,6 @@ class Topology():
|
|
7875
7876
|
if Topology.IsInstance(topology, "Cell"):
|
7876
7877
|
sinkCells = [topology]
|
7877
7878
|
elif hidimSink >= Topology.TypeID("Cell"):
|
7878
|
-
print("Transfering Dictionaries to Cells")
|
7879
7879
|
sinkCells = Topology.Cells(topology)
|
7880
7880
|
_ = Topology.TransferDictionaries(selectors, sinkCells, tolerance=tolerance, numWorkers=numWorkers)
|
7881
7881
|
return topology
|
topologicpy/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.7.
|
1
|
+
__version__ = '0.7.44'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.44
|
4
4
|
Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
|
5
5
|
Author-email: Wassim Jabi <wassim.jabi@gmail.com>
|
6
6
|
License: MIT License
|
@@ -8,7 +8,7 @@ topologicpy/Context.py,sha256=ppApYKngZZCQBFWaxIMi2z2dokY23c935IDCBosxDAE,3055
|
|
8
8
|
topologicpy/DGL.py,sha256=Dd6O08D-vSxpjHYgKm45JpKiaeGvWlg1BRMzYMAXGNc,138991
|
9
9
|
topologicpy/Dictionary.py,sha256=KqJ29YyE23Y3Xc6XmKLSCZXRfBvm-OEOxlMZ4dt-rfM,27094
|
10
10
|
topologicpy/Edge.py,sha256=vhYHkobSLGSWV-oe2oJFFDobqFToDyb7s71yQ840AAA,65166
|
11
|
-
topologicpy/EnergyModel.py,sha256=
|
11
|
+
topologicpy/EnergyModel.py,sha256=XcCP55VW5WHDIIKcURijmBOZEgNUDEn_V9h5EejkntA,53876
|
12
12
|
topologicpy/Face.py,sha256=d1Im4ogxuaVmZyb6hgv5muwQwahLtGzOar_a3og1a_I,115376
|
13
13
|
topologicpy/Graph.py,sha256=p3VoVH6yygNV2wwzpsi4tm6yOfwRbtmsbnsAu2opLjQ,393517
|
14
14
|
topologicpy/Grid.py,sha256=3-sn7CHWGcXk18XCnHjsUttNJTWwmN63g_Insj__p04,18218
|
@@ -16,20 +16,20 @@ topologicpy/Helper.py,sha256=i-AfI29NMsZXBaymjilfvxQbuS3wpYbpPw4RWu1YCHs,16358
|
|
16
16
|
topologicpy/Honeybee.py,sha256=vcBECJlgWVjNNdD9ZmjNik_pA1Y_ZNoOorsQb2CiyGA,21965
|
17
17
|
topologicpy/Matrix.py,sha256=umgR7An919-wGInXJ1wpqnoQ2jCPdyMe2rcWTZ16upk,8079
|
18
18
|
topologicpy/Neo4j.py,sha256=YvtF7RYUMATEZ8iHwFwK_MOxEDyARby2DTI2CCK6-cI,19694
|
19
|
-
topologicpy/Plotly.py,sha256=
|
19
|
+
topologicpy/Plotly.py,sha256=U6Lo7hyDoStRKQXqlhb2LM-rR_bfBulxetRT2wMBmhI,105391
|
20
20
|
topologicpy/Polyskel.py,sha256=EFsuh2EwQJGPLiFUjvtXmAwdX-A4r_DxP5hF7Qd3PaU,19829
|
21
|
-
topologicpy/PyG.py,sha256=
|
22
|
-
topologicpy/Shell.py,sha256=
|
21
|
+
topologicpy/PyG.py,sha256=0yeECsMz-dqhhZSv52s_xPCO_3BcEXUK7z1YFDN9qoo,106987
|
22
|
+
topologicpy/Shell.py,sha256=NZyHYTvV0pXx18AoMbVs8y-7if8teETItv5ZOJq6gzE,84672
|
23
23
|
topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
|
24
24
|
topologicpy/Sun.py,sha256=InnKtX8eKwtAgcScuABH6yp0ljmWh5m_fDR4-n3jJMY,36869
|
25
|
-
topologicpy/Topology.py,sha256=
|
25
|
+
topologicpy/Topology.py,sha256=RFZPKx15qM53skLavdMwL_YnJkDIinOnz3CLAY5OsWE,366001
|
26
26
|
topologicpy/Vector.py,sha256=WQQUbwrg7VKImtxuBUi2i-FRiPT77WlrzLP05gdXKM8,33079
|
27
27
|
topologicpy/Vertex.py,sha256=EQdVYHmW85_pZdHZB3N8pEi0GiadCCkF3z_oqohA7B0,71161
|
28
28
|
topologicpy/Wire.py,sha256=9EJE0Iq3nGz5X7Suy6xxjmuOpfV49By6WH98UAL_7m4,153532
|
29
29
|
topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
|
30
|
-
topologicpy/version.py,sha256=
|
31
|
-
topologicpy-0.7.
|
32
|
-
topologicpy-0.7.
|
33
|
-
topologicpy-0.7.
|
34
|
-
topologicpy-0.7.
|
35
|
-
topologicpy-0.7.
|
30
|
+
topologicpy/version.py,sha256=2Sw5dX1m7XzP13Ernw7oNdPR5WsUzOMJ7VZ-QyJpf9o,23
|
31
|
+
topologicpy-0.7.44.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
|
32
|
+
topologicpy-0.7.44.dist-info/METADATA,sha256=N7KPudecCpJl9CdmpNEfoLiXYGpxcXZwegs6AvC1HTo,10916
|
33
|
+
topologicpy-0.7.44.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
34
|
+
topologicpy-0.7.44.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
|
35
|
+
topologicpy-0.7.44.dist-info/RECORD,,
|
File without changes
|
File without changes
|