best-linear-approximation 0.1.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.
- best_linear_approximation-0.1.0/LICENSE +21 -0
- best_linear_approximation-0.1.0/PKG-INFO +178 -0
- best_linear_approximation-0.1.0/README.md +162 -0
- best_linear_approximation-0.1.0/pyproject.toml +69 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/__init__.py +43 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_argument_preparation.py +285 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_array_shapes.py +98 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_bla.py +241 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_config.py +5 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_covariance.py +44 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_dataloader.py +359 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_exceptions.py +42 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_frequency_response.py +23 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_linear_algebra.py +110 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_misc.py +37 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_signal_validation.py +111 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_spectra.py +340 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_spectral_validation.py +243 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_typing.py +50 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/_uncertainty.py +140 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/py.typed +0 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/robust/__init__.py +8 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/robust/_direct_methods.py +486 -0
- best_linear_approximation-0.1.0/src/best_linear_approximation/robust/_indirect_methods.py +434 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Merijn Floren
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: best-linear-approximation
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Estimate nonparametric best linear approximations of nonlinear systems
|
|
5
|
+
Author-email: merijn.floren@gmail.com
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: numpy>=2.0
|
|
9
|
+
Requires-Dist: nonlinear-benchmarks ; extra == 'benchmarks'
|
|
10
|
+
Requires-Dist: scipy>=1.17.0 ; extra == 'benchmarks'
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Project-URL: Repository, https://github.com/merijnfloren/best-linear-approximation
|
|
13
|
+
Project-URL: Issues, https://github.com/merijnfloren/best-linear-approximation/issues
|
|
14
|
+
Provides-Extra: benchmarks
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# best-linear-approximation
|
|
18
|
+
|
|
19
|
+
A well-tested Python package for estimating the nonparametric best linear approximation (BLA) and its uncertainty estimates for multivariable nonlinear systems in open- and closed-loop settings.
|
|
20
|
+
|
|
21
|
+
The implemented definitions follow *[System Identification: A Frequency Domain Approach, Second Edition][pintelon-schoukens]* by Rik Pintelon and Johan Schoukens, particularly the robust methods in Section 4.3.1.
|
|
22
|
+
|
|
23
|
+
## Basic usage
|
|
24
|
+
|
|
25
|
+
The four available BLA estimation methods correspond to different experimental conditions.
|
|
26
|
+
They estimate the equivalent nonlinear system from input $u$ to output $y$ under periodic multisine excitation.
|
|
27
|
+
The diagrams below show the input-output signals and measurement-noise sources $v_u$ and $v_y$; see each method's docstring for its required arguments.
|
|
28
|
+
|
|
29
|
+
### Known input
|
|
30
|
+
|
|
31
|
+
Use this method when $u$ is known exactly.
|
|
32
|
+
The BLA then captures all dynamics between $u$ and $y$, including actuator dynamics, delays, zero-order-hold effects, etc.
|
|
33
|
+
Including this behavior is often desirable for control applications.
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src="docs/known_input.drawio.svg" alt="Known-input measurement setup" width="514">
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
**Function:** `best_linear_approximation.robust.known_input(...)`
|
|
40
|
+
|
|
41
|
+
### Noisy input
|
|
42
|
+
|
|
43
|
+
To identify only the system dynamics, use a measurement of the signal entering the system as $u$.
|
|
44
|
+
Since $u$ is then a noise-corrupted measurement of the true system input, the BLA estimate will be biased.
|
|
45
|
+
The bias may be acceptable when the input measurements are sufficiently clean, possibly after averaging over repeated periods.
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<img src="docs/noisy_input.drawio.svg" alt="Noisy-input measurement setup" width="569">
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
**Function:** `best_linear_approximation.robust.noisy_input(...)`
|
|
52
|
+
|
|
53
|
+
### Known reference
|
|
54
|
+
|
|
55
|
+
As in the noisy-input case, use a measurement of the signal entering the system as $u$, but now also use a clean reference $r$.
|
|
56
|
+
Treating $r$ as an instrumental variable reduces the effect of input measurement noise on the BLA estimate and allows actuator-induced nonlinear distortion at the system input to be quantified.
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="docs/known_reference.drawio.svg" alt="Known-reference measurement setup" width="572">
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
**Function:** `best_linear_approximation.robust.known_reference(...)`
|
|
63
|
+
|
|
64
|
+
### Closed loop
|
|
65
|
+
|
|
66
|
+
Closed-loop estimation uses the same instrumental-variable principle as the known-reference method.
|
|
67
|
+
Using a clean reference avoids the bias that generally arises when applying an open-loop method to closed-loop data.
|
|
68
|
+
This reference can be the output reference $r_1$ or an additive input reference $r_2$.
|
|
69
|
+
It must have the same number of channels as $u$: this is guaranteed for $r_2$, but must be verified for $r_1$ in multivariable settings.
|
|
70
|
+
|
|
71
|
+
The diagram below does not show an actuator.
|
|
72
|
+
Depending on the desired model scope, it can be placed between $r_2$ and $u$ to exclude its dynamics from the BLA, or between $u$ and the system to include them.
|
|
73
|
+
|
|
74
|
+
<p align="center">
|
|
75
|
+
<img src="docs/closed_loop.drawio.svg" alt="Closed-loop measurement setup" width="701">
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
**Function:** `best_linear_approximation.robust.closed_loop(...)`
|
|
79
|
+
|
|
80
|
+
## Result object
|
|
81
|
+
|
|
82
|
+
The above estimation methods return a `NonparametricBLA` object:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
NonparametricBLA
|
|
86
|
+
├── G: FrequencyResponse
|
|
87
|
+
│ ├── value
|
|
88
|
+
│ └── noise, nonlinear, total: Uncertainty
|
|
89
|
+
├── spectra: Spectra
|
|
90
|
+
│ ├── U: InputSpectrum
|
|
91
|
+
│ │ ├── value
|
|
92
|
+
│ │ └── noise, nonlinear, total: Uncertainty
|
|
93
|
+
│ ├── Y: OutputSpectrum
|
|
94
|
+
│ │ ├── value
|
|
95
|
+
│ │ └── noise, nonlinear, total, total_equation_error: Uncertainty
|
|
96
|
+
│ └── R: InputSpectrum | None
|
|
97
|
+
│ └── value
|
|
98
|
+
├── freq: FrequencyInfo
|
|
99
|
+
└── experiment: ExperimentInfo
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Each available uncertainty field is an `Uncertainty` object:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
Uncertainty
|
|
106
|
+
├── cov: ComplexArray | None (n_bins, n_channels, n_channels), joint covariance
|
|
107
|
+
├── var: RealArray | None (n_bins, *marginal_shape), marginal variance
|
|
108
|
+
├── std: RealArray | None (n_bins, *marginal_shape), marginal standard deviation
|
|
109
|
+
├── as_percentage: RealArray | None uncertainty RMS relative to "value" RMS, in %
|
|
110
|
+
└── as_power_ratio_db: RealArray | None "value" RMS relative to uncertainty RMS, in dB
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Here, `marginal_shape` is the shape of the estimated quantity at a single frequency bin, and `n_channels` is the product of its dimensions.
|
|
114
|
+
For example, a frequency response has `marginal_shape = (ny, nu)` and `n_channels = ny * nu`.
|
|
115
|
+
|
|
116
|
+
Input and output spectra and their noise uncertainties are returned at every frequency bin.
|
|
117
|
+
All other values and uncertainties are returned only at excited frequency bins.
|
|
118
|
+
When an uncertainty cannot be estimated from the available measurements, its properties are `None`.
|
|
119
|
+
|
|
120
|
+
`as_percentage` and `as_power_ratio_db` reduce the frequency axis, yielding useful summary statistics.
|
|
121
|
+
For example, `bla_estimate.spectra.Y.noise.as_power_ratio_db` gives the signal-to-noise ratio for each output channel.
|
|
122
|
+
The corresponding `as_percentage` gives an a priori, noise-imposed lower bound on the achievable simulation error of a nonlinear parametric model under the measured operating condition.
|
|
123
|
+
|
|
124
|
+
## Benchmark datasets
|
|
125
|
+
|
|
126
|
+
For convenient access to selected benchmark datasets from [nonlinearbenchmark.org](https://www.nonlinearbenchmark.org/), the package provides `best_linear_approximation.dataloader`, which loads and prepares multisine data in the format required by the BLA estimators.
|
|
127
|
+
|
|
128
|
+
The following benchmarks are included:
|
|
129
|
+
|
|
130
|
+
- F-16 aircraft; `load_f16()`
|
|
131
|
+
- Fine Steering Mirror; `load_fine_steering_mirror()`
|
|
132
|
+
- Parallel Wiener-Hammerstein; `load_parallel_wiener_hammerstein()`
|
|
133
|
+
- Silverbox; `load_silverbox()`
|
|
134
|
+
|
|
135
|
+
## Example
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import best_linear_approximation as bla
|
|
139
|
+
|
|
140
|
+
data = bla.dataloader.load_fine_steering_mirror()["train 300mV"]
|
|
141
|
+
|
|
142
|
+
bla_estimate = bla.robust.noisy_input(data.u, data.y, data.fs)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The above call automatically detects the excited frequency bins from `data.u`.
|
|
146
|
+
Alternatively, if the bins are known, they can be passed as the fourth argument to `noisy_input(...)`.
|
|
147
|
+
|
|
148
|
+
Additional examples and visualizations of nonlinear benchmark systems are available in [`examples/`](examples/).
|
|
149
|
+
|
|
150
|
+
## Installation
|
|
151
|
+
|
|
152
|
+
Requires Python 3.12 or later.
|
|
153
|
+
The only runtime dependency is NumPy (2.0 or later).
|
|
154
|
+
|
|
155
|
+
Install with `pip`:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
pip install best-linear-approximation
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Or add it to a `uv` project:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
uv add best-linear-approximation
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
If you wish to use the benchmark dataloader, replace `best-linear-approximation` in either command with `"best-linear-approximation[benchmarks]"`.
|
|
168
|
+
This installs the additional required dependencies.
|
|
169
|
+
Calling a benchmark loader will download its data to the local cache when it is not already available.
|
|
170
|
+
|
|
171
|
+
## Related packages
|
|
172
|
+
|
|
173
|
+
Looking for:
|
|
174
|
+
|
|
175
|
+
- multisine excitation signals? See [multisine](https://github.com/merijnfloren/multisine).
|
|
176
|
+
- parametric state-space models, linear or nonlinear? See [freq-statespace](https://github.com/merijnfloren/freq-statespace).
|
|
177
|
+
|
|
178
|
+
[pintelon-schoukens]: https://doi.org/10.1002/9781118287422
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# best-linear-approximation
|
|
2
|
+
|
|
3
|
+
A well-tested Python package for estimating the nonparametric best linear approximation (BLA) and its uncertainty estimates for multivariable nonlinear systems in open- and closed-loop settings.
|
|
4
|
+
|
|
5
|
+
The implemented definitions follow *[System Identification: A Frequency Domain Approach, Second Edition][pintelon-schoukens]* by Rik Pintelon and Johan Schoukens, particularly the robust methods in Section 4.3.1.
|
|
6
|
+
|
|
7
|
+
## Basic usage
|
|
8
|
+
|
|
9
|
+
The four available BLA estimation methods correspond to different experimental conditions.
|
|
10
|
+
They estimate the equivalent nonlinear system from input $u$ to output $y$ under periodic multisine excitation.
|
|
11
|
+
The diagrams below show the input-output signals and measurement-noise sources $v_u$ and $v_y$; see each method's docstring for its required arguments.
|
|
12
|
+
|
|
13
|
+
### Known input
|
|
14
|
+
|
|
15
|
+
Use this method when $u$ is known exactly.
|
|
16
|
+
The BLA then captures all dynamics between $u$ and $y$, including actuator dynamics, delays, zero-order-hold effects, etc.
|
|
17
|
+
Including this behavior is often desirable for control applications.
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="docs/known_input.drawio.svg" alt="Known-input measurement setup" width="514">
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
**Function:** `best_linear_approximation.robust.known_input(...)`
|
|
24
|
+
|
|
25
|
+
### Noisy input
|
|
26
|
+
|
|
27
|
+
To identify only the system dynamics, use a measurement of the signal entering the system as $u$.
|
|
28
|
+
Since $u$ is then a noise-corrupted measurement of the true system input, the BLA estimate will be biased.
|
|
29
|
+
The bias may be acceptable when the input measurements are sufficiently clean, possibly after averaging over repeated periods.
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="docs/noisy_input.drawio.svg" alt="Noisy-input measurement setup" width="569">
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
**Function:** `best_linear_approximation.robust.noisy_input(...)`
|
|
36
|
+
|
|
37
|
+
### Known reference
|
|
38
|
+
|
|
39
|
+
As in the noisy-input case, use a measurement of the signal entering the system as $u$, but now also use a clean reference $r$.
|
|
40
|
+
Treating $r$ as an instrumental variable reduces the effect of input measurement noise on the BLA estimate and allows actuator-induced nonlinear distortion at the system input to be quantified.
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<img src="docs/known_reference.drawio.svg" alt="Known-reference measurement setup" width="572">
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
**Function:** `best_linear_approximation.robust.known_reference(...)`
|
|
47
|
+
|
|
48
|
+
### Closed loop
|
|
49
|
+
|
|
50
|
+
Closed-loop estimation uses the same instrumental-variable principle as the known-reference method.
|
|
51
|
+
Using a clean reference avoids the bias that generally arises when applying an open-loop method to closed-loop data.
|
|
52
|
+
This reference can be the output reference $r_1$ or an additive input reference $r_2$.
|
|
53
|
+
It must have the same number of channels as $u$: this is guaranteed for $r_2$, but must be verified for $r_1$ in multivariable settings.
|
|
54
|
+
|
|
55
|
+
The diagram below does not show an actuator.
|
|
56
|
+
Depending on the desired model scope, it can be placed between $r_2$ and $u$ to exclude its dynamics from the BLA, or between $u$ and the system to include them.
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="docs/closed_loop.drawio.svg" alt="Closed-loop measurement setup" width="701">
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
**Function:** `best_linear_approximation.robust.closed_loop(...)`
|
|
63
|
+
|
|
64
|
+
## Result object
|
|
65
|
+
|
|
66
|
+
The above estimation methods return a `NonparametricBLA` object:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
NonparametricBLA
|
|
70
|
+
├── G: FrequencyResponse
|
|
71
|
+
│ ├── value
|
|
72
|
+
│ └── noise, nonlinear, total: Uncertainty
|
|
73
|
+
├── spectra: Spectra
|
|
74
|
+
│ ├── U: InputSpectrum
|
|
75
|
+
│ │ ├── value
|
|
76
|
+
│ │ └── noise, nonlinear, total: Uncertainty
|
|
77
|
+
│ ├── Y: OutputSpectrum
|
|
78
|
+
│ │ ├── value
|
|
79
|
+
│ │ └── noise, nonlinear, total, total_equation_error: Uncertainty
|
|
80
|
+
│ └── R: InputSpectrum | None
|
|
81
|
+
│ └── value
|
|
82
|
+
├── freq: FrequencyInfo
|
|
83
|
+
└── experiment: ExperimentInfo
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Each available uncertainty field is an `Uncertainty` object:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
Uncertainty
|
|
90
|
+
├── cov: ComplexArray | None (n_bins, n_channels, n_channels), joint covariance
|
|
91
|
+
├── var: RealArray | None (n_bins, *marginal_shape), marginal variance
|
|
92
|
+
├── std: RealArray | None (n_bins, *marginal_shape), marginal standard deviation
|
|
93
|
+
├── as_percentage: RealArray | None uncertainty RMS relative to "value" RMS, in %
|
|
94
|
+
└── as_power_ratio_db: RealArray | None "value" RMS relative to uncertainty RMS, in dB
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Here, `marginal_shape` is the shape of the estimated quantity at a single frequency bin, and `n_channels` is the product of its dimensions.
|
|
98
|
+
For example, a frequency response has `marginal_shape = (ny, nu)` and `n_channels = ny * nu`.
|
|
99
|
+
|
|
100
|
+
Input and output spectra and their noise uncertainties are returned at every frequency bin.
|
|
101
|
+
All other values and uncertainties are returned only at excited frequency bins.
|
|
102
|
+
When an uncertainty cannot be estimated from the available measurements, its properties are `None`.
|
|
103
|
+
|
|
104
|
+
`as_percentage` and `as_power_ratio_db` reduce the frequency axis, yielding useful summary statistics.
|
|
105
|
+
For example, `bla_estimate.spectra.Y.noise.as_power_ratio_db` gives the signal-to-noise ratio for each output channel.
|
|
106
|
+
The corresponding `as_percentage` gives an a priori, noise-imposed lower bound on the achievable simulation error of a nonlinear parametric model under the measured operating condition.
|
|
107
|
+
|
|
108
|
+
## Benchmark datasets
|
|
109
|
+
|
|
110
|
+
For convenient access to selected benchmark datasets from [nonlinearbenchmark.org](https://www.nonlinearbenchmark.org/), the package provides `best_linear_approximation.dataloader`, which loads and prepares multisine data in the format required by the BLA estimators.
|
|
111
|
+
|
|
112
|
+
The following benchmarks are included:
|
|
113
|
+
|
|
114
|
+
- F-16 aircraft; `load_f16()`
|
|
115
|
+
- Fine Steering Mirror; `load_fine_steering_mirror()`
|
|
116
|
+
- Parallel Wiener-Hammerstein; `load_parallel_wiener_hammerstein()`
|
|
117
|
+
- Silverbox; `load_silverbox()`
|
|
118
|
+
|
|
119
|
+
## Example
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import best_linear_approximation as bla
|
|
123
|
+
|
|
124
|
+
data = bla.dataloader.load_fine_steering_mirror()["train 300mV"]
|
|
125
|
+
|
|
126
|
+
bla_estimate = bla.robust.noisy_input(data.u, data.y, data.fs)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The above call automatically detects the excited frequency bins from `data.u`.
|
|
130
|
+
Alternatively, if the bins are known, they can be passed as the fourth argument to `noisy_input(...)`.
|
|
131
|
+
|
|
132
|
+
Additional examples and visualizations of nonlinear benchmark systems are available in [`examples/`](examples/).
|
|
133
|
+
|
|
134
|
+
## Installation
|
|
135
|
+
|
|
136
|
+
Requires Python 3.12 or later.
|
|
137
|
+
The only runtime dependency is NumPy (2.0 or later).
|
|
138
|
+
|
|
139
|
+
Install with `pip`:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pip install best-linear-approximation
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Or add it to a `uv` project:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv add best-linear-approximation
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
If you wish to use the benchmark dataloader, replace `best-linear-approximation` in either command with `"best-linear-approximation[benchmarks]"`.
|
|
152
|
+
This installs the additional required dependencies.
|
|
153
|
+
Calling a benchmark loader will download its data to the local cache when it is not already available.
|
|
154
|
+
|
|
155
|
+
## Related packages
|
|
156
|
+
|
|
157
|
+
Looking for:
|
|
158
|
+
|
|
159
|
+
- multisine excitation signals? See [multisine](https://github.com/merijnfloren/multisine).
|
|
160
|
+
- parametric state-space models, linear or nonlinear? See [freq-statespace](https://github.com/merijnfloren/freq-statespace).
|
|
161
|
+
|
|
162
|
+
[pintelon-schoukens]: https://doi.org/10.1002/9781118287422
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.10.4,<0.11.0"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[dependency-groups]
|
|
6
|
+
dev = [
|
|
7
|
+
"ipykernel>=7.4.0",
|
|
8
|
+
"matplotlib>=3.11.1",
|
|
9
|
+
"multisine>=0.1.1",
|
|
10
|
+
"nonlinear-benchmarks",
|
|
11
|
+
"pytest>=9.1.1",
|
|
12
|
+
"ruff>=0.16.3",
|
|
13
|
+
"scipy>=1.17.0",
|
|
14
|
+
"toml-sort>=0.25.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project]
|
|
18
|
+
name = "best-linear-approximation"
|
|
19
|
+
version = "0.1.0"
|
|
20
|
+
description = "Estimate nonparametric best linear approximations of nonlinear systems"
|
|
21
|
+
readme = "README.md"
|
|
22
|
+
authors = [
|
|
23
|
+
{ email = "merijn.floren@gmail.com" }
|
|
24
|
+
]
|
|
25
|
+
license = "MIT"
|
|
26
|
+
license-files = ["LICENSE"]
|
|
27
|
+
requires-python = ">=3.12"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"numpy>=2.0"
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
benchmarks = [
|
|
34
|
+
"nonlinear-benchmarks",
|
|
35
|
+
"scipy>=1.17.0"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Repository = "https://github.com/merijnfloren/best-linear-approximation"
|
|
40
|
+
Issues = "https://github.com/merijnfloren/best-linear-approximation/issues"
|
|
41
|
+
|
|
42
|
+
[tool.ruff]
|
|
43
|
+
line-length = 100
|
|
44
|
+
|
|
45
|
+
[tool.ruff.lint]
|
|
46
|
+
select = ["ALL"]
|
|
47
|
+
ignore = [
|
|
48
|
+
"CPY001", # missing-copyright-notice
|
|
49
|
+
"D203", # incorrect-blank-line-before-class
|
|
50
|
+
"D213", # multi-line-summary-second-line
|
|
51
|
+
"N803", # invalid-argument-name
|
|
52
|
+
"N806" # non-lowercase-variable-in-function
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint.per-file-ignores]
|
|
56
|
+
"src/best_linear_approximation/_dataloader.py" = [
|
|
57
|
+
"ANN401", # untyped optional dependency
|
|
58
|
+
"PLC0415" # lazy optional-dependency imports
|
|
59
|
+
]
|
|
60
|
+
"tests/**/*.py" = [
|
|
61
|
+
"D100", # undocumented-public-module
|
|
62
|
+
"D103", # undocumented-public-function
|
|
63
|
+
"FBT001", # boolean-type-hint-positional-argument
|
|
64
|
+
"INP001", # implicit-namespace-package
|
|
65
|
+
"PLR0913", # too-many-arguments
|
|
66
|
+
"PLR0917", # too-many-positional-arguments
|
|
67
|
+
"N803", # invalid-argument-name
|
|
68
|
+
"S101" # assert
|
|
69
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Tools for best linear approximation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from best_linear_approximation import _dataloader as dataloader
|
|
6
|
+
from best_linear_approximation import robust
|
|
7
|
+
from best_linear_approximation._bla import (
|
|
8
|
+
EstimationMethod,
|
|
9
|
+
ExperimentInfo,
|
|
10
|
+
FrequencyInfo,
|
|
11
|
+
FrequencyResponse,
|
|
12
|
+
NonparametricBLA,
|
|
13
|
+
)
|
|
14
|
+
from best_linear_approximation._dataloader import (
|
|
15
|
+
load_f16,
|
|
16
|
+
load_fine_steering_mirror,
|
|
17
|
+
load_parallel_wiener_hammerstein,
|
|
18
|
+
load_silverbox,
|
|
19
|
+
)
|
|
20
|
+
from best_linear_approximation._spectra import (
|
|
21
|
+
InputSpectrum,
|
|
22
|
+
OutputSpectrum,
|
|
23
|
+
Spectra,
|
|
24
|
+
)
|
|
25
|
+
from best_linear_approximation._uncertainty import Uncertainty
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"EstimationMethod",
|
|
29
|
+
"ExperimentInfo",
|
|
30
|
+
"FrequencyInfo",
|
|
31
|
+
"FrequencyResponse",
|
|
32
|
+
"InputSpectrum",
|
|
33
|
+
"NonparametricBLA",
|
|
34
|
+
"OutputSpectrum",
|
|
35
|
+
"Spectra",
|
|
36
|
+
"Uncertainty",
|
|
37
|
+
"dataloader",
|
|
38
|
+
"load_f16",
|
|
39
|
+
"load_fine_steering_mirror",
|
|
40
|
+
"load_parallel_wiener_hammerstein",
|
|
41
|
+
"load_silverbox",
|
|
42
|
+
"robust",
|
|
43
|
+
]
|