noda
crosspeak.noda
MovingWindowResult
Bases: NamedTuple
Correlation maps from a moving-window 2DCOS analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
sync |
ndarray
|
Synchronous matrices, shape (n_windows, n_wavenumbers, n_wavenumbers). |
asyn |
ndarray
|
Asynchronous matrices, same shape. |
centres |
ndarray
|
Perturbation value at the middle of each window, shape (n_windows,). |
Source code in src/crosspeak/noda.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
AutopeakResult
Bases: NamedTuple
Autopeaks found on a synchronous diagonal.
Attributes:
| Name | Type | Description |
|---|---|---|
positions |
ndarray
|
Wavenumbers at which autopeaks were detected, in the order of the input wavenumber axis. |
intensities |
ndarray
|
Autopower values (diagonal of the synchronous matrix) at those positions. |
Source code in src/crosspeak/noda.py
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
hilbert_noda_matrix(n)
The Hilbert-Noda matrix for n perturbation points.
The discrete kernel that turns the asynchronous calculation into a matrix product: with N in hand, Ψ = Y^T @ N @ Y / (m - 1). Off the diagonal N_jk = 1 / (π(k - j)); the diagonal is zero, since a point has no phase lag against itself.
The sign convention matters. With N positive in the upper triangle, a positive Ψ(ν₁, ν₂) alongside a positive Φ means ν₁ leads ν₂ under Noda's rules. Transpose N and every ordering flips — so if this ever gets swapped out, check the sign against a sequence you already know.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
Number of perturbation points (m in the usual notation), at least 2. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The (n, n) matrix, antisymmetric with a zero diagonal. |
Source code in src/crosspeak/noda.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
synchronous(series)
Synchronous 2DCOS matrix Φ of a spectral series.
Φ(ν₁, ν₂) = Y^T @ Y / (m - 1) over the mean-centred intensities, which is just the sample covariance across the perturbation. Large positive values mean two wavenumbers rise and fall together; negative means they move in opposition. The diagonal is the autopower spectrum — where the perturbation does the most work.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
A |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The (n, n) synchronous matrix, symmetric by construction. |
Source code in src/crosspeak/noda.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
asynchronous(series)
Asynchronous 2DCOS matrix Ψ of a spectral series.
Ψ(ν₁, ν₂) = Y^T @ N @ Y / (m - 1), with N the Hilbert-Noda matrix. Where Φ says which bands move together, Ψ says in what order: read against the sign of Φ, a nonzero Ψ resolves which of two overlapping features responds first. Antisymmetric, with a zero diagonal.
Same mean-centring and conventions as synchronous; see
hilbert_noda_matrix for the sign that fixes the direction of the ordering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
A |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The (n, n) asynchronous matrix. |
Source code in src/crosspeak/noda.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
moving_window(series, *, window_size=5)
Moving-window 2DCOS: correlation over a sliding perturbation window.
Full-range 2DCOS gives one pair of maps summarising the whole series, which hides when things happened — a system that reorganises in two stages produces a single map with both stages blended into it. Moving-window analysis slides a short window along the perturbation axis and correlates within each position, so features can be seen switching on and off as the perturbation advances.
Each window is mean-centred against its own local mean rather than the mean of the whole series. That is what makes the result local.
The window is constant in index, not in perturbation value. For an
unevenly sampled series — water contents of 0, 1, 2, 5, 10, 15, 20, 30, say
— a five-point window spans 0 to 10 at one end and 10 to 30 at the other.
This is the standard formulation, but it means centres should be read
alongside the maps rather than assumed evenly spaced.
Short windows localise sharply but leave few points to correlate, and the asynchronous map degrades first. Windows of 5 to 11 points are usual.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
SpectralSeries
|
A |
required |
window_size
|
int
|
Perturbation points per window. Must be odd, at least 3, and no larger than the series. Default 5. Noda writes this as 2m+1, so 5 is m=2. |
5
|
Returns:
| Type | Description |
|---|---|
MovingWindowResult
|
Named tuple of (sync, asyn, centres), with
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/crosspeak/noda.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
find_autopeaks(phi, wavenumbers, *, prominence_frac=0.02, **kwargs)
Detect autopeaks on the diagonal of a synchronous 2DCOS matrix.
The diagonal of Phi is the autopower spectrum — the variance of each wavenumber across the perturbation series. Local maxima of this spectrum are Noda's autopeaks and identify the wavenumbers that change most strongly under the perturbation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phi
|
ndarray
|
Synchronous 2DCOS matrix, shape (n, n), as returned by |
required |
wavenumbers
|
ndarray
|
Wavenumber axis, shape (n,), strictly monotonic. |
required |
prominence_frac
|
float
|
Minimum peak prominence, as a fraction of the diagonal maximum. Default 0.02. Set to 0 to disable the prominence filter. |
0.02
|
**kwargs
|
Additional keyword arguments passed through to |
{}
|
Returns:
| Type | Description |
|---|---|
AutopeakResult
|
Named tuple of (positions, intensities). Empty arrays if none found. |
Source code in src/crosspeak/noda.py
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | |
synchronous_hetero(series_1, series_2)
Heterospectral synchronous 2DCOS matrix.
Computes Φ(ν₁, ν₂) = Y_1^T @ Y_2 / (m - 1), where Y_1 and Y_2 are the mean-centred intensities of the two series. The two series must share the same perturbation array (rows are paired by index).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series_1
|
SpectralSeries
|
SpectralSeries supplying ν₁ — maps to matrix axis 0 (rows), and to the y-axis when the result is plotted. |
required |
series_2
|
SpectralSeries
|
SpectralSeries supplying ν₂ — maps to matrix axis 1 (cols), and to the x-axis when the result is plotted. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the two series have different perturbation arrays. |
Source code in src/crosspeak/noda.py
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
asynchronous_hetero(series_1, series_2)
Heterospectral asynchronous 2DCOS matrix.
Computes Ψ(ν₁, ν₂) = Y_1^T @ N @ Y_2 / (m - 1), where N is the Hilbert-Noda matrix of shape (m, m).
See synchronous_hetero for axis conventions.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the two series have different perturbation arrays. |
Source code in src/crosspeak/noda.py
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |