patme 0.4.4__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.

Potentially problematic release.


This version of patme might be problematic. Click here for more details.

Files changed (46) hide show
  1. patme/__init__.py +52 -0
  2. patme/buildtools/__init__.py +7 -0
  3. patme/buildtools/rce_releasecreator.py +336 -0
  4. patme/buildtools/release.py +26 -0
  5. patme/femtools/__init__.py +5 -0
  6. patme/femtools/abqmsgfilechecker.py +137 -0
  7. patme/femtools/fecall.py +1092 -0
  8. patme/geometry/__init__.py +0 -0
  9. patme/geometry/area.py +124 -0
  10. patme/geometry/coordinatesystem.py +635 -0
  11. patme/geometry/intersect.py +284 -0
  12. patme/geometry/line.py +183 -0
  13. patme/geometry/misc.py +420 -0
  14. patme/geometry/plane.py +464 -0
  15. patme/geometry/rotate.py +244 -0
  16. patme/geometry/scale.py +152 -0
  17. patme/geometry/shape2d.py +50 -0
  18. patme/geometry/transformations.py +1831 -0
  19. patme/geometry/translate.py +139 -0
  20. patme/mechanics/__init__.py +4 -0
  21. patme/mechanics/loads.py +435 -0
  22. patme/mechanics/material.py +1260 -0
  23. patme/service/__init__.py +7 -0
  24. patme/service/decorators.py +85 -0
  25. patme/service/duration.py +96 -0
  26. patme/service/exceptionhook.py +104 -0
  27. patme/service/exceptions.py +36 -0
  28. patme/service/io/__init__.py +3 -0
  29. patme/service/io/basewriter.py +122 -0
  30. patme/service/logger.py +375 -0
  31. patme/service/mathutils.py +108 -0
  32. patme/service/misc.py +71 -0
  33. patme/service/moveimports.py +217 -0
  34. patme/service/stringutils.py +419 -0
  35. patme/service/systemutils.py +290 -0
  36. patme/sshtools/__init__.py +3 -0
  37. patme/sshtools/cara.py +435 -0
  38. patme/sshtools/clustercaller.py +420 -0
  39. patme/sshtools/facluster.py +350 -0
  40. patme/sshtools/sshcall.py +168 -0
  41. patme-0.4.4.dist-info/LICENSE +21 -0
  42. patme-0.4.4.dist-info/LICENSES/MIT.txt +9 -0
  43. patme-0.4.4.dist-info/METADATA +168 -0
  44. patme-0.4.4.dist-info/RECORD +46 -0
  45. patme-0.4.4.dist-info/WHEEL +4 -0
  46. patme-0.4.4.dist-info/entry_points.txt +3 -0
