topologicpy 0.7.42__py3-none-any.whl → 0.7.43__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/Plotly.py +160 -5
- topologicpy/PyG.py +170 -14
- topologicpy/Shell.py +104 -0
- topologicpy/version.py +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.43.dist-info}/METADATA +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.43.dist-info}/RECORD +9 -9
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.43.dist-info}/WHEEL +1 -1
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.43.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.42.dist-info → topologicpy-0.7.43.dist-info}/top_level.txt +0 -0
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
@@ -73,10 +73,35 @@ class CustomGraphDataset(Dataset):
|
|
73
73
|
else:
|
74
74
|
edge_attr = None
|
75
75
|
|
76
|
+
|
77
|
+
|
76
78
|
if self.graph_level:
|
77
|
-
|
79
|
+
label_value = self.graph_df[self.graph_df['graph_id'] == graph_id]['label'].values[0]
|
80
|
+
|
81
|
+
# Check if the label is an integer or a float and cast accordingly
|
82
|
+
if isinstance(label_value, int):
|
83
|
+
y = torch.tensor([label_value], dtype=torch.long)
|
84
|
+
elif isinstance(label_value, float):
|
85
|
+
y = torch.tensor([label_value], dtype=torch.float)
|
86
|
+
else:
|
87
|
+
raise ValueError(f"Unexpected label type: {type(label_value)}. Expected int or float.")
|
88
|
+
|
78
89
|
elif self.node_level:
|
79
|
-
|
90
|
+
label_values = graph_nodes['label'].values
|
91
|
+
|
92
|
+
# Check if the labels are integers or floats and cast accordingly
|
93
|
+
if issubclass(label_values.dtype.type, int):
|
94
|
+
y = torch.tensor(label_values, dtype=torch.long)
|
95
|
+
elif issubclass(label_values.dtype.type, float):
|
96
|
+
y = torch.tensor(label_values, dtype=torch.float)
|
97
|
+
else:
|
98
|
+
raise ValueError(f"Unexpected label types: {label_values.dtype}. Expected int or float.")
|
99
|
+
|
100
|
+
|
101
|
+
# if self.graph_level:
|
102
|
+
# y = torch.tensor([self.graph_df[self.graph_df['graph_id'] == graph_id]['label'].values[0]], dtype=torch.long)
|
103
|
+
# elif self.node_level:
|
104
|
+
# y = torch.tensor(graph_nodes['label'].values, dtype=torch.long)
|
80
105
|
|
81
106
|
data = Data(x=x, edge_index=edge_index, y=y)
|
82
107
|
if edge_attr is not None:
|
@@ -1411,6 +1436,82 @@ class PyG:
|
|
1411
1436
|
|
1412
1437
|
return CustomGraphDataset(root=path, node_level=node_level, graph_level=graph_level, node_attr_key=nodeATTRKey, edge_attr_key=edgeATTRKey)
|
1413
1438
|
|
1439
|
+
@staticmethod
|
1440
|
+
def DatasetGraphLabels(dataset, graphLabelHeader="label"):
|
1441
|
+
"""
|
1442
|
+
Returns the labels of the graphs in the input dataset
|
1443
|
+
|
1444
|
+
Parameters
|
1445
|
+
----------
|
1446
|
+
dataset : CustomDataset
|
1447
|
+
The input dataset
|
1448
|
+
graphLabelHeader: str , optional
|
1449
|
+
The key string under which the graph labels are stored. The default is "label".
|
1450
|
+
|
1451
|
+
Returns
|
1452
|
+
-------
|
1453
|
+
list
|
1454
|
+
The list of graph labels.
|
1455
|
+
"""
|
1456
|
+
import torch
|
1457
|
+
|
1458
|
+
graph_labels = []
|
1459
|
+
for g in dataset:
|
1460
|
+
# Get the label of the graph
|
1461
|
+
label = g.y
|
1462
|
+
graph_labels.append(label.item())
|
1463
|
+
return graph_labels
|
1464
|
+
|
1465
|
+
@staticmethod
|
1466
|
+
def DatasetSplit(dataset, split=[0.8,0.1,0.1], shuffle=True, randomState=42):
|
1467
|
+
"""
|
1468
|
+
Splits the dataset into three subsets.
|
1469
|
+
|
1470
|
+
Parameters
|
1471
|
+
----------
|
1472
|
+
dataset : CustomDataset
|
1473
|
+
The input dataset
|
1474
|
+
split: list , optional
|
1475
|
+
The list of ratios. This list must be made out of three numbers adding to 1.
|
1476
|
+
shuffle: boolean , optional
|
1477
|
+
If set to True, the subsets are created from random indices. Otherwise, they are split sequentially. The default is True.
|
1478
|
+
randomState : int , optional
|
1479
|
+
The random seed to use for reproducibility. The default is 42.
|
1480
|
+
|
1481
|
+
Returns
|
1482
|
+
-------
|
1483
|
+
list
|
1484
|
+
The list of three subset datasets.
|
1485
|
+
"""
|
1486
|
+
|
1487
|
+
import torch
|
1488
|
+
from torch.utils.data import random_split, Subset
|
1489
|
+
train_ratio, val_ratio, test_ratio = split
|
1490
|
+
assert abs(train_ratio + val_ratio + test_ratio - 1.0) < 1e-6, "Ratios must add up to 1."
|
1491
|
+
|
1492
|
+
# Calculate the number of samples for each split
|
1493
|
+
dataset_len = len(dataset)
|
1494
|
+
train_len = int(train_ratio * dataset_len)
|
1495
|
+
val_len = int(val_ratio * dataset_len)
|
1496
|
+
test_len = dataset_len - train_len - val_len # Ensure it adds up correctly
|
1497
|
+
|
1498
|
+
## Generate indices for the split
|
1499
|
+
indices = list(range(dataset_len))
|
1500
|
+
if shuffle:
|
1501
|
+
torch.manual_seed(randomState) # For reproducibility
|
1502
|
+
indices = torch.randperm(dataset_len).tolist() # Shuffled indices
|
1503
|
+
|
1504
|
+
# Create splits
|
1505
|
+
train_indices = indices[:train_len]
|
1506
|
+
val_indices = indices[train_len:train_len + val_len]
|
1507
|
+
test_indices = indices[train_len + val_len:train_len + val_len + test_len]
|
1508
|
+
|
1509
|
+
train_dataset = Subset(dataset, train_indices)
|
1510
|
+
val_dataset = Subset(dataset, val_indices)
|
1511
|
+
test_dataset = Subset(dataset, test_indices)
|
1512
|
+
|
1513
|
+
return train_dataset, val_dataset, test_dataset
|
1514
|
+
|
1414
1515
|
@staticmethod
|
1415
1516
|
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
1517
|
"""
|
@@ -1529,11 +1630,11 @@ class PyG:
|
|
1529
1630
|
----------
|
1530
1631
|
hparams : HParams
|
1531
1632
|
The input hyperparameters
|
1532
|
-
trainingDataset :
|
1633
|
+
trainingDataset : CustomDataset
|
1533
1634
|
The input training dataset.
|
1534
|
-
validationDataset :
|
1635
|
+
validationDataset : CustomDataset
|
1535
1636
|
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 :
|
1637
|
+
testingDataset : CustomDataset
|
1537
1638
|
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
1639
|
|
1539
1640
|
Returns
|
@@ -1635,13 +1736,13 @@ class PyG:
|
|
1635
1736
|
import os
|
1636
1737
|
|
1637
1738
|
if model == None:
|
1638
|
-
print("
|
1739
|
+
print("PyG.ModelSave - Error: The input model parameter is invalid. Returning None.")
|
1639
1740
|
return None
|
1640
1741
|
if path == None:
|
1641
|
-
print("
|
1742
|
+
print("PyG.ModelSave - Error: The input path parameter is invalid. Returning None.")
|
1642
1743
|
return None
|
1643
1744
|
if not overwrite and os.path.exists(path):
|
1644
|
-
print("
|
1745
|
+
print("PyG.ModelSave - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
|
1645
1746
|
return None
|
1646
1747
|
if overwrite and os.path.exists(path):
|
1647
1748
|
os.remove(path)
|
@@ -1893,7 +1994,7 @@ class PyG:
|
|
1893
1994
|
from sklearn import metrics
|
1894
1995
|
from sklearn.metrics import accuracy_score
|
1895
1996
|
except:
|
1896
|
-
print("
|
1997
|
+
print("PyG - Installing required scikit-learn (sklearn) library.")
|
1897
1998
|
try:
|
1898
1999
|
os.system("pip install scikit-learn")
|
1899
2000
|
except:
|
@@ -1901,19 +2002,19 @@ class PyG:
|
|
1901
2002
|
try:
|
1902
2003
|
from sklearn import metrics
|
1903
2004
|
from sklearn.metrics import accuracy_score
|
1904
|
-
print("
|
2005
|
+
print("PyG - scikit-learn (sklearn) library installed correctly.")
|
1905
2006
|
except:
|
1906
|
-
warnings.warn("
|
2007
|
+
warnings.warn("PyG - Error: Could not import scikit-learn (sklearn). Please try to install scikit-learn manually. Returning None.")
|
1907
2008
|
return None
|
1908
2009
|
|
1909
2010
|
if not isinstance(actual, list):
|
1910
|
-
print("
|
2011
|
+
print("PyG.ConfusionMatrix - ERROR: The actual input is not a list. Returning None")
|
1911
2012
|
return None
|
1912
2013
|
if not isinstance(predicted, list):
|
1913
|
-
print("
|
2014
|
+
print("PyG.ConfusionMatrix - ERROR: The predicted input is not a list. Returning None")
|
1914
2015
|
return None
|
1915
2016
|
if len(actual) != len(predicted):
|
1916
|
-
print("
|
2017
|
+
print("PyG.ConfusionMatrix - ERROR: The two input lists do not have the same length. Returning None")
|
1917
2018
|
return None
|
1918
2019
|
if normalize:
|
1919
2020
|
cm = np.transpose(metrics.confusion_matrix(y_true=actual, y_pred=predicted, normalize="true"))
|
@@ -2065,3 +2166,58 @@ class PyG:
|
|
2065
2166
|
size = len(predicted)
|
2066
2167
|
|
2067
2168
|
return {"mse": mse, "size": size}
|
2169
|
+
|
2170
|
+
@staticmethod
|
2171
|
+
def Performance(actual, predicted, mantissa: int = 6):
|
2172
|
+
"""
|
2173
|
+
Computes regression model performance measures. This is to be used only with regression not with classification.
|
2174
|
+
|
2175
|
+
Parameters
|
2176
|
+
----------
|
2177
|
+
actual : list
|
2178
|
+
The input list of actual values.
|
2179
|
+
predicted : list
|
2180
|
+
The input list of predicted values.
|
2181
|
+
mantissa : int , optional
|
2182
|
+
The desired length of the mantissa. The default is 6.
|
2183
|
+
|
2184
|
+
Returns
|
2185
|
+
-------
|
2186
|
+
dict
|
2187
|
+
The dictionary containing the performance measures. The keys in the dictionary are: 'mae', 'mape', 'mse', 'r', 'r2', 'rmse'.
|
2188
|
+
"""
|
2189
|
+
|
2190
|
+
if not isinstance(actual, list):
|
2191
|
+
print("PyG.Performance - ERROR: The actual input is not a list. Returning None")
|
2192
|
+
return None
|
2193
|
+
if not isinstance(predicted, list):
|
2194
|
+
print("PyG.Performance - ERROR: The predicted input is not a list. Returning None")
|
2195
|
+
return None
|
2196
|
+
if not (len(actual) == len(predicted)):
|
2197
|
+
print("PyG.Performance - ERROR: The actual and predicted input lists have different lengths. Returning None")
|
2198
|
+
return None
|
2199
|
+
|
2200
|
+
predicted = np.array(predicted)
|
2201
|
+
actual = np.array(actual)
|
2202
|
+
|
2203
|
+
mae = np.mean(np.abs(predicted - actual))
|
2204
|
+
mape = np.mean(np.abs((actual - predicted) / actual))*100
|
2205
|
+
mse = np.mean((predicted - actual)**2)
|
2206
|
+
correlation_matrix = np.corrcoef(predicted, actual)
|
2207
|
+
r = correlation_matrix[0, 1]
|
2208
|
+
r2 = r**2
|
2209
|
+
absolute_errors = np.abs(predicted - actual)
|
2210
|
+
mean_actual = np.mean(actual)
|
2211
|
+
if mean_actual == 0:
|
2212
|
+
rae = None
|
2213
|
+
else:
|
2214
|
+
rae = np.mean(absolute_errors) / mean_actual
|
2215
|
+
rmse = np.sqrt(mse)
|
2216
|
+
return {'mae': round(mae, mantissa),
|
2217
|
+
'mape': round(mape, mantissa),
|
2218
|
+
'mse': round(mse, mantissa),
|
2219
|
+
'r': round(r, mantissa),
|
2220
|
+
'r2': round(r2, mantissa),
|
2221
|
+
'rae': round(rae, mantissa),
|
2222
|
+
'rmse': round(rmse, mantissa)
|
2223
|
+
}
|
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/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.7.
|
1
|
+
__version__ = '0.7.43'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.43
|
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
|
@@ -16,10 +16,10 @@ 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=Dd0fiEbM_KR-sEHKCodmURBFFvckB6j7x4oBcCC5Q2o,102171
|
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
25
|
topologicpy/Topology.py,sha256=5KGQ8jSiURMk9syoMLc3mrIONCfj_pfvCfHTKgPcLOM,366047
|
@@ -27,9 +27,9 @@ 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=7JOl9BjjPK0ib5M5rAuj9I5xjEoYF6YsFAS_dvAYEzg,23
|
31
|
+
topologicpy-0.7.43.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
|
32
|
+
topologicpy-0.7.43.dist-info/METADATA,sha256=NCprd1lCZf1afHBHxA5uol5btFYvJFZeiIdoIJtQ5aI,10916
|
33
|
+
topologicpy-0.7.43.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
34
|
+
topologicpy-0.7.43.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
|
35
|
+
topologicpy-0.7.43.dist-info/RECORD,,
|
File without changes
|
File without changes
|