topologicpy 0.8.0__py3-none-any.whl → 0.8.3__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/Cluster.py +67 -0
- topologicpy/Edge.py +101 -0
- topologicpy/Face.py +160 -4
- topologicpy/Helper.py +158 -44
- topologicpy/Matrix.py +85 -73
- topologicpy/Topology.py +279 -4
- topologicpy/Wire.py +239 -43
- topologicpy/version.py +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.3.dist-info}/METADATA +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.3.dist-info}/RECORD +13 -13
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.3.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.3.dist-info}/LICENSE +0 -0
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.3.dist-info}/top_level.txt +0 -0
topologicpy/Cluster.py
CHANGED
@@ -1247,6 +1247,73 @@ class Cluster():
|
|
1247
1247
|
return resultingTopologies[0]
|
1248
1248
|
return cluster
|
1249
1249
|
|
1250
|
+
@staticmethod
|
1251
|
+
def Tripod(size: float = 1.0,
|
1252
|
+
radius: float = 0.03,
|
1253
|
+
sides: int = 4,
|
1254
|
+
faceColorKey="faceColor",
|
1255
|
+
xColor = "red",
|
1256
|
+
yColor = "green",
|
1257
|
+
zColor = "blue",
|
1258
|
+
matrix=None):
|
1259
|
+
"""
|
1260
|
+
Creates a color-coded Axes tripod for X, Y, and Z axes. X-Axis is red, Y-Axis is "green", and Z-Axis= "blue"
|
1261
|
+
|
1262
|
+
Parameters
|
1263
|
+
----------
|
1264
|
+
size : float , optional
|
1265
|
+
The desired size of the tripod. The default is 1.0.
|
1266
|
+
radius : float , optional
|
1267
|
+
The desired radiues of the tripod. The default is 0.03
|
1268
|
+
sides : int , optional
|
1269
|
+
The desired number of sides of the tripod. The default is 4.
|
1270
|
+
faceColorKey : str , optional
|
1271
|
+
The dictionary key under which to store the colors of the axes.
|
1272
|
+
xColor : str , optional
|
1273
|
+
The color to use for the X axis. The default is "red".
|
1274
|
+
yColor : str , optional
|
1275
|
+
The color to use for the Y axis. The default is "green".
|
1276
|
+
zColor : str , optional
|
1277
|
+
The color to use for the Z axis. The default is "blue".
|
1278
|
+
matrix : list , optional
|
1279
|
+
The desired 4X4 transformation matrix to use for transforming the tripod. The default is None which means the tripod will be placed at the origin and will be axis-aligned.
|
1280
|
+
|
1281
|
+
Returns
|
1282
|
+
-------
|
1283
|
+
topologic_core.Cluster
|
1284
|
+
The created tripod
|
1285
|
+
|
1286
|
+
"""
|
1287
|
+
|
1288
|
+
from topologicpy.Cell import Cell
|
1289
|
+
from topologicpy.Topology import Topology
|
1290
|
+
from topologicpy.Dictionary import Dictionary
|
1291
|
+
|
1292
|
+
cyl = Cell.Cylinder(radius=radius, height=size - size*0.3, uSides=sides, placement="bottom")
|
1293
|
+
cone = Cell.Cone(baseRadius=radius*2.25, height=size*0.3, placement="bottom", uSides=sides)
|
1294
|
+
cone = Topology.Translate(cone, 0, 0, size - size*0.3)
|
1295
|
+
z_arrow = Topology.Union(cyl, cone)
|
1296
|
+
x_arrow = Topology.Rotate(z_arrow, axis=[0,1,0], angle=90)
|
1297
|
+
y_arrow = Topology.Rotate(z_arrow, axis=[1,0,0], angle=-90)
|
1298
|
+
|
1299
|
+
x_faces = Topology.Faces(x_arrow)
|
1300
|
+
for x_face in x_faces:
|
1301
|
+
d = Dictionary.ByKeyValue(faceColorKey, xColor)
|
1302
|
+
x_face = Topology.SetDictionary(x_face, d)
|
1303
|
+
y_faces = Topology.Faces(y_arrow)
|
1304
|
+
for y_face in y_faces:
|
1305
|
+
d = Dictionary.ByKeyValue(faceColorKey, yColor)
|
1306
|
+
y_face = Topology.SetDictionary(y_face, d)
|
1307
|
+
z_faces = Topology.Faces(z_arrow)
|
1308
|
+
for z_face in z_faces:
|
1309
|
+
d = Dictionary.ByKeyValue(faceColorKey, zColor)
|
1310
|
+
z_face = Topology.SetDictionary(z_face, d)
|
1311
|
+
|
1312
|
+
cluster = Cluster.ByTopologies(x_arrow, y_arrow, z_arrow)
|
1313
|
+
if not matrix == None:
|
1314
|
+
cluster = Topology.Transform(cluster, matrix=matrix)
|
1315
|
+
return cluster
|
1316
|
+
|
1250
1317
|
@staticmethod
|
1251
1318
|
def Vertices(cluster) -> list:
|
1252
1319
|
"""
|
topologicpy/Edge.py
CHANGED
@@ -17,6 +17,63 @@
|
|
17
17
|
import topologic_core as topologic
|
18
18
|
|
19
19
|
class Edge():
|
20
|
+
|
21
|
+
@staticmethod
|
22
|
+
def Align2D(edgeA, edgeB):
|
23
|
+
"""
|
24
|
+
Compute the 4x4 transformation matrix to fully align edgeA to edgeB.
|
25
|
+
|
26
|
+
Parameters:
|
27
|
+
edge1 (Edge): The source 2D edge to transform.
|
28
|
+
edge2 (Edge): The target 2D edge.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
list: A 4x4 transformation matrix.
|
32
|
+
"""
|
33
|
+
from topologicpy.Vertex import Vertex
|
34
|
+
from topologicpy.Edge import Edge
|
35
|
+
from topologicpy.Topology import Topology
|
36
|
+
from topologicpy.Matrix import Matrix
|
37
|
+
from topologicpy.Vector import Vector
|
38
|
+
|
39
|
+
centroid1 = Topology.Centroid(edgeA)
|
40
|
+
centroid2 = Topology.Centroid(edgeB)
|
41
|
+
# Extract coordinates
|
42
|
+
x1, y1, z1 = Vertex.Coordinates(centroid1)
|
43
|
+
x2, y2, z2 = Vertex.Coordinates(centroid2)
|
44
|
+
|
45
|
+
# Translation to move edge1 to the origin
|
46
|
+
move_to_origin = Matrix.ByTranslation(-x1, -y1, -z1)
|
47
|
+
|
48
|
+
# Translation to move edge1 from the origin to the start of edge2
|
49
|
+
move_to_target = Matrix.ByTranslation(x2, y2, z2)
|
50
|
+
|
51
|
+
# Lengths of the edges
|
52
|
+
length1 = Edge.Length(edgeA)
|
53
|
+
length2 = Edge.Length(edgeB)
|
54
|
+
|
55
|
+
if length1 == 0 or length2 == 0:
|
56
|
+
raise ValueError("Edges must have non-zero length.")
|
57
|
+
|
58
|
+
# Calculate scaling factor
|
59
|
+
scale_factor = length2 / length1
|
60
|
+
# Scaling matrix
|
61
|
+
scaling_matrix = Matrix.ByScaling(scale_factor, scale_factor, 1.0)
|
62
|
+
|
63
|
+
# Calculate angles of the edges relative to the X-axis
|
64
|
+
angle1 = Vector.CompassAngle(Edge.Direction(edgeA), [1,0,0])
|
65
|
+
angle2 = Vector.CompassAngle(Edge.Direction(edgeB), [1,0,0])
|
66
|
+
# Rotation angle
|
67
|
+
rotation_angle = angle2 - angle1
|
68
|
+
# Rotation matrix (about Z-axis for 2D alignment)
|
69
|
+
rotation_matrix = Matrix.ByRotation(0, 0, rotation_angle, order="xyz")
|
70
|
+
|
71
|
+
# Combine transformations: Move to origin -> Scale -> Rotate -> Move to target
|
72
|
+
transformation_matrix = Matrix.Multiply(scaling_matrix, move_to_origin)
|
73
|
+
transformation_matrix = Matrix.Multiply(rotation_matrix, transformation_matrix)
|
74
|
+
transformation_matrix = Matrix.Multiply(move_to_target, transformation_matrix)
|
75
|
+
return transformation_matrix
|
76
|
+
|
20
77
|
@staticmethod
|
21
78
|
def Angle(edgeA, edgeB, mantissa: int = 6, bracket: bool = False) -> float:
|
22
79
|
"""
|
@@ -268,6 +325,50 @@ class Edge():
|
|
268
325
|
edge = None
|
269
326
|
return edge
|
270
327
|
|
328
|
+
@staticmethod
|
329
|
+
def ByOriginDirectionLength(origin = None, direction=[0,0,1], length: float = 1.0, tolerance: float = 0.0001, silent: bool = False):
|
330
|
+
"""
|
331
|
+
Creates a straight edge from the input parameters.
|
332
|
+
|
333
|
+
Parameters
|
334
|
+
----------
|
335
|
+
origin : topologic_core.Vertex
|
336
|
+
The origin (start vertex) of the edge.
|
337
|
+
direction : list , optional
|
338
|
+
The desired direction vector of the edge. The default is [0,0,1] (pointing up in the Z direction)
|
339
|
+
length: float , optional
|
340
|
+
The desired length of edge. The default is 1.0.
|
341
|
+
tolerance : float , optional
|
342
|
+
The desired tolerance to decide if an edge can be created. The default is 0.0001.
|
343
|
+
silent : bool , optional
|
344
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
345
|
+
|
346
|
+
Returns
|
347
|
+
-------
|
348
|
+
topologic_core.Edge
|
349
|
+
The created edge.
|
350
|
+
|
351
|
+
"""
|
352
|
+
from topologicpy.Vertex import Vertex
|
353
|
+
from topologicpy.Topology import Topology
|
354
|
+
|
355
|
+
if origin == None:
|
356
|
+
origin = Vertex.Origin()
|
357
|
+
|
358
|
+
if not Topology.IsInstance(origin, "vertex"):
|
359
|
+
if not silent:
|
360
|
+
print("Edge.ByVertexDirectionLength - Error: The input vertex parameter is not a valid vertex. Returning None.")
|
361
|
+
return None
|
362
|
+
|
363
|
+
if length < tolerance:
|
364
|
+
if not silent:
|
365
|
+
print("Edge.ByVertexDirectionLength - Error: The input edge parameter must not be less than the input tolerance parameter. Returning None.")
|
366
|
+
return None
|
367
|
+
|
368
|
+
endVertex = Topology.TranslateByDirectionDistance(origin, direction=direction[:3], distance=length)
|
369
|
+
edge = Edge.ByVertices(origin, endVertex, tolerance=tolerance)
|
370
|
+
return edge
|
371
|
+
|
271
372
|
@staticmethod
|
272
373
|
def ByVertices(*args, tolerance: float = 0.0001, silent: bool = False):
|
273
374
|
"""
|
topologicpy/Face.py
CHANGED
@@ -1124,6 +1124,162 @@ class Face():
|
|
1124
1124
|
dirA = Face.Normal(face, outputType="xyz", mantissa=mantissa)
|
1125
1125
|
return Vector.CompassAngle(vectorA=dirA, vectorB=north, mantissa=mantissa, tolerance=tolerance)
|
1126
1126
|
|
1127
|
+
@staticmethod
|
1128
|
+
def CrossShape(origin=None,
|
1129
|
+
width=1,
|
1130
|
+
length=1,
|
1131
|
+
a=0.25,
|
1132
|
+
b=0.25,
|
1133
|
+
c=None,
|
1134
|
+
d=None,
|
1135
|
+
flipHorizontal = False,
|
1136
|
+
flipVertical = False,
|
1137
|
+
direction=[0,0,1],
|
1138
|
+
placement="center",
|
1139
|
+
tolerance=0.0001,
|
1140
|
+
silent=False):
|
1141
|
+
"""
|
1142
|
+
Creates a Cross-shape.
|
1143
|
+
|
1144
|
+
Parameters
|
1145
|
+
----------
|
1146
|
+
origin : topologic_core.Vertex , optional
|
1147
|
+
The location of the origin of the T-shape. The default is None which results in the Cross-shape being placed at (0, 0, 0).
|
1148
|
+
width : float , optional
|
1149
|
+
The overall width of the Cross-shape. The default is 1.0.
|
1150
|
+
length : float , optional
|
1151
|
+
The overall length of the Cross-shape. The default is 1.0.
|
1152
|
+
a : float , optional
|
1153
|
+
The hortizontal thickness of the vertical arm of the Cross-shape. The default is 0.25.
|
1154
|
+
b : float , optional
|
1155
|
+
The vertical thickness of the horizontal arm of the Cross-shape. The default is 0.25.
|
1156
|
+
c : float , optional
|
1157
|
+
The distance of the vertical symmetry axis measured from the left side of the Cross-shape. The default is None which results in the Cross-shape being symmetrical on the Y-axis.
|
1158
|
+
d : float , optional
|
1159
|
+
The distance of the horizontal symmetry axis measured from the bottom side of the Cross-shape. The default is None which results in the Cross-shape being symmetrical on the X-axis.
|
1160
|
+
direction : list , optional
|
1161
|
+
The vector representing the up direction of the Cross-shape. The default is [0, 0, 1].
|
1162
|
+
placement : str , optional
|
1163
|
+
The description of the placement of the origin of the Cross-shape. This can be "center", "lowerleft", "upperleft", "lowerright", "upperright". It is case insensitive. The default is "center".
|
1164
|
+
tolerance : float , optional
|
1165
|
+
The desired tolerance. The default is 0.0001.
|
1166
|
+
silent : bool , optional
|
1167
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1168
|
+
|
1169
|
+
Returns
|
1170
|
+
-------
|
1171
|
+
topologic_core.Face
|
1172
|
+
The created Cross-shape.
|
1173
|
+
|
1174
|
+
"""
|
1175
|
+
from topologicpy.Vertex import Vertex
|
1176
|
+
from topologicpy.Wire import Wire
|
1177
|
+
from topologicpy.Topology import Topology
|
1178
|
+
|
1179
|
+
if not isinstance(width, int) and not isinstance(width, float):
|
1180
|
+
if not silent:
|
1181
|
+
print("Wire.CrossShape - Error: The width input parameter is not a valid number. Returning None.")
|
1182
|
+
return None
|
1183
|
+
if not isinstance(length, int) and not isinstance(length, float):
|
1184
|
+
if not silent:
|
1185
|
+
print("Wire.CrossShape - Error: The length input parameter is not a valid number. Returning None.")
|
1186
|
+
return None
|
1187
|
+
if not isinstance(a, int) and not isinstance(a, float):
|
1188
|
+
if not silent:
|
1189
|
+
print("Wire.CrossShape - Error: The a input parameter is not a valid number. Returning None.")
|
1190
|
+
return None
|
1191
|
+
if not isinstance(b, int) and not isinstance(b, float):
|
1192
|
+
if not silent:
|
1193
|
+
print("Wire.CrossShape - Error: The b input parameter is not a valid number. Returning None.")
|
1194
|
+
return None
|
1195
|
+
if c == None:
|
1196
|
+
c = width/2
|
1197
|
+
if d == None:
|
1198
|
+
d = length/2
|
1199
|
+
if not isinstance(c, int) and not isinstance(c, float):
|
1200
|
+
if not silent:
|
1201
|
+
print("Wire.CrossShape - Error: The c input parameter is not a valid number. Returning None.")
|
1202
|
+
return None
|
1203
|
+
if not isinstance(d, int) and not isinstance(d, float):
|
1204
|
+
if not silent:
|
1205
|
+
print("Wire.CrossShape - Error: The d input parameter is not a valid number. Returning None.")
|
1206
|
+
if width <= tolerance:
|
1207
|
+
if not silent:
|
1208
|
+
print("Wire.CrossShape - Error: The width input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1209
|
+
return None
|
1210
|
+
if length <= tolerance:
|
1211
|
+
if not silent:
|
1212
|
+
print("Wire.CrossShape - Error: The length input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1213
|
+
return None
|
1214
|
+
if a <= tolerance:
|
1215
|
+
if not silent:
|
1216
|
+
print("Wire.CrossShape - Error: The a input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1217
|
+
return None
|
1218
|
+
if b <= tolerance:
|
1219
|
+
if not silent:
|
1220
|
+
print("Wire.CrossShape - Error: The b input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1221
|
+
return None
|
1222
|
+
if c <= tolerance:
|
1223
|
+
if not silent:
|
1224
|
+
print("Wire.CrossShape - Error: The c input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1225
|
+
return None
|
1226
|
+
if d <= tolerance:
|
1227
|
+
if not silent:
|
1228
|
+
print("Wire.CrossShape - Error: The d input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
|
1229
|
+
return None
|
1230
|
+
if a >= (width - tolerance*2):
|
1231
|
+
if not silent:
|
1232
|
+
print("Wire.CrossShape - Error: The a input parameter must be less than the width input parameter. Returning None.")
|
1233
|
+
return None
|
1234
|
+
if b >= (length - tolerance*2):
|
1235
|
+
if not silent:
|
1236
|
+
print("Wire.CrossShape - Error: The b input parameter must be less than the length input parameter. Returning None.")
|
1237
|
+
return None
|
1238
|
+
if c <= (tolerance + a/2):
|
1239
|
+
if not silent:
|
1240
|
+
print("Wire.CrossShape - Error: The c input parameter must be more than half the a input parameter. Returning None.")
|
1241
|
+
return None
|
1242
|
+
if d <= (tolerance + b/2):
|
1243
|
+
if not silent:
|
1244
|
+
print("Wire.CrossShape - Error: The c input parameter must be more than half the b input parameter. Returning None.")
|
1245
|
+
return None
|
1246
|
+
if c >= (width - tolerance - a/2):
|
1247
|
+
if not silent:
|
1248
|
+
print("Wire.CrossShape - Error: The c input parameter must be less than the width minus half the a input parameter. Returning None.")
|
1249
|
+
return None
|
1250
|
+
if d >= (length - tolerance - b/2):
|
1251
|
+
if not silent:
|
1252
|
+
print("Wire.CrossShape - Error: The c input parameter must be less than the width minus half the b input parameter. Returning None.")
|
1253
|
+
return None
|
1254
|
+
if origin == None:
|
1255
|
+
origin = Vertex.Origin()
|
1256
|
+
if not Topology.IsInstance(origin, "vertex"):
|
1257
|
+
if not silent:
|
1258
|
+
print("Wire.CrossShape - Error: The origin input parameter is not a valid topologic vertex. Returning None.")
|
1259
|
+
return None
|
1260
|
+
if not isinstance(direction, list):
|
1261
|
+
if not silent:
|
1262
|
+
print("Wire.CrossShape - Error: The direction input parameter is not a valid list. Returning None.")
|
1263
|
+
return None
|
1264
|
+
if not len(direction) == 3:
|
1265
|
+
if not silent:
|
1266
|
+
print("Wire.CrossShape - Error: The direction input parameter is not a valid vector. Returning None.")
|
1267
|
+
return None
|
1268
|
+
cross_shape_wire = Wire.CrossShape(origin=origin,
|
1269
|
+
width=width,
|
1270
|
+
length=length,
|
1271
|
+
a=a,
|
1272
|
+
b=b,
|
1273
|
+
c=c,
|
1274
|
+
d=d,
|
1275
|
+
flipHorizontal=flipHorizontal,
|
1276
|
+
flipVertical=flipVertical,
|
1277
|
+
direction=direction,
|
1278
|
+
placement=placement,
|
1279
|
+
tolerance=tolerance,
|
1280
|
+
silent=silent)
|
1281
|
+
return Face.ByWire(cross_shape_wire, tolerance=tolerance, silent=silent)
|
1282
|
+
|
1127
1283
|
@staticmethod
|
1128
1284
|
def CShape(origin=None,
|
1129
1285
|
width=1,
|
@@ -3545,8 +3701,8 @@ class Face():
|
|
3545
3701
|
def TShape(origin=None,
|
3546
3702
|
width=1,
|
3547
3703
|
length=1,
|
3548
|
-
a=0.
|
3549
|
-
b=0.
|
3704
|
+
a=0.25,
|
3705
|
+
b=0.25,
|
3550
3706
|
flipHorizontal = False,
|
3551
3707
|
flipVertical = False,
|
3552
3708
|
direction=[0,0,1],
|
@@ -3565,9 +3721,9 @@ class Face():
|
|
3565
3721
|
length : float , optional
|
3566
3722
|
The overall length of the T-shape. The default is 1.0.
|
3567
3723
|
a : float , optional
|
3568
|
-
The hortizontal thickness of the vertical arm of the T-shape. The default is 0.
|
3724
|
+
The hortizontal thickness of the vertical arm of the T-shape. The default is 0.25.
|
3569
3725
|
b : float , optional
|
3570
|
-
The vertical thickness of the horizontal arm of the T-shape. The default is 0.
|
3726
|
+
The vertical thickness of the horizontal arm of the T-shape. The default is 0.25.
|
3571
3727
|
direction : list , optional
|
3572
3728
|
The vector representing the up direction of the T-shape. The default is [0, 0, 1].
|
3573
3729
|
placement : str , optional
|
topologicpy/Helper.py
CHANGED
@@ -98,29 +98,29 @@ class Helper:
|
|
98
98
|
@staticmethod
|
99
99
|
def ClusterByKeys(elements, dictionaries, *keys, silent=False):
|
100
100
|
"""
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
101
|
+
Clusters the input list of elements and dictionaries based on the input key or keys.
|
102
|
+
|
103
|
+
Parameters
|
104
|
+
----------
|
105
|
+
elements : list
|
106
|
+
The input list of elements to be clustered.
|
107
|
+
dictionaries : list[Topology.Dictionary]
|
108
|
+
The input list of dictionaries to be consulted for clustering. This is assumed to be in the same order as the list of elements.
|
109
|
+
keys : str or list or comma-separated str input parameters
|
110
|
+
The key or keys in the topology's dictionary to use for clustering.
|
111
|
+
silent : bool , optional
|
112
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
113
|
+
|
114
|
+
|
115
|
+
Returns
|
116
|
+
-------
|
117
|
+
dict
|
118
|
+
A dictionary containing the elements and the dictionaries, but clustered. The dictionary has two keys:
|
119
|
+
"elements": list
|
120
|
+
A nested list of elements where each item is a list of elements with the same key values.
|
121
|
+
"dictionaries": list
|
122
|
+
A nested list of dictionaries where each item is a list of dictionaries with the same key values.
|
123
|
+
"""
|
124
124
|
|
125
125
|
from topologicpy.Dictionary import Dictionary
|
126
126
|
from topologicpy.Helper import Helper
|
@@ -275,6 +275,41 @@ class Helper:
|
|
275
275
|
iterated_list.append(y)
|
276
276
|
return iterated_list
|
277
277
|
|
278
|
+
@staticmethod
|
279
|
+
def MakeUnique(listA):
|
280
|
+
"""
|
281
|
+
Forces the strings in the input list to be unique if they have duplicates.
|
282
|
+
|
283
|
+
Parameters
|
284
|
+
----------
|
285
|
+
listA : list
|
286
|
+
The input list of strings.
|
287
|
+
|
288
|
+
Returns
|
289
|
+
-------
|
290
|
+
list
|
291
|
+
The input list, but with each item ensured to be unique if they have duplicates.
|
292
|
+
|
293
|
+
"""
|
294
|
+
# Create a dictionary to store counts of each string
|
295
|
+
counts = {}
|
296
|
+
# Create a list to store modified strings
|
297
|
+
unique_strings = []
|
298
|
+
|
299
|
+
for string in listA:
|
300
|
+
# If the string already exists in the counts dictionary
|
301
|
+
if string in counts:
|
302
|
+
# Increment the count
|
303
|
+
counts[string] += 1
|
304
|
+
# Append the modified string with underscore and count
|
305
|
+
unique_strings.append(f"{string}_{counts[string]}")
|
306
|
+
else:
|
307
|
+
# If it's the first occurrence of the string, add it to the counts dictionary
|
308
|
+
counts[string] = 0
|
309
|
+
unique_strings.append(string)
|
310
|
+
|
311
|
+
return unique_strings
|
312
|
+
|
278
313
|
@staticmethod
|
279
314
|
def MergeByThreshold(listA, threshold=0.0001):
|
280
315
|
"""
|
@@ -312,39 +347,76 @@ class Helper:
|
|
312
347
|
return merged_list
|
313
348
|
|
314
349
|
@staticmethod
|
315
|
-
def
|
350
|
+
def MaximumIndices(listA, silent: bool = False):
|
316
351
|
"""
|
317
|
-
|
352
|
+
Returns a list of indices of the maximum value in the input list.
|
353
|
+
For example, if the input list is [7,3,4,7,5,7] then the returned list is [0,3,5] to indicate the indices of the maximum value (7).
|
318
354
|
|
319
355
|
Parameters
|
320
356
|
----------
|
321
357
|
listA : list
|
322
|
-
The input list
|
358
|
+
The input list.
|
359
|
+
silent : bool , optional
|
360
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
323
361
|
|
324
362
|
Returns
|
325
363
|
-------
|
326
364
|
list
|
327
|
-
The
|
365
|
+
The resulting list.
|
328
366
|
|
329
367
|
"""
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
368
|
+
if not isinstance(listA, list):
|
369
|
+
if not silent:
|
370
|
+
print("Helper.MaximumIndices - Error: The input listA parameter is not a valid list. Returning None.")
|
371
|
+
return None
|
372
|
+
if len(listA) == 0:
|
373
|
+
return []
|
374
|
+
if len(listA) == 1:
|
375
|
+
return [0]
|
376
|
+
|
377
|
+
# Find the maximum value in the list
|
378
|
+
max_value = min(listA)
|
334
379
|
|
335
|
-
|
336
|
-
|
337
|
-
if string in counts:
|
338
|
-
# Increment the count
|
339
|
-
counts[string] += 1
|
340
|
-
# Append the modified string with underscore and count
|
341
|
-
unique_strings.append(f"{string}_{counts[string]}")
|
342
|
-
else:
|
343
|
-
# If it's the first occurrence of the string, add it to the counts dictionary
|
344
|
-
counts[string] = 0
|
345
|
-
unique_strings.append(string)
|
380
|
+
# Find all indices where this minimum value occurs
|
381
|
+
indices = [i for i, value in enumerate(listA) if value == max_value]
|
346
382
|
|
347
|
-
return
|
383
|
+
return indices
|
384
|
+
|
385
|
+
@staticmethod
|
386
|
+
def MinimumIndices(listA, silent: bool = False):
|
387
|
+
"""
|
388
|
+
Returns a list of indices of the minimum value in the input list.
|
389
|
+
For example, if the input list is [1,3,4,1,5,1] then the returned list is [0,3,5] to indicate the indices of the minimum value (1).
|
390
|
+
|
391
|
+
Parameters
|
392
|
+
----------
|
393
|
+
listA : list
|
394
|
+
The input list.
|
395
|
+
silent : bool , optional
|
396
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
397
|
+
|
398
|
+
Returns
|
399
|
+
-------
|
400
|
+
list
|
401
|
+
The resulting list.
|
402
|
+
|
403
|
+
"""
|
404
|
+
if not isinstance(listA, list):
|
405
|
+
if not silent:
|
406
|
+
print("Helper.MinimumIndices - Error: The input listA parameter is not a valid list. Returning None.")
|
407
|
+
return None
|
408
|
+
if len(listA) == 0:
|
409
|
+
return []
|
410
|
+
if len(listA) == 1:
|
411
|
+
return [0]
|
412
|
+
|
413
|
+
# Find the minimum value in the list
|
414
|
+
min_value = min(listA)
|
415
|
+
|
416
|
+
# Find all indices where this minimum value occurs
|
417
|
+
indices = [i for i, value in enumerate(listA) if value == min_value]
|
418
|
+
|
419
|
+
return indices
|
348
420
|
|
349
421
|
@staticmethod
|
350
422
|
def Normalize(listA, mantissa: int = 6):
|
@@ -356,7 +428,7 @@ class Helper:
|
|
356
428
|
listA : list
|
357
429
|
The input nested list.
|
358
430
|
mantissa : int , optional
|
359
|
-
The desired mantissa
|
431
|
+
The desired length of the mantissa. The default is 6.
|
360
432
|
|
361
433
|
Returns
|
362
434
|
-------
|
@@ -415,6 +487,48 @@ class Helper:
|
|
415
487
|
# If the target is not found, return the position where it would be inserted
|
416
488
|
return left
|
417
489
|
|
490
|
+
@staticmethod
|
491
|
+
def RemoveEven(listA):
|
492
|
+
"""
|
493
|
+
Removes the even indexed members of the input list.
|
494
|
+
|
495
|
+
Parameters
|
496
|
+
----------
|
497
|
+
listA : list
|
498
|
+
The input list.
|
499
|
+
|
500
|
+
Returns
|
501
|
+
-------
|
502
|
+
list
|
503
|
+
The resulting list.
|
504
|
+
|
505
|
+
"""
|
506
|
+
return_list = []
|
507
|
+
for i in range(1, len(listA), 2):
|
508
|
+
return_list.append(listA[i])
|
509
|
+
return return_list
|
510
|
+
|
511
|
+
@staticmethod
|
512
|
+
def RemoveOdd(listA):
|
513
|
+
"""
|
514
|
+
Removes the odd indexed members of the input list.
|
515
|
+
|
516
|
+
Parameters
|
517
|
+
----------
|
518
|
+
listA : list
|
519
|
+
The input list.
|
520
|
+
|
521
|
+
Returns
|
522
|
+
-------
|
523
|
+
list
|
524
|
+
The resulting list.
|
525
|
+
|
526
|
+
"""
|
527
|
+
return_list = []
|
528
|
+
for i in range(0, len(listA), 2):
|
529
|
+
return_list.append(listA[i])
|
530
|
+
return return_list
|
531
|
+
|
418
532
|
@staticmethod
|
419
533
|
def Repeat(listA):
|
420
534
|
"""
|