patme/geometry/misc.py ADDED
@@ -0,0 +1,420 @@
1
+ # Copyright (C) 2020 Deutsches Zentrum fuer Luft- und Raumfahrt(DLR, German Aerospace Center) <www.dlr.de>
2
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
3
+ #
4
+ # SPDX-License-Identifier: MIT
5
+ """ """
6
+ from operator import eq, ne
7
+
8
+ import numpy as np
9
+
10
+ from patme import epsilon
11
+ from patme.geometry.translate import Translation
12
+ from patme.service.exceptions import ImproperParameterError, InternalError
13
+
14
+
15
+ def PCA(data, correlation=False, sort=True):
16
+ """Applies Principal Component Analysis to the data
17
+
18
+ Method from
19
+ https://github.com/daavoo/pyntcloud/blob/master/pyntcloud/utils/array.py
20
+ MIT license
21
+
22
+ Parameters
23
+ ----------
24
+ data: array
25
+ The array containing the data. The array must have NxM dimensions, where each
26
+ of the N rows represents a different individual record and each of the M columns
27
+ represents a different variable recorded for that individual record.
28
+ array([
29
+ [V11, ... , V1m],
30
+ ...,
31
+ [Vn1, ... , Vnm]])
32
+
33
+ correlation(Optional) : bool
34
+ Set the type of matrix to be computed (see Notes):
35
+ If True compute the correlation matrix.
36
+ If False(Default) compute the covariance matrix.
37
+
38
+ sort(Optional) : bool
39
+ Set the order that the eigenvalues/vectors will have
40
+ If True(Default) they will be sorted (from higher value to less).
41
+ If False they won't.
42
+ Returns
43
+ -------
44
+ eigenvalues: (1,M) array
45
+ The eigenvalues of the corresponding matrix.
46
+
47
+ eigenvector: (M,M) array
48
+ The eigenvectors of the corresponding matrix.
49
+
50
+ Notes
51
+ -----
52
+ The correlation matrix is a better choice when there are different magnitudes
53
+ representing the M variables. Use covariance matrix in other cases.
54
+
55
+ """
56
+
57
+ mean = np.mean(data, axis=0)
58
+
59
+ data_adjust = data - mean
60
+
61
+ #: the data is transposed due to np.cov/corrcoef syntax
62
+ if correlation:
63
+
64
+ matrix = np.corrcoef(data_adjust.T)
65
+
66
+ else:
67
+ matrix = np.cov(data_adjust.T)
68
+
69
+ eigenvalues, eigenvectors = np.linalg.eig(matrix)
70
+
71
+ if sort:
72
+ #: sort eigenvalues and eigenvectors
73
+ sort = eigenvalues.argsort()[::-1]
74
+ eigenvalues = eigenvalues[sort]
75
+ eigenvectors = eigenvectors[:, sort]
76
+
77
+ return eigenvalues, eigenvectors
78
+
79
+
80
+ def areVectorsParallel(vector1, vector2):
81
+ """checks if two vectors are parallel to each other
82
+
83
+ >>> areVectorsParallel([0,0,2],[0,0,1])
84
+ True
85
+ >>> areVectorsParallel([0,0,2],[0,1,1])
86
+ False
87
+ >>> areVectorsParallel([0,0,0],[0,0,1])
88
+ False
89
+ """
90
+ vector1, vector2 = np.array(vector1), np.array(vector2)
91
+ if np.linalg.norm(vector1) < epsilon or np.linalg.norm(vector2) < epsilon:
92
+ return False
93
+
94
+ # normalize vectors
95
+ vector1, vector2 = vector1 / vector1[np.argmax(np.abs(vector1))], vector2 / vector2[np.argmax(np.abs(vector2))]
96
+ return np.linalg.norm(vector1 - vector2) < epsilon
97
+
98
+
99
+ def getGeometricCenterSimple(keypointList):
100
+ """Returns the geometric center of self using the average of the min and
101
+ max coordinates.
102
+
103
+ >>> from patme.geometry.translate import Translation
104
+ >>> keypointList = [Translation([0,a,(-1)**a*5]) for a in range(10)]
105
+ >>> getGeometricCenterSimple(keypointList)
106
+ Translation([0. , 4.5, 0. ])
107
+
108
+ :param keypointList: list of Translation objects
109
+ :return: instance of type Translation at the geometric center of the rib
110
+ """
111
+ pointArray = np.array([kp[:3] for kp in keypointList])
112
+ center = (pointArray.max(axis=0) + pointArray.min(axis=0)) / 2
113
+ return Translation(center)
114
+
115
+
116
+ def getAngleOnYZPlane(keypoint, referenceY=0.0, referenceZ=0.0):
117
+ """calculating angle of keypoint on the y-z plane in reference to a
118
+ optionally shifted coordinate system.
119
+
120
+ :return: angle in degees[0,360]
121
+
122
+ .. note:: Please refer to the CPACS definition of the fuselage coordinate system.
123
+ These are the results for the CPACS definition::
124
+
125
+ # results of getAngleOnYZPlane:
126
+ # y ^
127
+ # 225 | 315
128
+ # |
129
+ # <---x---> z
130
+ # |
131
+ # 135 | 45
132
+
133
+ tan alpha = y / z
134
+ coordinate system is rotated since angle=0 is on positive z-axis
135
+ additionally the negative angles need to be shifted by 360deg
136
+
137
+ >>> t1 = Translation([0,-1.,1.])
138
+ >>> abs(getAngleOnYZPlane(t1))
139
+ 45.0
140
+ >>> t1 = Translation([0,0.,1.])
141
+ >>> abs(getAngleOnYZPlane(t1))
142
+ 0.0
143
+ """
144
+
145
+ alpha = np.arctan2(keypoint.y - referenceY, keypoint.z - referenceZ) * 180 / np.pi
146
+ if alpha < epsilon:
147
+ alpha += 360
148
+
149
+ # subtract alpha by 360 since arctan2 calculates alpha in mathematically positive direction but
150
+ # tigl calculates it in the negative direction
151
+ return 360.0 - alpha
152
+
153
+
154
+ def getNearestKeypoint(points, point):
155
+ """This method returns the point from a specified point list next to the
156
+ position of a specified point.
157
+ All points have to be of a class that inherits the numpy array class."""
158
+
159
+ tmpPoints = np.array(points, copy=True)
160
+ allDists = np.linalg.norm(tmpPoints - point, axis=1)
161
+ return points[np.argmin(allDists)]
162
+
163
+
164
+ def getRelativePositionOfProjectedPointOnLine(point, lineStartPoint, lineEndPoint):
165
+ """Retrieve the relative distance of point Pp to the lineStartPoint. Pp is the point
166
+ projection of point P on the straight line through the points lineStartPoint and
167
+ lineEndPoint. The relative distance can also be < 0 or > 1, indicating that the
168
+ projected point is not in between the given points.
169
+
170
+ x P P = point
171
+ Pp = projected point
172
+ o-------x-------o Start = lineStartPoint
173
+ Start Pp End End = lineEndPoint
174
+ 0-----alpha---->1
175
+
176
+ >>> round(getRelativePositionOfProjectedPointOnLine([0,0,0], [-1,-1,-1], [1,1,1]), 1)
177
+ 0.5
178
+ >>> round(getRelativePositionOfProjectedPointOnLine([-1,-1,-1], [-1,-1,-1], [1,1,1]), 1)
179
+ 0.0
180
+ >>> round(getRelativePositionOfProjectedPointOnLine([1,1,1], [-1,-1,-1], [1,1,1]), 1)
181
+ 1.0
182
+ >>> round(getRelativePositionOfProjectedPointOnLine([10,10,10], [-1,-1,-1], [1,1,1]), 1)
183
+ 5.5
184
+ >>> round(getRelativePositionOfProjectedPointOnLine([-3,-3,-3], [-1,-1,-1], [1,1,1]), 1)
185
+ -1.0
186
+ >>> round(getRelativePositionOfProjectedPointOnLine([2,2,2], [0,0,0], [1,0,0]), 1)
187
+ 2.0
188
+
189
+ :param point: array with 3d coordinate of point to be projected
190
+ :param lineStartPoint: array with 3d coordinate of the line start point
191
+ :param lineEndPoint: array with 3d coordinate of the line end point
192
+ :return: relative distance between lineStartPoint and projection of point
193
+ """
194
+ point, lineStartPoint, lineEndPoint = np.array(point), np.array(lineStartPoint), np.array(lineEndPoint)
195
+ alpha = np.dot(
196
+ (point - lineStartPoint), (lineEndPoint - lineStartPoint) / np.linalg.norm(lineEndPoint - lineStartPoint) ** 2
197
+ )
198
+ return alpha
199
+
200
+
201
+ def getPointProjectedOnLine(lineStart, lineEnd, point, clipAlpha=True):
202
+ """calculate the point that is projected from point to the line defined by lineStart and lineEnd
203
+
204
+ :return: Pp - projected point
205
+
206
+ x P P = point
207
+ Pp = projected point
208
+ o-------x-------o Start = lineStartPoint
209
+ Start Pp End End = lineEndPoint
210
+ 0-----alpha---->1
211
+
212
+ >>> getPointProjectedOnLine([0,0,0], [0,0,1], [1,0,0])
213
+ array([0., 0., 0.])
214
+ >>> getPointProjectedOnLine([0,0,0], [0,0,2], [1,0,1])
215
+ array([0., 0., 1.])
216
+
217
+ """
218
+ point, lineStart, lineEnd = np.array(point), np.array(lineStart), np.array(lineEnd)
219
+ alpha = getRelativePositionOfProjectedPointOnLine(point, lineStart, lineEnd)
220
+ # limitation of alpha between 0 and 1
221
+ # next position for distance calculation if clipAlpha equals true
222
+ # else projection point is used for distance computation
223
+ if clipAlpha:
224
+ alpha = np.clip(alpha, 0, 1)
225
+ projPoint = lineStart + alpha * (lineEnd - lineStart)
226
+ return projPoint
227
+
228
+
229
+ def getPointDistanceToLine(lineStart, lineEnd, point, clipAlpha=True):
230
+ """Retrieve the absolute distance of point from the straight line through lineStart and
231
+ lineEnd. The returned distance is the distance between P and Pp
232
+
233
+ x P P = point
234
+ Pp = projected point
235
+ o-------x-------o Start = lineStartPoint
236
+ Start Pp End End = lineEndPoint
237
+ 0-----alpha---->1
238
+
239
+ >>> round(getPointDistanceToLine([-1,-1,-1], [1,1,1], [0,0,0]), 1)
240
+ 0.0
241
+ >>> round(getPointDistanceToLine([0,0,0], [0,0,1], [2,0,-2], clipAlpha=False), 1)
242
+ 2.0
243
+ >>> round(getPointDistanceToLine([-1,-1,-1], [1,1,1], [10,10,10], clipAlpha=False), 1)
244
+ 0.0
245
+
246
+ :param lineStart: array with 3d coordinate of the line start point
247
+ :param lineEnd: array with 3d coordinate of the line end point
248
+ :param point: array with 3d coordinate of point to be projected
249
+ :return: distance between point and the straight line through lineStart and lineEnd
250
+ """
251
+ point, lineStart, lineEnd = np.array(point), np.array(lineStart), np.array(lineEnd)
252
+ projPoint = getPointProjectedOnLine(lineStart, lineEnd, point, clipAlpha)
253
+ distance = np.linalg.norm(point - projPoint)
254
+ if distance == np.nan:
255
+ length = np.linalg.norm(lineStart, lineEnd)
256
+ raise InternalError(
257
+ "Got an error while calculating the distance of a point to a line. " + "The line-points coincide."
258
+ if length < epsilon
259
+ else ""
260
+ )
261
+
262
+ return distance
263
+
264
+
265
+ def isPointProjectionOnLineBetweenPoints(point, lineStartPoint, lineEndPoint):
266
+ """Checks if the projection of point onto the straight line through lineStartPoint
267
+ and lineEndPoint is between lineStartPoint and lineEndPoint. Both end points are
268
+ included into the interval. For further information read the documentation of the
269
+ function getRelativePositionOfProjectedPointOnLine()
270
+
271
+ >>> isPointProjectionOnLineBetweenPoints([0,0,0], [-1,-1,-1], [1,1,1])
272
+ True
273
+ >>> isPointProjectionOnLineBetweenPoints([-1,-1,-1], [-1,-1,-1], [1,1,1])
274
+ True
275
+ >>> isPointProjectionOnLineBetweenPoints([1,1,1], [-1,-1,-1], [1,1,1])
276
+ True
277
+ >>> isPointProjectionOnLineBetweenPoints([10,10,10], [-1,-1,-1], [1,1,1])
278
+ False
279
+ >>> isPointProjectionOnLineBetweenPoints([-10,-10,-10], [-1,-1,-1], [1,1,1])
280
+ False
281
+ >>> isPointProjectionOnLineBetweenPoints([-0.5,-0.5,0.], [-1,-1,-1], [1,1,1])
282
+ True
283
+
284
+ :param point: array with 3d coordinate of point to be projected
285
+ :param lineStartPoint: array with 3d coordinate of the line start point
286
+ :param lineEndPoint: array with 3d coordinate of the line end point
287
+ :return: True if projection of point is between lineStartPoint and lineEndPoint, else False
288
+ """
289
+ point, lineStartPoint, lineEndPoint = np.array(point), np.array(lineStartPoint), np.array(lineEndPoint)
290
+ alpha = getRelativePositionOfProjectedPointOnLine(point, lineStartPoint, lineEndPoint)
291
+ if alpha > -epsilon and alpha < 1 + epsilon:
292
+ return True
293
+ else:
294
+ return False
295
+
296
+
297
+ def isPointOnLineBetweenPoints(point, lineStartPoint, lineEndPoint):
298
+ """Checks if point is located on a straight line between the given points lineStartPoint and
299
+ lineEndPoint including these points.
300
+
301
+ >>> isPointOnLineBetweenPoints([0,0,0], [-1,-1,-1], [1,1,1])
302
+ True
303
+ >>> isPointOnLineBetweenPoints([-1,-1,-1], [-1,-1,-1], [1,1,1])
304
+ True
305
+ >>> isPointOnLineBetweenPoints([1,1,1], [-1,-1,-1], [1,1,1])
306
+ True
307
+ >>> isPointOnLineBetweenPoints([10,10,10], [-1,-1,-1], [1,1,1])
308
+ False
309
+ >>> isPointOnLineBetweenPoints([-10,-10,-10], [-1,-1,-1], [1,1,1])
310
+ False
311
+ >>> isPointOnLineBetweenPoints([-10,-10,0], [-1,-1,-1], [1,1,1])
312
+ False
313
+
314
+ :param point: 1x3 array containing a 3D coordinate of the point to be checked
315
+ :param lineStartPoint: 1x3 array containing a 3D coordinate of the line start point
316
+ :param lineStartPoint: 1x3 array containing a 3D coordinate of the line end point
317
+ :return: True if point is on straight line between lineStartPoint and lineEndPoint, else False
318
+ """
319
+ point, lineStartPoint, lineEndPoint = np.array(point), np.array(lineStartPoint), np.array(lineEndPoint)
320
+ # check if lineStartPoint and lineEndPoint are not equal
321
+ if all(np.abs(lineStartPoint - lineEndPoint) < epsilon):
322
+ raise ImproperParameterError("lineStartPoint and lineEndPoint must not be coincidental")
323
+ # check if point is coincident with lineStartPoint or lineEndPoint
324
+ if all(np.abs(lineStartPoint - point) < epsilon) or all(np.abs(lineEndPoint - point) < epsilon):
325
+ return True
326
+ # check if point is not on straight line through lineStartPoint and lineEndPoint
327
+ if getPointDistanceToLine(lineStartPoint, lineEndPoint, point, clipAlpha=False) > epsilon:
328
+ return False
329
+ # check if point is in between lineStartPoint and lineEndPoint
330
+ if isPointProjectionOnLineBetweenPoints(point, lineStartPoint, lineEndPoint):
331
+ return True
332
+ return False
333
+
334
+
335
+ def getLineLoop(lines, startLine=None):
336
+ """retuns a list of lines in the correct order"""
337
+
338
+ def isAdjacentLine(line, otherLine):
339
+ return bool({line.p1, line.p2} & {otherLine.p1, otherLine.p2})
340
+
341
+ if len(lines) == 1:
342
+ return lines, [1]
343
+
344
+ linesCopy = lines[:]
345
+ if startLine is not None:
346
+ ix = linesCopy.index(startLine)
347
+ if ix == -1:
348
+ firstLine = linesCopy[0]
349
+ else:
350
+ firstLine = linesCopy[ix]
351
+ else:
352
+ firstLine = linesCopy[0]
353
+
354
+ loop = [firstLine]
355
+ linesCopy.remove(firstLine)
356
+
357
+ curLine = None
358
+ adjLines = [line for line in linesCopy if isAdjacentLine(line, loop[0])]
359
+ if adjLines:
360
+ curLine = next((line for line in adjLines if line.p1 == loop[0].p2), None)
361
+ if not curLine:
362
+ curLine = next((line for line in adjLines if line.p2 == loop[0].p2), None)
363
+ if not curLine:
364
+ raise Exception("No matching adjacent line found for line %s" % loop[0].id)
365
+ else:
366
+ raise Exception("No matching adjacent line found for line %s" % loop[0].id)
367
+
368
+ loop.append(curLine)
369
+
370
+ linesCopy.pop(linesCopy.index(curLine))
371
+ while len(linesCopy) > 0:
372
+ nextLineIx = next(i for i, line in enumerate(linesCopy) if isAdjacentLine(line, curLine))
373
+ loop.append(linesCopy[nextLineIx])
374
+ curLine = linesCopy[nextLineIx]
375
+ linesCopy.pop(nextLineIx)
376
+
377
+ lineOrientation = [1]
378
+ cmpFuncDict = {-1: eq, 1: ne}
379
+ for i, line in enumerate(loop[1:], 1):
380
+
381
+ cmpFunc = cmpFuncDict[lineOrientation[i - 1]]
382
+
383
+ prevLinePoints = loop[i - 1].keypoints[:: lineOrientation[i - 1]]
384
+
385
+ if cmpFunc(line.p1.id, prevLinePoints[-1].id):
386
+ muliplier = -1
387
+ else:
388
+ muliplier = 1
389
+
390
+ lineOrientation.append(lineOrientation[i - 1] * muliplier)
391
+
392
+ return loop, lineOrientation
393
+
394
+
395
+ def getAngleBetweenVectors(vector1, vector2):
396
+ """calcuclates the angle [°] between two vectors
397
+
398
+ >>> angle = getAngleBetweenVectors([1,0,0],[0,1,0])
399
+ >>> round(angle,1)
400
+ 90.0
401
+ >>> angle = getAngleBetweenVectors([1,0,0],[1,1,0])
402
+ >>> round(angle,1)
403
+ 45.0
404
+ >>> angle = getAngleBetweenVectors([1,0,0],[1,0,0])
405
+ >>> round(angle,1)
406
+ 0.0
407
+ """
408
+ vector1, vector2 = np.array(vector1), np.array(vector2)
409
+
410
+ nominator = np.dot(vector1, vector2)
411
+ denominator = np.linalg.norm(vector1) * np.linalg.norm(vector2)
412
+ fraction = nominator / denominator
413
+ if abs(fraction - 1) < epsilon:
414
+ angleRad = 0.0
415
+ elif abs(fraction + 1) < epsilon:
416
+ angleRad = np.pi
417
+ else:
418
+ angleRad = np.arccos(fraction)
419
+ angle = np.degrees(angleRad)
420
+ return angle