OpenIRF 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {openirf-0.2.0 → openirf-0.3.0}/PKG-INFO +5 -1
- {openirf-0.2.0 → openirf-0.3.0}/README.md +4 -0
- openirf-0.3.0/docs/experimental_irf.rst +1 -0
- openirf-0.3.0/docs/index.rst +14 -0
- openirf-0.3.0/docs/numerical_irf.rst +1 -0
- openirf-0.3.0/docs/utils.rst +29 -0
- {openirf-0.2.0 → openirf-0.3.0}/pyproject.toml +3 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/PKG-INFO +5 -1
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/SOURCES.txt +6 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/scm_file_list.json +6 -0
- openirf-0.3.0/src/OpenIRF.egg-info/scm_version.json +8 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/openirf/experimental_irf.py +93 -79
- openirf-0.3.0/src/openirf/logo_small.png +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/openirf/numerical_irf.py +1 -1
- openirf-0.3.0/src/openirf/utils.py +872 -0
- openirf-0.3.0/tests/experimental_irf_calculation_test.py +396 -0
- openirf-0.3.0/tests/experimental_time_series_plot_test.py +463 -0
- openirf-0.3.0/tests/interactive_retrigger_test.py +846 -0
- openirf-0.3.0/tests/plot_style_test.py +127 -0
- openirf-0.3.0/tests/retrigger_data_test.py +263 -0
- {openirf-0.2.0 → openirf-0.3.0}/tests/string_print_test.py +5 -3
- openirf-0.3.0/tests/time_series_import_test.py +409 -0
- openirf-0.2.0/docs/experimental_irf.rst +0 -1
- openirf-0.2.0/docs/index.rst +0 -6
- openirf-0.2.0/docs/numerical_irf.rst +0 -1
- openirf-0.2.0/src/OpenIRF.egg-info/scm_version.json +0 -8
- openirf-0.2.0/src/openirf/utils.py +0 -165
- openirf-0.2.0/tests/retrigger_data_test.py +0 -236
- openirf-0.2.0/tests/time_series_import_test.py +0 -324
- {openirf-0.2.0 → openirf-0.3.0}/.gitignore +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/.gitlab-ci.yml +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/.readthedocs.yaml +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/.vscode/settings.json +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/LICENSE +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/docs/Makefile +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/docs/conf.py +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/docs/make.bat +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/docs/requirements.in +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/docs/requirements.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/requirements.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/requirements_dev.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/ruff.toml +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/setup.cfg +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/dependency_links.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/requires.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/OpenIRF.egg-info/top_level.txt +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/src/openirf/__init__.py +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/tests/convolution_matrix_test.py +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/tests/mck_import_test.py +0 -0
- {openirf-0.2.0 → openirf-0.3.0}/tests/numerical_irf_test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenIRF
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: An Open-Source Package for Impulse Response Function Estimation of Mechanical Systems
|
|
5
5
|
Author-email: Oliver Maximilian Zobel <oliver.zobel@tum.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,3 +35,7 @@ A collection of tools for the time domain analysis of mechanical systems.
|
|
|
35
35
|
To install OpenIRF through pip, use the following command:
|
|
36
36
|
|
|
37
37
|
`pip install openirf`
|
|
38
|
+
|
|
39
|
+
## AI Usage Disclosure
|
|
40
|
+
|
|
41
|
+
Claude Code was used to create parts of the tests and plotting functions, as well as to set up the project infrastructure, packaging, and the documentation infrastructure. The main computation code was written by humans and verified using real data.
|
|
@@ -13,3 +13,7 @@ A collection of tools for the time domain analysis of mechanical systems.
|
|
|
13
13
|
To install OpenIRF through pip, use the following command:
|
|
14
14
|
|
|
15
15
|
`pip install openirf`
|
|
16
|
+
|
|
17
|
+
## AI Usage Disclosure
|
|
18
|
+
|
|
19
|
+
Claude Code was used to create parts of the tests and plotting functions, as well as to set up the project infrastructure, packaging, and the documentation infrastructure. The main computation code was written by humans and verified using real data.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.. image:: ../src/openirf/logo_small.png
|
|
2
|
+
:alt: OpenIRF
|
|
3
|
+
:align: center
|
|
4
|
+
:width: 80%
|
|
5
|
+
|
|
6
|
+
**An Open-Source Package for Impulse Response Function Estimation of Mechanical Systems**
|
|
7
|
+
|
|
8
|
+
OpenIRF Documentation
|
|
9
|
+
=======================
|
|
10
|
+
|
|
11
|
+
.. toctree::
|
|
12
|
+
numerical_irf
|
|
13
|
+
experimental_irf
|
|
14
|
+
utils
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
.. image:: ../src/openirf/logo_small.png
|
|
2
|
+
:alt: OpenIRF
|
|
3
|
+
:align: center
|
|
4
|
+
:width: 80%
|
|
5
|
+
|
|
6
|
+
Utility Functions
|
|
7
|
+
=================
|
|
8
|
+
|
|
9
|
+
Interactive Selection Tools
|
|
10
|
+
---------------------------
|
|
11
|
+
|
|
12
|
+
.. autofunction:: openirf.interactive_retrigger
|
|
13
|
+
|
|
14
|
+
Plotting Functions
|
|
15
|
+
------------------
|
|
16
|
+
|
|
17
|
+
.. autofunction:: openirf.experimental_time_series_plot
|
|
18
|
+
|
|
19
|
+
.. autofunction:: openirf.numerical_irf_plot
|
|
20
|
+
|
|
21
|
+
General Utility Functions
|
|
22
|
+
-------------------------
|
|
23
|
+
|
|
24
|
+
.. autofunction:: openirf.build_convolution_matrix
|
|
25
|
+
|
|
26
|
+
.. autofunction:: openirf.newmark_integration
|
|
27
|
+
|
|
28
|
+
.. autofunction:: openirf.extract_impulse_time_series
|
|
29
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenIRF
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: An Open-Source Package for Impulse Response Function Estimation of Mechanical Systems
|
|
5
5
|
Author-email: Oliver Maximilian Zobel <oliver.zobel@tum.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,3 +35,7 @@ A collection of tools for the time domain analysis of mechanical systems.
|
|
|
35
35
|
To install OpenIRF through pip, use the following command:
|
|
36
36
|
|
|
37
37
|
`pip install openirf`
|
|
38
|
+
|
|
39
|
+
## AI Usage Disclosure
|
|
40
|
+
|
|
41
|
+
Claude Code was used to create parts of the tests and plotting functions, as well as to set up the project infrastructure, packaging, and the documentation infrastructure. The main computation code was written by humans and verified using real data.
|
|
@@ -16,6 +16,7 @@ docs/make.bat
|
|
|
16
16
|
docs/numerical_irf.rst
|
|
17
17
|
docs/requirements.in
|
|
18
18
|
docs/requirements.txt
|
|
19
|
+
docs/utils.rst
|
|
19
20
|
src/OpenIRF.egg-info/PKG-INFO
|
|
20
21
|
src/OpenIRF.egg-info/SOURCES.txt
|
|
21
22
|
src/OpenIRF.egg-info/dependency_links.txt
|
|
@@ -25,11 +26,16 @@ src/OpenIRF.egg-info/scm_version.json
|
|
|
25
26
|
src/OpenIRF.egg-info/top_level.txt
|
|
26
27
|
src/openirf/__init__.py
|
|
27
28
|
src/openirf/experimental_irf.py
|
|
29
|
+
src/openirf/logo_small.png
|
|
28
30
|
src/openirf/numerical_irf.py
|
|
29
31
|
src/openirf/utils.py
|
|
30
32
|
tests/convolution_matrix_test.py
|
|
33
|
+
tests/experimental_irf_calculation_test.py
|
|
34
|
+
tests/experimental_time_series_plot_test.py
|
|
35
|
+
tests/interactive_retrigger_test.py
|
|
31
36
|
tests/mck_import_test.py
|
|
32
37
|
tests/numerical_irf_test.py
|
|
38
|
+
tests/plot_style_test.py
|
|
33
39
|
tests/retrigger_data_test.py
|
|
34
40
|
tests/string_print_test.py
|
|
35
41
|
tests/time_series_import_test.py
|
|
@@ -14,17 +14,23 @@
|
|
|
14
14
|
"docs/numerical_irf.rst",
|
|
15
15
|
"docs/requirements.in",
|
|
16
16
|
"docs/requirements.txt",
|
|
17
|
+
"docs/utils.rst",
|
|
17
18
|
"pyproject.toml",
|
|
18
19
|
"requirements.txt",
|
|
19
20
|
"requirements_dev.txt",
|
|
20
21
|
"ruff.toml",
|
|
21
22
|
"src/openirf/__init__.py",
|
|
22
23
|
"src/openirf/experimental_irf.py",
|
|
24
|
+
"src/openirf/logo_small.png",
|
|
23
25
|
"src/openirf/numerical_irf.py",
|
|
24
26
|
"src/openirf/utils.py",
|
|
25
27
|
"tests/convolution_matrix_test.py",
|
|
28
|
+
"tests/experimental_irf_calculation_test.py",
|
|
29
|
+
"tests/experimental_time_series_plot_test.py",
|
|
30
|
+
"tests/interactive_retrigger_test.py",
|
|
26
31
|
"tests/mck_import_test.py",
|
|
27
32
|
"tests/numerical_irf_test.py",
|
|
33
|
+
"tests/plot_style_test.py",
|
|
28
34
|
"tests/retrigger_data_test.py",
|
|
29
35
|
"tests/string_print_test.py",
|
|
30
36
|
"tests/time_series_import_test.py"
|
|
@@ -12,9 +12,10 @@ class ExperimentalIRF:
|
|
|
12
12
|
|
|
13
13
|
Shape of time series arrays
|
|
14
14
|
---------------------------
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
15
|
+
- SISO: ``y_vec`` with shape ``(n_t)``, ``f_vec`` with shape ``(n_t)``
|
|
16
|
+
- SISO with averaging: ``y_vec`` with shape ``(n_avg,n_t)``, ``f_vec`` with shape ``(n_avg,n_t)``
|
|
17
|
+
- MIMO: ``y_vec`` with shape ``(n_resp, n_exc, n_t)``, ``f_vec`` with shape ``(n_exc, n_t)``
|
|
18
|
+
- MIMO with averaging: ``y_vec`` with shape ``(n_resp, n_exc, n_avg, n_t)``, ``f_vec`` with shape ``(n_exc, n_avg, n_t)``
|
|
18
19
|
|
|
19
20
|
Constraints
|
|
20
21
|
-----------
|
|
@@ -26,25 +27,25 @@ class ExperimentalIRF:
|
|
|
26
27
|
----------
|
|
27
28
|
:param t_vec: Time vector of time series ``y_vec`` and ``f_vec``.
|
|
28
29
|
:type t_vec: ndarray
|
|
29
|
-
:param y_vec: Time series of system responses.
|
|
30
|
+
:param y_vec: Time series of the system responses.
|
|
30
31
|
:type y_vec: ndarray
|
|
31
|
-
:param f_vec: Time series of applied forces.
|
|
32
|
+
:param f_vec: Time series of the applied forces.
|
|
32
33
|
:type f_vec: ndarray
|
|
33
34
|
:param H: Calculated IRF matrix.
|
|
34
35
|
:type H: ndarray
|
|
35
|
-
:param t_vec_IRF: Time vector for calculated IRFs.
|
|
36
|
+
:param t_vec_IRF: Time vector for the calculated IRFs.
|
|
36
37
|
:type t_vec_IRF: ndarray
|
|
37
38
|
|
|
38
39
|
"""
|
|
39
40
|
|
|
40
41
|
# Declare parameters as attributes
|
|
41
42
|
t_vec = np.empty(0)
|
|
42
|
-
y_vec = np.empty((0, 0, 0))
|
|
43
|
+
y_vec = np.empty((0, 0, 0, 0))
|
|
43
44
|
f_vec = np.empty((0, 0, 0))
|
|
44
45
|
H = np.empty((0, 0, 0))
|
|
45
46
|
t_vec_IRF = np.empty(0)
|
|
46
47
|
|
|
47
|
-
def __init__(self,
|
|
48
|
+
def __init__(self, y_vec=np.empty((0, 0, 0, 0)), f_vec=np.empty((0, 0, 0)), t_vec=np.empty((0))):
|
|
48
49
|
# Initialize ExperimentalIRF class with provided data
|
|
49
50
|
if t_vec.size != 0:
|
|
50
51
|
self.t_vec = convert_to_1d_array(t_vec)
|
|
@@ -52,24 +53,6 @@ class ExperimentalIRF:
|
|
|
52
53
|
if y_vec.size != 0 or f_vec.size != 0:
|
|
53
54
|
self.add_time_series(y_vec, f_vec, t_vec=self.t_vec)
|
|
54
55
|
|
|
55
|
-
# Convert any array passed to ExperimentalIRF into a 3D array for concise internal storage.
|
|
56
|
-
def _convert_to_3d_array(self, array):
|
|
57
|
-
# Input convention:
|
|
58
|
-
# 3D: Multiple dofs, multiple measurements (dof,number_of_measurements,points)
|
|
59
|
-
# 2D: Single dof, multiple measurements (number_of_measurements,points)
|
|
60
|
-
# 1D: Single dof, one measurement (points)
|
|
61
|
-
|
|
62
|
-
if array.ndim == 1:
|
|
63
|
-
array = array[np.newaxis, np.newaxis, :]
|
|
64
|
-
elif array.ndim == 2:
|
|
65
|
-
array = array[np.newaxis, :, :]
|
|
66
|
-
elif array.ndim == 3:
|
|
67
|
-
pass
|
|
68
|
-
else:
|
|
69
|
-
raise ValueError(f"Expected 1D, 2D, or 3D array. Got {array.ndim}D.")
|
|
70
|
-
|
|
71
|
-
return array
|
|
72
|
-
|
|
73
56
|
def __str__(self):
|
|
74
57
|
# Prints a formatted object summary of the ExperimentalIRF object
|
|
75
58
|
def print_array(arr):
|
|
@@ -100,9 +83,10 @@ class ExperimentalIRF:
|
|
|
100
83
|
|
|
101
84
|
Shape of time series arrays
|
|
102
85
|
---------------------------
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
-
|
|
86
|
+
- SISO: ``y_vec`` with shape ``(n_t)``, ``f_vec`` with shape ``(n_t)``
|
|
87
|
+
- SISO with averaging: ``y_vec`` with shape ``(n_avg,n_t)``, ``f_vec`` with shape ``(n_avg,n_t)``
|
|
88
|
+
- MIMO: ``y_vec`` with shape ``(n_resp, n_exc, n_t)``, ``f_vec`` with shape ``(n_exc, n_t)``
|
|
89
|
+
- MIMO with averaging: ``y_vec`` with shape ``(n_resp, n_exc, n_avg, n_t)``, ``f_vec`` with shape ``(n_exc, n_avg, n_t)``
|
|
106
90
|
|
|
107
91
|
Constraints
|
|
108
92
|
-----------
|
|
@@ -114,17 +98,30 @@ class ExperimentalIRF:
|
|
|
114
98
|
----------
|
|
115
99
|
:param t_vec: Time vector of time series ``y_vec`` and ``f_vec``.
|
|
116
100
|
:type t_vec: ndarray
|
|
117
|
-
:param y_vec: Time series of system responses.
|
|
101
|
+
:param y_vec: Time series of the system responses.
|
|
118
102
|
:type y_vec: ndarray
|
|
119
|
-
:param f_vec: Time series of applied forces.
|
|
103
|
+
:param f_vec: Time series of the applied forces.
|
|
120
104
|
:type f_vec: ndarray, optional
|
|
121
105
|
|
|
122
106
|
"""
|
|
123
107
|
# Shape input data
|
|
124
108
|
if t_vec is not None:
|
|
125
109
|
t_vec = convert_to_1d_array(t_vec)
|
|
126
|
-
|
|
127
|
-
|
|
110
|
+
|
|
111
|
+
# Detect input data mode
|
|
112
|
+
if y_vec.ndim == 1 and f_vec.ndim == 1: # SISO
|
|
113
|
+
f_vec = f_vec[np.newaxis, np.newaxis, :]
|
|
114
|
+
y_vec = y_vec[np.newaxis, np.newaxis, np.newaxis, :]
|
|
115
|
+
elif y_vec.ndim == 2 and f_vec.ndim == 2: # SISO with averaging
|
|
116
|
+
f_vec = f_vec[np.newaxis, :]
|
|
117
|
+
y_vec = y_vec[np.newaxis, np.newaxis, :, :]
|
|
118
|
+
elif y_vec.ndim == 3 and f_vec.ndim == 2: # SISO with averaging
|
|
119
|
+
f_vec = f_vec[:, np.newaxis, :]
|
|
120
|
+
y_vec = y_vec[:, :, np.newaxis, :]
|
|
121
|
+
elif y_vec.ndim == 4 and f_vec.ndim == 3: # SISO with averaging
|
|
122
|
+
pass
|
|
123
|
+
else:
|
|
124
|
+
raise Exception("Shape of provided time series for y_vec and f_vec does not match a supported format.")
|
|
128
125
|
|
|
129
126
|
# Input check - Time Vector
|
|
130
127
|
if self.t_vec.size != 0 and t_vec is not None:
|
|
@@ -135,15 +132,21 @@ class ExperimentalIRF:
|
|
|
135
132
|
raise Exception("No t_vec provided for data.")
|
|
136
133
|
self.t_vec = t_vec
|
|
137
134
|
|
|
138
|
-
# Input
|
|
135
|
+
# Input Check - Number of time samples
|
|
139
136
|
if y_vec.shape[-1] != len(self.t_vec):
|
|
140
137
|
raise Exception("Provided y_vec does not match length of stored t_vec.")
|
|
141
138
|
if f_vec.shape[-1] != len(self.t_vec):
|
|
142
139
|
raise Exception("Provided f_vec does not match length of stored t_vec.")
|
|
143
140
|
|
|
141
|
+
# Input Check - Match of n_exc, and n_avg dimensions
|
|
142
|
+
if y_vec.shape[1] != f_vec.shape[0]: # Mismatch of n_exc axis
|
|
143
|
+
raise Exception("Number of excitation dofs in y_vec and f_vec does not match.")
|
|
144
|
+
if y_vec.shape[2] != f_vec.shape[1]: # Mismatch of n_avg axis
|
|
145
|
+
raise Exception("Number of averages in y_vec and f_vec does not match.")
|
|
146
|
+
|
|
144
147
|
if self.y_vec.size != 0: # Only y_vec or f_vec must be checked here, since they can only be initialized in pairs.
|
|
145
|
-
y_vec_new = np.append(self.y_vec, y_vec, axis=
|
|
146
|
-
f_vec_new = np.append(self.f_vec, f_vec, axis=
|
|
148
|
+
y_vec_new = np.append(self.y_vec, y_vec, axis=2)
|
|
149
|
+
f_vec_new = np.append(self.f_vec, f_vec, axis=1)
|
|
147
150
|
else:
|
|
148
151
|
y_vec_new = y_vec
|
|
149
152
|
f_vec_new = f_vec
|
|
@@ -164,32 +167,34 @@ class ExperimentalIRF:
|
|
|
164
167
|
:type trigger_level: float
|
|
165
168
|
|
|
166
169
|
"""
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
+
n_resp_dof = self.y_vec.shape[0] # Response dofs
|
|
171
|
+
n_exc_dof = self.y_vec.shape[1] # Excitation dofs
|
|
172
|
+
n_avg = self.y_vec.shape[2]
|
|
173
|
+
t_trigg_idx = np.zeros((n_exc_dof, n_avg), dtype=int)
|
|
174
|
+
t_vec_len_old = len(self.t_vec)
|
|
170
175
|
|
|
171
176
|
# Get trigger index for each provided force time series
|
|
172
|
-
for
|
|
173
|
-
|
|
174
|
-
t_trigg_idx[run]
|
|
177
|
+
for exc_dof in range(0, n_exc_dof):
|
|
178
|
+
for run in range(0, n_avg):
|
|
179
|
+
t_trigg_idx[exc_dof, run] = get_trigger_index(self.f_vec[exc_dof, run], trigger_level)
|
|
175
180
|
|
|
176
181
|
# Construct trimmed time vector
|
|
177
182
|
self.t_vec = self.t_vec[np.max(t_trigg_idx) :] - self.t_vec[np.max(t_trigg_idx)]
|
|
178
|
-
|
|
183
|
+
t_vec_len_new = len(self.t_vec)
|
|
179
184
|
|
|
180
185
|
# Trim force and response time series
|
|
181
|
-
y_vec_trimmed = np.zeros([
|
|
182
|
-
f_vec_trimmed = np.zeros([
|
|
183
|
-
|
|
184
|
-
for run in range(0, n_run):
|
|
185
|
-
idx = t_trigg_idx[run]
|
|
186
|
-
f_vec_trimmed[0, run] = self.f_vec[0, run, idx : idx + new_len]
|
|
186
|
+
y_vec_trimmed = np.zeros([n_resp_dof, n_exc_dof, n_avg, t_vec_len_new])
|
|
187
|
+
f_vec_trimmed = np.zeros([n_exc_dof, n_avg, t_vec_len_new])
|
|
187
188
|
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
for exc_dof in range(0, n_exc_dof):
|
|
190
|
+
for run in range(0, n_avg):
|
|
191
|
+
idx = t_trigg_idx[exc_dof, run]
|
|
192
|
+
f_vec_trimmed[exc_dof, run] = self.f_vec[exc_dof, run, idx : idx + t_vec_len_new]
|
|
193
|
+
y_vec_trimmed[:, exc_dof, run] = self.y_vec[:, exc_dof, run, idx : idx + t_vec_len_new]
|
|
190
194
|
|
|
191
195
|
self.y_vec = y_vec_trimmed
|
|
192
196
|
self.f_vec = f_vec_trimmed
|
|
197
|
+
print(f"[OpenIRF]: Time data retriggered. Length of t_vec {t_vec_len_old} -> {t_vec_len_new}.")
|
|
193
198
|
|
|
194
199
|
def calculate_IRF(self, t_len, extract_impulse=True, resp_dofs=None, exci_dofs=None, deconvolve_type="truncated_convolution", averaged_runs="all"):
|
|
195
200
|
"""
|
|
@@ -224,53 +229,62 @@ class ExperimentalIRF:
|
|
|
224
229
|
|
|
225
230
|
"""
|
|
226
231
|
|
|
232
|
+
n_resp_dof = self.y_vec.shape[0] # Response dofs
|
|
233
|
+
n_exc_dof = self.y_vec.shape[1] # Excitation dofs
|
|
234
|
+
|
|
227
235
|
# Selection of runs to average
|
|
228
236
|
if np.all(averaged_runs == "all"):
|
|
229
237
|
f_vec = self.f_vec
|
|
230
238
|
y_vec = self.y_vec
|
|
231
239
|
else:
|
|
232
240
|
f_vec = self.f_vec[:, averaged_runs]
|
|
233
|
-
y_vec = self.y_vec[:, averaged_runs]
|
|
241
|
+
y_vec = self.y_vec[:, :, averaged_runs]
|
|
242
|
+
|
|
243
|
+
n_avg = y_vec.shape[2] # Number of averages considering the user selection
|
|
234
244
|
|
|
245
|
+
# Determin index for requested IRF length
|
|
235
246
|
h_len = np.argmin(np.abs(self.t_vec - t_len))
|
|
236
247
|
|
|
237
|
-
|
|
248
|
+
# Trim responses to requested length
|
|
249
|
+
y_vec_trimmed = y_vec[:, :, :, 0:h_len]
|
|
238
250
|
|
|
239
|
-
|
|
251
|
+
# Preallocate final IRF matrix
|
|
252
|
+
H = np.zeros([n_resp_dof, n_exc_dof, h_len])
|
|
240
253
|
|
|
241
|
-
#
|
|
242
|
-
|
|
243
|
-
if extract_impulse:
|
|
244
|
-
f_vec_trimmed = extract_impulse_time_series(f_vec[:, idx], self.t_vec)
|
|
245
|
-
else:
|
|
246
|
-
f_vec_trimmed = f_vec[:, idx]
|
|
254
|
+
for exc_dof in range(0, n_exc_dof): # Loop over the different force excitation dofs
|
|
255
|
+
F_exp_list = []
|
|
247
256
|
|
|
248
|
-
#
|
|
249
|
-
|
|
257
|
+
# Build force convolution matrices
|
|
258
|
+
for run in tqdm(range(0, n_avg), desc=f"[OpenIRF]: Building Force Convolution Matrices for excitation dof ({exc_dof + 1}/{n_exc_dof})"):
|
|
259
|
+
if extract_impulse:
|
|
260
|
+
f_vec_trimmed = extract_impulse_time_series(f_vec[exc_dof, run], self.t_vec)
|
|
261
|
+
else:
|
|
262
|
+
f_vec_trimmed = f_vec[exc_dof, run]
|
|
250
263
|
|
|
251
|
-
|
|
252
|
-
|
|
264
|
+
# Trim to requested IRF length
|
|
265
|
+
f_vec_trimmed = f_vec_trimmed[0:h_len]
|
|
253
266
|
|
|
254
|
-
|
|
267
|
+
# Build force convolution matrix
|
|
268
|
+
F_exp_run = build_convolution_matrix(f_vec_trimmed)
|
|
255
269
|
|
|
256
|
-
|
|
257
|
-
F_exp = np.vstack(F_exp_list)
|
|
258
|
-
R = F_exp.transpose() @ F_exp
|
|
259
|
-
R_inv = np.linalg.inv(R)
|
|
270
|
+
F_exp_list.append(F_exp_run)
|
|
260
271
|
|
|
261
|
-
|
|
262
|
-
|
|
272
|
+
# Build and invert auto-correlation matrix
|
|
273
|
+
F_exp = np.vstack(F_exp_list)
|
|
274
|
+
R = F_exp.transpose() @ F_exp
|
|
275
|
+
R_inv = np.linalg.inv(R)
|
|
263
276
|
|
|
264
|
-
|
|
265
|
-
|
|
277
|
+
# Build pseudo-inverse
|
|
278
|
+
F_plus = R_inv @ F_exp.transpose()
|
|
266
279
|
|
|
267
|
-
|
|
280
|
+
# Cleanup temporary variables
|
|
281
|
+
del F_exp_run, F_exp_list, R, R_inv, F_exp
|
|
268
282
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
283
|
+
# Build stacked response vector and calculate IRF
|
|
284
|
+
for resp_dof in tqdm(range(0, n_resp_dof), desc=f"[OpenIRF]: Calculating Experimental IRFs for excitation dof ({exc_dof + 1}/{n_exc_dof})"):
|
|
285
|
+
y_stacked = y_vec_trimmed[resp_dof, exc_dof].reshape(-1)
|
|
286
|
+
H[resp_dof, exc_dof] = F_plus @ y_stacked / self.t_vec[1]
|
|
273
287
|
|
|
274
|
-
# Assign
|
|
288
|
+
# Assign IRF matrix to class instance
|
|
275
289
|
self.H = H
|
|
276
290
|
self.t_vec_IRF = self.t_vec[:h_len]
|
|
Binary file
|
|
@@ -55,7 +55,7 @@ class NumericalIRF:
|
|
|
55
55
|
def __init__(self, M=np.empty((0, 0)), C=np.empty((0, 0)), K=np.empty((0, 0))):
|
|
56
56
|
# Initialize NumericalIRF class with provided data
|
|
57
57
|
if M.size == 0 and K.size != 0:
|
|
58
|
-
raise Exception("No mass matrix M was provided.")
|
|
58
|
+
raise Exception("No mass matrix M was provided.")
|
|
59
59
|
elif K.size == 0 and M.size != 0:
|
|
60
60
|
raise Exception("No stiffness matrix K was provided.")
|
|
61
61
|
elif M.size == 0 and K.size == 0 and C.size != 0:
|