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
c4dynamics/__init__.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
'''
|
|
2
|
+
|
|
3
|
+
C4DYNAMICS
|
|
4
|
+
==========
|
|
5
|
+
|
|
6
|
+
c4dynamics provides
|
|
7
|
+
1. State objects as fundamental data structure for dynamic systems.
|
|
8
|
+
2. Internal systems and 3rd party integrated libraries.
|
|
9
|
+
3. Fast algorithmic operations over objects and systems.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
How to use the documentation
|
|
13
|
+
----------------------------
|
|
14
|
+
Documentation is currently availble through examples,
|
|
15
|
+
readme pages, and inline comments.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Available subpackages
|
|
19
|
+
---------------------
|
|
20
|
+
sensors
|
|
21
|
+
Models of EO and EM sensors.
|
|
22
|
+
detectors
|
|
23
|
+
Objects detection models to computer vision manipulations.
|
|
24
|
+
filters
|
|
25
|
+
Kalman and lowpass filters.
|
|
26
|
+
eqm
|
|
27
|
+
Runge Kutta solvers for integrating the equations of motion on the datapoint and rigidbody objects.
|
|
28
|
+
rotmat
|
|
29
|
+
Rotation matrices and rotational operations.
|
|
30
|
+
'''
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
import os
|
|
34
|
+
import doctest
|
|
35
|
+
import warnings
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# body objects
|
|
41
|
+
##
|
|
42
|
+
from .states.state import state
|
|
43
|
+
from .states.lib.pixelpoint import pixelpoint
|
|
44
|
+
from .states.lib.datapoint import datapoint, create
|
|
45
|
+
from . import rotmat
|
|
46
|
+
# rotmat is required to import rigidbody:
|
|
47
|
+
from .states.lib.rigidbody import rigidbody # rotmat is required to import rigidbody.
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# routines
|
|
51
|
+
##
|
|
52
|
+
from . import eqm
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# utils
|
|
56
|
+
##
|
|
57
|
+
from .utils.const import *
|
|
58
|
+
from .utils.math import *
|
|
59
|
+
from .utils.gen_gif import gif
|
|
60
|
+
from .utils.cprint import cprint
|
|
61
|
+
from .utils.plottools import plotdefaults, _figdef, _legdef
|
|
62
|
+
from .utils import tictoc
|
|
63
|
+
from .utils.tictoc import tic, toc
|
|
64
|
+
from .utils._struct import struct
|
|
65
|
+
from .utils.idx2keys import idx2keys
|
|
66
|
+
from . import datasets
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
#
|
|
70
|
+
# sensors
|
|
71
|
+
##
|
|
72
|
+
from . import sensors
|
|
73
|
+
from . import filters
|
|
74
|
+
from . import detectors
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
# version
|
|
81
|
+
##
|
|
82
|
+
__version__ = '2.0.3'
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
#
|
|
86
|
+
# some convinient mirroring
|
|
87
|
+
##
|
|
88
|
+
j = os.path.join
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# warnings
|
|
94
|
+
##
|
|
95
|
+
class c4warn(UserWarning): pass
|
|
96
|
+
|
|
97
|
+
# customize the warning messages:
|
|
98
|
+
YELLOW = "\033[93m"
|
|
99
|
+
RESET = "\033[0m" # Reset color to default
|
|
100
|
+
# Override showwarning to globally apply custom formatting
|
|
101
|
+
def show_warning(message, category, filename, lineno, file = None, line = None):
|
|
102
|
+
|
|
103
|
+
if issubclass(category, c4warn):
|
|
104
|
+
# Apply formatting for c4warn warnings
|
|
105
|
+
|
|
106
|
+
# FIXME suppressing is absolutely not working.
|
|
107
|
+
message1 = str(message) + f"\n"
|
|
108
|
+
message2 = f"To suppress c4dynamics' warnings, run: import warnings, import c4dynamics as c4d, warnings.simplefilter('ignore', c4d.c4warn)\n"
|
|
109
|
+
|
|
110
|
+
print(f"\n{YELLOW}{message1}{RESET}{message2} (File: {filename}, Line: {lineno})")
|
|
111
|
+
else:
|
|
112
|
+
# For other warnings, use the default behavior
|
|
113
|
+
print(f"{category.__name__}: {message} (File: {filename}, Line: {lineno})")
|
|
114
|
+
|
|
115
|
+
warnings.showwarning = show_warning
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class IgnoreOutputChecker(doctest.OutputChecker):
|
|
120
|
+
from typing import Union
|
|
121
|
+
|
|
122
|
+
IGNORE_OUTPUT = doctest.register_optionflag("IGNORE_OUTPUT") # 2048
|
|
123
|
+
NUMPY_FORMAT = doctest.register_optionflag("NUMPY_FORMAT") # 4096
|
|
124
|
+
|
|
125
|
+
def check_output(self, want, got, optionflags):
|
|
126
|
+
|
|
127
|
+
# If the IGNORE_OUTPUT flag is set, always return True
|
|
128
|
+
if optionflags & self.IGNORE_OUTPUT:
|
|
129
|
+
return True
|
|
130
|
+
|
|
131
|
+
# If NUMPY_FORMAT flag is set, compare NumPy arrays with formatting tolerance
|
|
132
|
+
if optionflags & self.NUMPY_FORMAT:
|
|
133
|
+
want = self._convert_to_array(want)
|
|
134
|
+
got = self._convert_to_array(got)
|
|
135
|
+
if want is not None and got is not None:
|
|
136
|
+
|
|
137
|
+
abs_tol = 1e-3
|
|
138
|
+
rel_tol = 1e-3
|
|
139
|
+
|
|
140
|
+
if False:
|
|
141
|
+
|
|
142
|
+
# Calculate element-wise absolute and relative differences
|
|
143
|
+
# if diff < abs (for small values) OR diff/want < rel (for large values)
|
|
144
|
+
np.abs(want - got) < abs_tol
|
|
145
|
+
np.abs((want - got) / np.where(want != 0, want, np.inf)) < rel_tol
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
return np.allclose(want, got, atol = abs_tol, rtol = rel_tol)
|
|
149
|
+
|
|
150
|
+
# Otherwise, fall back to the original behavior
|
|
151
|
+
return super().check_output(want, got, optionflags) # type: ignore
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _convert_to_array(self, text):
|
|
155
|
+
|
|
156
|
+
import re
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
"""Attempt to convert text to a NumPy array for comparison."""
|
|
160
|
+
try:
|
|
161
|
+
|
|
162
|
+
if ',' not in text:
|
|
163
|
+
text = re.sub(r'\s+', ',', text.strip())
|
|
164
|
+
|
|
165
|
+
# Remove extraneous text like 'array(' and closing ')' using regex
|
|
166
|
+
clean_text = re.sub(r'(array\(|\))', '', text).strip()
|
|
167
|
+
# Remove brackets
|
|
168
|
+
clean_text = re.sub(r'[\[\]]', '', clean_text)
|
|
169
|
+
|
|
170
|
+
# Convert to NumPy array
|
|
171
|
+
return np.fromstring(clean_text, sep = ',')
|
|
172
|
+
|
|
173
|
+
except ValueError:
|
|
174
|
+
return None # Return None if conversion fails
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# just find the package root folder:
|
|
178
|
+
|
|
179
|
+
def c4dir(dir, addpath = ''):
|
|
180
|
+
# dirname and basename are supplamentary:
|
|
181
|
+
# c:\dropbox\c4dynamics\text.txt
|
|
182
|
+
# dirname: c:\dropbox\c4dynamics
|
|
183
|
+
# basename: text.txt
|
|
184
|
+
|
|
185
|
+
inc4d = os.path.basename(dir) == 'c4dynamics'
|
|
186
|
+
hasc4d = any(f == 'c4dynamics' for f in os.listdir(dir)
|
|
187
|
+
if os.path.isdir(os.path.join(dir, f)))
|
|
188
|
+
|
|
189
|
+
if inc4d and hasc4d:
|
|
190
|
+
addpath += ''
|
|
191
|
+
return addpath
|
|
192
|
+
|
|
193
|
+
addpath += '..\\'
|
|
194
|
+
return c4dir(os.path.dirname(dir), addpath)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
#
|
|
198
|
+
# TODO BUG FIXME HACK NOTE XXX
|
|
199
|
+
#
|
|
200
|
+
# TODO IMPROVMEMNT
|
|
201
|
+
#
|
|
202
|
+
# BUG LOGICAL FAILURE PROBABLY COMES WITH XXX
|
|
203
|
+
# Highlights the presence of a bug or an issue.
|
|
204
|
+
# FIXME NOT SEVERE BUT A BETTER IDEA IS TO DO SO
|
|
205
|
+
# Indicates that there is a problem or bug that needs to be fixed.
|
|
206
|
+
# HACK I KNOW ITS NOT BEST SOLUTION TREAT IF U HAVE SPARE TIME
|
|
207
|
+
# Suggests that a workaround or temporary solution has been implemented and should be revisited.
|
|
208
|
+
# NOTE MORE IMPORTANT THAN A CASUAL COMMENT
|
|
209
|
+
# Provides additional information or context about the code.
|
|
210
|
+
# XXX TREAT THIS BEFORE OTHERS
|
|
211
|
+
# Used to highlight something that is problematic, needs attention, or should be addressed later.
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# FIXME
|
|
216
|
+
# dependencies: for time limits requirementx.txt currently
|
|
217
|
+
# install all. actually maybe 90% of the users use only numpy
|
|
218
|
+
# and pyplot so it's a good practice to offer another full-req.txt
|
|
219
|
+
# file and add an import check for those not necessary:
|
|
220
|
+
import os
|
|
221
|
+
import subprocess
|
|
222
|
+
def ensure_package(package_name):
|
|
223
|
+
try:
|
|
224
|
+
__import__(package_name)
|
|
225
|
+
except ImportError:
|
|
226
|
+
# Check if the user is in a conda environment
|
|
227
|
+
in_conda_env = os.environ.get("CONDA_PREFIX") is not None
|
|
228
|
+
manager = "conda" if in_conda_env else "pip"
|
|
229
|
+
|
|
230
|
+
user_input = input(
|
|
231
|
+
f"{package_name} is required but not installed. "
|
|
232
|
+
f"Would you like to install it with {manager}? (y/n): "
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if user_input.lower() == 'y':
|
|
236
|
+
if manager == "conda":
|
|
237
|
+
subprocess.check_call(["conda", "install", package_name, "-y"])
|
|
238
|
+
else:
|
|
239
|
+
subprocess.check_call(["pip", "install", package_name])
|
|
240
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'''
|
|
2
|
+
|
|
3
|
+
Usage of Datasets
|
|
4
|
+
=================
|
|
5
|
+
|
|
6
|
+
C4dynamics dataset functions can be simply called as follows:
|
|
7
|
+
:code:`c4dynamics.datasets.module(file)`,
|
|
8
|
+
where ``module`` and ``file`` define the dataset.
|
|
9
|
+
The available modules and files are detailed on the corresponding pages.
|
|
10
|
+
This downloads the dataset file over the network once, saves it to the cache,
|
|
11
|
+
and returns the path to the file.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Dataset retrieval and storage
|
|
17
|
+
=============================
|
|
18
|
+
|
|
19
|
+
The YOLOv3 weights file can be found at the official YOLO
|
|
20
|
+
site: `Joseph Redmon <https://pjreddie.com/darknet/yolo/>`_.
|
|
21
|
+
Oher dataset files are available in the
|
|
22
|
+
C4dynamics GitHub repository under
|
|
23
|
+
`datasets <https://github.com/C4dynamics/C4dynamics/blob/main/datasets/>`_
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
C4dynamics.datasets uses
|
|
27
|
+
`Pooch <https://www.fatiando.org/pooch/latest/>`_,
|
|
28
|
+
a Python package designed to simplify fetching data files.
|
|
29
|
+
`Pooch` retrieves the necessary dataset files
|
|
30
|
+
from these repositories when the dataset function is called.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
A registry file of all datasets provides a mapping of filenames
|
|
34
|
+
to their SHA256 hashes and repository URLs
|
|
35
|
+
Pooch uses this registry to manage and verify downloads when the function is called.
|
|
36
|
+
After downloading the dataset once, the files are saved
|
|
37
|
+
in the system cache directory under ``'c4data'``.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
Dataset cache locations may vary on different platforms.
|
|
41
|
+
|
|
42
|
+
For Windows::
|
|
43
|
+
|
|
44
|
+
'C:\\Users\\<user>\\AppData\\Local\\c4data'
|
|
45
|
+
|
|
46
|
+
For macOS::
|
|
47
|
+
|
|
48
|
+
'~/Library/Caches/c4data'
|
|
49
|
+
|
|
50
|
+
For Linux and other Unix-like platforms::
|
|
51
|
+
|
|
52
|
+
'~/.cache/c4data' # or the value of the XDG_CACHE_HOME env var, if defined
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
In environments with constrained network connectivity for various security
|
|
56
|
+
reasons or on systems without continuous internet connections,
|
|
57
|
+
one may manually
|
|
58
|
+
load the cache of the datasets by placing the contents of the dataset repo in
|
|
59
|
+
the above mentioned cache directory to avoid fetching dataset errors without
|
|
60
|
+
the internet connectivity.
|
|
61
|
+
|
|
62
|
+
'''
|
|
63
|
+
|
|
64
|
+
import sys, os
|
|
65
|
+
sys.path.append('.')
|
|
66
|
+
|
|
67
|
+
from c4dynamics.datasets._manager import sha256, image, video, nn_model, d3_model, download_all, clear_cache
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
|
|
74
|
+
import doctest, contextlib
|
|
75
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
76
|
+
|
|
77
|
+
# Register the custom OutputChecker
|
|
78
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
79
|
+
|
|
80
|
+
tofile = False
|
|
81
|
+
optionflags = doctest.FAIL_FAST
|
|
82
|
+
|
|
83
|
+
if tofile:
|
|
84
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
85
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
86
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
87
|
+
else:
|
|
88
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
89
|
+
|
|
90
|
+
if result.failed == 0:
|
|
91
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
92
|
+
else:
|
|
93
|
+
print(f"{result.failed}")
|
|
94
|
+
|
|
95
|
+
|