c4dynamics 2.0.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.
- c4dynamics/__init__.py +240 -0
- c4dynamics/datasets/__init__.py +95 -0
- c4dynamics/datasets/_manager.py +596 -0
- c4dynamics/datasets/_registry.py +80 -0
- c4dynamics/detectors/__init__.py +37 -0
- c4dynamics/detectors/yolo3_opencv.py +686 -0
- c4dynamics/detectors/yolo3_tf.py +124 -0
- c4dynamics/eqm/__init__.py +324 -0
- c4dynamics/eqm/derivs.py +212 -0
- c4dynamics/eqm/integrate.py +359 -0
- c4dynamics/filters/__init__.py +1373 -0
- c4dynamics/filters/a.py +48 -0
- c4dynamics/filters/ekf.py +320 -0
- c4dynamics/filters/kalman.py +725 -0
- c4dynamics/filters/kalman_v0.py +1071 -0
- c4dynamics/filters/kalman_v1.py +821 -0
- c4dynamics/filters/lowpass.py +123 -0
- c4dynamics/filters/luenberger.py +97 -0
- c4dynamics/rotmat/__init__.py +141 -0
- c4dynamics/rotmat/animate.py +465 -0
- c4dynamics/rotmat/rotmat.py +351 -0
- c4dynamics/sensors/__init__.py +72 -0
- c4dynamics/sensors/lineofsight.py +78 -0
- c4dynamics/sensors/radar.py +740 -0
- c4dynamics/sensors/seeker.py +1030 -0
- c4dynamics/states/__init__.py +327 -0
- c4dynamics/states/lib/__init__.py +320 -0
- c4dynamics/states/lib/datapoint.py +660 -0
- c4dynamics/states/lib/pixelpoint.py +776 -0
- c4dynamics/states/lib/rigidbody.py +677 -0
- c4dynamics/states/state.py +1486 -0
- c4dynamics/utils/__init__.py +44 -0
- c4dynamics/utils/_struct.py +6 -0
- c4dynamics/utils/const.py +130 -0
- c4dynamics/utils/cprint.py +80 -0
- c4dynamics/utils/gen_gif.py +142 -0
- c4dynamics/utils/idx2keys.py +4 -0
- c4dynamics/utils/images_loader.py +63 -0
- c4dynamics/utils/math.py +136 -0
- c4dynamics/utils/plottools.py +140 -0
- c4dynamics/utils/plottracks.py +304 -0
- c4dynamics/utils/printpts.py +36 -0
- c4dynamics/utils/slides_gen.py +64 -0
- c4dynamics/utils/tictoc.py +167 -0
- c4dynamics/utils/video_gen.py +300 -0
- c4dynamics/utils/vidgen.py +182 -0
- c4dynamics-2.0.3.dist-info/METADATA +242 -0
- c4dynamics-2.0.3.dist-info/RECORD +50 -0
- c4dynamics-2.0.3.dist-info/WHEEL +5 -0
- c4dynamics-2.0.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#
|
|
2
|
+
# utils __init__
|
|
3
|
+
##
|
|
4
|
+
|
|
5
|
+
# from . import plottools
|
|
6
|
+
# from . import gen_gif
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
sys.path.append('.')
|
|
10
|
+
vi = sys.version_info
|
|
11
|
+
|
|
12
|
+
if vi.minor <= 7:
|
|
13
|
+
from c4dynamics.utils.images_loader import *
|
|
14
|
+
|
|
15
|
+
# from . import const
|
|
16
|
+
# from . import math
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
|
|
22
|
+
import doctest, contextlib, os
|
|
23
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
24
|
+
|
|
25
|
+
# Register the custom OutputChecker
|
|
26
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
27
|
+
|
|
28
|
+
tofile = False
|
|
29
|
+
optionflags = doctest.FAIL_FAST
|
|
30
|
+
|
|
31
|
+
if tofile:
|
|
32
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
33
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
34
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
35
|
+
else:
|
|
36
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
37
|
+
|
|
38
|
+
if result.failed == 0:
|
|
39
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
40
|
+
else:
|
|
41
|
+
print(f"{result.failed}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
__doc__ = '''
|
|
4
|
+
Globals and conversion constants.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
C4dynamics includes several constants as global quantities
|
|
8
|
+
and conversion units:
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Global Constants
|
|
12
|
+
----------------
|
|
13
|
+
|
|
14
|
+
.. data:: pi
|
|
15
|
+
|
|
16
|
+
The ratio of a circle's circumference to its diameter.
|
|
17
|
+
C4dynamics' pi is a simple assignment of numpy.pi:
|
|
18
|
+
|
|
19
|
+
``pi = 3.1415926535897932384626433...``
|
|
20
|
+
|
|
21
|
+
.. rubric:: Reference
|
|
22
|
+
|
|
23
|
+
https://en.wikipedia.org/wiki/Pi
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
.. data:: g_ms2
|
|
27
|
+
|
|
28
|
+
Gravity of earth in meter per square second.
|
|
29
|
+
|
|
30
|
+
``g = 9.80665``
|
|
31
|
+
|
|
32
|
+
.. rubric:: Reference
|
|
33
|
+
|
|
34
|
+
https://en.wikipedia.org/wiki/Gravity_of_Earth
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
.. data:: g_fts2
|
|
38
|
+
|
|
39
|
+
Gravity of earth in foot per square second.
|
|
40
|
+
|
|
41
|
+
``g = 32.1740``
|
|
42
|
+
|
|
43
|
+
.. rubric:: Reference
|
|
44
|
+
|
|
45
|
+
https://en.wikipedia.org/wiki/Gravity_of_Earth
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
Conversion Constants
|
|
50
|
+
--------------------
|
|
51
|
+
|
|
52
|
+
.. data:: ft2m
|
|
53
|
+
|
|
54
|
+
foot to meter.
|
|
55
|
+
|
|
56
|
+
``ft2m = 0.3048``
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
.. data:: lbft2tokgm2
|
|
60
|
+
|
|
61
|
+
pound square foot to kilogram square meter.
|
|
62
|
+
|
|
63
|
+
``lbft2tokgm2 = 4.88243``
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
.. data:: r2d
|
|
67
|
+
|
|
68
|
+
radians to degrees.
|
|
69
|
+
|
|
70
|
+
``r2d = 57.2958``
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
.. data:: d2r
|
|
74
|
+
|
|
75
|
+
degrees to radians.
|
|
76
|
+
|
|
77
|
+
``d2r = 0.0174533``
|
|
78
|
+
|
|
79
|
+
.. data:: k2ms
|
|
80
|
+
|
|
81
|
+
knots to meters per second
|
|
82
|
+
|
|
83
|
+
``k2ms = 0.514444``
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
'''
|
|
87
|
+
|
|
88
|
+
import sys
|
|
89
|
+
sys.path.append('.')
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# global quantities
|
|
93
|
+
pi = np.pi
|
|
94
|
+
g_ms2 = 9.80665 # m/s^2
|
|
95
|
+
g_fts2 = 32.1740 # ft/s^2
|
|
96
|
+
|
|
97
|
+
# conversion variables
|
|
98
|
+
ft2m = 0.3048 # 1 #
|
|
99
|
+
lbft2tokgm2 = 4.88243 # 47.8803 to include gravity # 1
|
|
100
|
+
r2d = 180 / np.pi
|
|
101
|
+
d2r = np.pi / 180
|
|
102
|
+
kmh2ms = 1000 / 3600
|
|
103
|
+
k2ms = 1852 / 3600 # knots to meter per second
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
|
|
109
|
+
import doctest, contextlib, os
|
|
110
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
111
|
+
|
|
112
|
+
# Register the custom OutputChecker
|
|
113
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
114
|
+
|
|
115
|
+
tofile = False
|
|
116
|
+
optionflags = doctest.FAIL_FAST
|
|
117
|
+
|
|
118
|
+
if tofile:
|
|
119
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
120
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
121
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
122
|
+
else:
|
|
123
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
124
|
+
|
|
125
|
+
if result.failed == 0:
|
|
126
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
127
|
+
else:
|
|
128
|
+
print(f"{result.failed}")
|
|
129
|
+
|
|
130
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
sys.path.append('.')
|
|
3
|
+
|
|
4
|
+
TXTCOLORS = { 'k': '30', 'black': '30'
|
|
5
|
+
, 'r': '31', 'red': '31'
|
|
6
|
+
, 'g': '32', 'green': '32'
|
|
7
|
+
, 'y': '33', 'yellow': '33'
|
|
8
|
+
, 'b': '34', 'blue': '34'
|
|
9
|
+
, 'm': '35', 'magenta': '35'
|
|
10
|
+
, 'c': '36', 'cyan': '36'
|
|
11
|
+
, 'w': '37', 'white': '37'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def cprint(txt = '', color = 'white', end = '\n'):
|
|
15
|
+
'''
|
|
16
|
+
Printing colored text in the console.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
|
|
21
|
+
txt : str
|
|
22
|
+
The text to be printed.
|
|
23
|
+
|
|
24
|
+
color : str, optional
|
|
25
|
+
The color of the text. Default is 'white'.
|
|
26
|
+
|
|
27
|
+
Example
|
|
28
|
+
-------
|
|
29
|
+
|
|
30
|
+
.. code::
|
|
31
|
+
|
|
32
|
+
>>> carr = ['y', 'w', 'r', 'm', 'c', 'g', 'k', 'b']
|
|
33
|
+
>>> for c in carr:
|
|
34
|
+
... c4d.cprint('C4DYNAMICS', c)
|
|
35
|
+
|
|
36
|
+
.. raw:: html
|
|
37
|
+
|
|
38
|
+
<span style="color:yellow">C4DYNAMICS</span><br>
|
|
39
|
+
<span style="color:white">C4DYNAMICS</span><br>
|
|
40
|
+
<span style="color:red">C4DYNAMICS</span><br>
|
|
41
|
+
<span style="color:magenta">C4DYNAMICS</span><br>
|
|
42
|
+
<span style="color:cyan">C4DYNAMICS</span><br>
|
|
43
|
+
<span style="color:green">C4DYNAMICS</span><br>
|
|
44
|
+
<span style="color:black">C4DYNAMICS</span><br>
|
|
45
|
+
<span style="color:blue">C4DYNAMICS</span><br>
|
|
46
|
+
|
|
47
|
+
'''
|
|
48
|
+
settxt = '\033['
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
settxt += TXTCOLORS[color]
|
|
52
|
+
|
|
53
|
+
print(settxt + 'm' + str(txt) + '\033[0m', end = end)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
|
|
58
|
+
import os
|
|
59
|
+
import doctest, contextlib
|
|
60
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
61
|
+
|
|
62
|
+
# Register the custom OutputChecker
|
|
63
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
64
|
+
|
|
65
|
+
tofile = False
|
|
66
|
+
optionflags = doctest.FAIL_FAST
|
|
67
|
+
|
|
68
|
+
if tofile:
|
|
69
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
70
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
71
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
72
|
+
else:
|
|
73
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
74
|
+
|
|
75
|
+
if result.failed == 0:
|
|
76
|
+
cprint("All tests passed!", 'g')
|
|
77
|
+
else:
|
|
78
|
+
print(f"{result.failed}")
|
|
79
|
+
|
|
80
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import imageio
|
|
3
|
+
import natsort
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
sys.path.append('.')
|
|
8
|
+
import c4dynamics as c4d
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def gif(dirname, gif_name, duration = None):
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
Gif creator.
|
|
15
|
+
|
|
16
|
+
`gif` creates a Gif from a directory containing image files.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
|
|
21
|
+
dirname : str
|
|
22
|
+
The path to the directory containing image files.
|
|
23
|
+
|
|
24
|
+
gif_name : str
|
|
25
|
+
The desired name of the output GIF file.
|
|
26
|
+
|
|
27
|
+
duration : float, optional
|
|
28
|
+
The duration (in seconds) for each frame of the GIF.
|
|
29
|
+
If None, default duration is used.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
Example
|
|
33
|
+
-------
|
|
34
|
+
|
|
35
|
+
1. Prepare trajectory to animate.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Import required packages:
|
|
39
|
+
|
|
40
|
+
.. code::
|
|
41
|
+
|
|
42
|
+
>>> import c4dynamics as c4d
|
|
43
|
+
>>> from IPython.display import Image
|
|
44
|
+
>>> import numpy as np
|
|
45
|
+
>>> import os
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Settings and initial conditions:
|
|
49
|
+
|
|
50
|
+
.. code::
|
|
51
|
+
|
|
52
|
+
>>> f16 = c4d.rigidbody()
|
|
53
|
+
>>> dt = 0.01
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
Main loop:
|
|
57
|
+
|
|
58
|
+
.. code::
|
|
59
|
+
|
|
60
|
+
>>> for t in np.arange(0, 9, dt):
|
|
61
|
+
... # in 3 seconds make 180 deg:
|
|
62
|
+
... if t < 3:
|
|
63
|
+
... f16.psi += dt * 180 * c4d.d2r / 3
|
|
64
|
+
... elif t < 6:
|
|
65
|
+
... f16.theta += dt * 180 * c4d.d2r / 3
|
|
66
|
+
... else:
|
|
67
|
+
... f16.phi -= dt * 180 * c4d.d2r / 3
|
|
68
|
+
... f16.store(t)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
2. Animate and save image files.
|
|
72
|
+
|
|
73
|
+
(Use c4dynamics' :mod:`datasets <c4dynamics.datasets>` to fetch F16 3D model.)
|
|
74
|
+
|
|
75
|
+
.. code::
|
|
76
|
+
|
|
77
|
+
>>> f16path = c4d.datasets.d3_model('f16')
|
|
78
|
+
Fetched successfully
|
|
79
|
+
>>> x0 = [90 * c4d.d2r, 0, 180 * c4d.d2r]
|
|
80
|
+
>>> outfol = os.path.join('tests', '_out', 'f16b')
|
|
81
|
+
>>> f16.animate(f16path, savedir = outfol, angle0 = x0, modelcolor = [0, 0, 0], cbackground = [230 / 255, 230 / 255, 255 / 255])
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
3. Export images as gif.
|
|
85
|
+
|
|
86
|
+
.. code::
|
|
87
|
+
|
|
88
|
+
>>> gifname = 'f16_monochrome_gif.gif'
|
|
89
|
+
>>> c4d.gif(outfol, gifname, duration = 1)
|
|
90
|
+
>>> Image(filename = os.path.join(outfol, gifname)) # doctest: +IGNORE_OUTPUT
|
|
91
|
+
|
|
92
|
+
.. figure:: /_examples/animate/f16_monochrome_gif.gif
|
|
93
|
+
|
|
94
|
+
'''
|
|
95
|
+
dirfiles = natsort.natsorted(os.listdir(dirname))
|
|
96
|
+
imgfiles = [f for f in dirfiles if f.lower().endswith(('.png', '.jpg', '.jpeg', 'bmp', '.tiff'))]
|
|
97
|
+
|
|
98
|
+
if not imgfiles:
|
|
99
|
+
warnings.warn(f"""No image files in {dirfiles}. ('.png', '.jpg', '.jpeg', 'bmp', '.tiff', are supported). """ , c4d.c4warn)
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
fps = 60 # 60hz (60frames per second) -> 16.6msec
|
|
103
|
+
if duration is None:
|
|
104
|
+
interval = 1
|
|
105
|
+
else:
|
|
106
|
+
# FIXME sth here is wrong. see the test test_specified_fps_effect currently disabled.
|
|
107
|
+
interval = max(int(len(imgfiles) / (duration * fps)), 1)
|
|
108
|
+
|
|
109
|
+
images = []
|
|
110
|
+
|
|
111
|
+
for i in range(0, len(imgfiles), interval):
|
|
112
|
+
images.append(imageio.v2.imread(os.path.join(dirname, imgfiles[i])))
|
|
113
|
+
|
|
114
|
+
gif_name = gif_name if gif_name.endswith('.gif') else gif_name + '.gif'
|
|
115
|
+
imageio.mimsave(os.path.join(dirname, gif_name)
|
|
116
|
+
, images, loop = 0, duration = int(1000 * 1 / fps))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
|
|
121
|
+
import doctest, contextlib
|
|
122
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
123
|
+
|
|
124
|
+
# Register the custom OutputChecker
|
|
125
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
126
|
+
|
|
127
|
+
tofile = False
|
|
128
|
+
optionflags = doctest.FAIL_FAST
|
|
129
|
+
|
|
130
|
+
if tofile:
|
|
131
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
132
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
133
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
134
|
+
else:
|
|
135
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
136
|
+
|
|
137
|
+
if result.failed == 0:
|
|
138
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
139
|
+
else:
|
|
140
|
+
print(f"{result.failed}")
|
|
141
|
+
|
|
142
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# sngl3
|
|
2
|
+
# load single image as 3 layers rgb
|
|
3
|
+
# snglv
|
|
4
|
+
# load single image as a row vector
|
|
5
|
+
# mltpl3
|
|
6
|
+
# load multiple images as 3 layers rgb
|
|
7
|
+
# mltplv
|
|
8
|
+
# load mulitple images as an array where each row is an image
|
|
9
|
+
|
|
10
|
+
import glob
|
|
11
|
+
import numpy as np
|
|
12
|
+
from matplotlib import image
|
|
13
|
+
|
|
14
|
+
def sngl3(file):
|
|
15
|
+
err1 = False
|
|
16
|
+
if file.lower().endswith(('.png', '.jpg', '.jpeg')):
|
|
17
|
+
img = image.imread(file)
|
|
18
|
+
if img is None:
|
|
19
|
+
err1 = True
|
|
20
|
+
else:
|
|
21
|
+
err1 = True
|
|
22
|
+
|
|
23
|
+
if err1:
|
|
24
|
+
print(file + ' is not an image file')
|
|
25
|
+
else:
|
|
26
|
+
return img
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def snglv(file):
|
|
30
|
+
err1 = False
|
|
31
|
+
if file.lower().endswith(('.png', '.jpg', '.jpeg')):
|
|
32
|
+
img = image.imread(file)
|
|
33
|
+
if img is None:
|
|
34
|
+
err1 = True
|
|
35
|
+
else:
|
|
36
|
+
err1 = True
|
|
37
|
+
|
|
38
|
+
if err1:
|
|
39
|
+
print(file + ' is not an image file')
|
|
40
|
+
else:
|
|
41
|
+
img = np.reshape(img, (1, -1)) # the unspecified value is inferred as ..
|
|
42
|
+
return img
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def mltpl3(folder):
|
|
46
|
+
images = []
|
|
47
|
+
for f in glob.glob(folder):
|
|
48
|
+
if f.lower().endswith(('.png', '.jpg', '.jpeg')):
|
|
49
|
+
img = image.imread(f)
|
|
50
|
+
if img is not None:
|
|
51
|
+
images.append(img)
|
|
52
|
+
return images
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def mltplv(folder):
|
|
56
|
+
images = []
|
|
57
|
+
for f in glob.glob(folder):
|
|
58
|
+
if f.lower().endswith(('.png', '.jpg', '.jpeg')):
|
|
59
|
+
img = image.imread(f)
|
|
60
|
+
if img is not None:
|
|
61
|
+
img = np.reshape(img, (1, -1))
|
|
62
|
+
images.append(img)
|
|
63
|
+
return images
|
c4dynamics/utils/math.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.special import erfinv
|
|
3
|
+
import sys
|
|
4
|
+
sys.path.append('.')
|
|
5
|
+
import c4dynamics as c4d
|
|
6
|
+
|
|
7
|
+
__doc__ = '''
|
|
8
|
+
Math functions aliasing.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
For convenience, C4dynamics aliases some of
|
|
12
|
+
NumPy's trigonometric functions
|
|
13
|
+
with slight variations in some of them:
|
|
14
|
+
|
|
15
|
+
.. code::
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
import c4dynamics as c4d
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
.. data:: sin
|
|
22
|
+
|
|
23
|
+
``c4d.sin = np.sin``
|
|
24
|
+
|
|
25
|
+
.. data:: sind
|
|
26
|
+
|
|
27
|
+
``c4d.sind = lambda n: np.sin(n * c4d.d2r)``
|
|
28
|
+
|
|
29
|
+
.. data:: cos
|
|
30
|
+
|
|
31
|
+
``c4d.cos = np.cos``
|
|
32
|
+
|
|
33
|
+
.. data:: cosd
|
|
34
|
+
|
|
35
|
+
``c4d.cosd = lambda n: np.cos(n * c4d.d2r)``
|
|
36
|
+
|
|
37
|
+
.. data:: tan
|
|
38
|
+
|
|
39
|
+
``c4d.tan = np.tan``
|
|
40
|
+
|
|
41
|
+
.. data:: tand
|
|
42
|
+
|
|
43
|
+
``c4d.tand = lambda n: np.tan(n * c4d.d2r)``
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
.. data:: asin
|
|
47
|
+
|
|
48
|
+
``c4d.asin = np.arcsin``
|
|
49
|
+
|
|
50
|
+
.. data:: asind
|
|
51
|
+
|
|
52
|
+
``c4d.asind = lambda n: np.arcsin(n) * c4d.r2d``
|
|
53
|
+
|
|
54
|
+
.. data:: acos
|
|
55
|
+
|
|
56
|
+
``c4d.acos = np.arccos``
|
|
57
|
+
|
|
58
|
+
.. data:: acosd
|
|
59
|
+
|
|
60
|
+
``c4d.acosd = lambda n: np.arccos(n) * c4d.r2d``
|
|
61
|
+
|
|
62
|
+
.. data:: atan
|
|
63
|
+
|
|
64
|
+
``c4d.atan = np.arctan``
|
|
65
|
+
|
|
66
|
+
.. data:: atan2
|
|
67
|
+
|
|
68
|
+
``c4d.atan2 = np.arctan2``
|
|
69
|
+
|
|
70
|
+
.. data:: atan2d
|
|
71
|
+
|
|
72
|
+
``c4d.atan2d = lambda y, x: np.arctan2(y, x) * c4d.r2d``
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
.. data:: sqrt
|
|
76
|
+
|
|
77
|
+
``c4d.sqrt = np.sqrt``
|
|
78
|
+
|
|
79
|
+
.. data:: norm
|
|
80
|
+
|
|
81
|
+
``c4d.norm = np.linalg.norm``
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
'''
|
|
85
|
+
sin = np.sin
|
|
86
|
+
sind = lambda n: np.sin(n * c4d.d2r)
|
|
87
|
+
cos = np.cos
|
|
88
|
+
cosd = lambda n: np.cos(n * c4d.d2r)
|
|
89
|
+
tan = np.tan
|
|
90
|
+
tand = lambda n: np.tan(n * c4d.d2r)
|
|
91
|
+
|
|
92
|
+
asin = np.arcsin
|
|
93
|
+
asind = lambda n: np.arcsin(n) * c4d.r2d
|
|
94
|
+
acos = np.arccos
|
|
95
|
+
acosd = lambda n: np.arccos(n) * c4d.r2d
|
|
96
|
+
atan = np.arctan
|
|
97
|
+
atand = lambda n: np.arctan(n) * c4d.r2d
|
|
98
|
+
atan2 = np.arctan2 # atan2(y, x)
|
|
99
|
+
atan2d = lambda y, x: np.arctan2(y, x) * c4d.r2d # atan2(y, x)
|
|
100
|
+
|
|
101
|
+
sqrt = np.sqrt
|
|
102
|
+
norm = np.linalg.norm
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# mrandn preserves matlab normal distributed numbers generation
|
|
106
|
+
# XXX it doesnt preserve anything. just a suggested implementation to make in both sides.
|
|
107
|
+
# no more it also doesnt generate normal distribution. see also the test test_mrandn currently disabled.
|
|
108
|
+
mrandn = lambda n = 1: np.sqrt(2) * erfinv(2 * np.random.rand(n) - 1)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
|
|
114
|
+
import doctest, contextlib, os
|
|
115
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
116
|
+
|
|
117
|
+
# Register the custom OutputChecker
|
|
118
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
119
|
+
|
|
120
|
+
tofile = False
|
|
121
|
+
optionflags = doctest.FAIL_FAST
|
|
122
|
+
|
|
123
|
+
if tofile:
|
|
124
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
125
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
126
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
127
|
+
else:
|
|
128
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
129
|
+
|
|
130
|
+
if result.failed == 0:
|
|
131
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
132
|
+
else:
|
|
133
|
+
print(f"{result.failed}")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|