Generated reference › Lomb Scargle Periodogram — Control Systems/Spectral Measurements
kind: generated#block#control-systems-spectral-measurements

Lomb Scargle Periodogram — Control Systems/Spectral Measurements

L-S

Control_Systems/Spectral_Measurements/Lomb_Scargle_Periodogram · 2 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Lomb-Scargle Periodogram

Control Systems / Spectral Measurements

The Lomb-Scargle periodogram of a record sampled at arbitrary times – MATLAB's plomb(x, t, f). The samples arrive on one port and their time stamps on a second, so the sampling need not be uniform and no rate is assumed anywhere. At each frequency the block fits a sinusoid to the mean-removed record by least squares, through the time offset τ that makes its sine and cosine parts orthogonal:

tan(2ωτ) = Σsin(2ωt) ÷ Σcos(2ωt),   ω = 2πf

P(f) = (Σx·cosω(t−τ))² ÷ Σcos²ω(t−τ)  +  (Σx·sinω(t−τ))² ÷ Σsin²ω(t−τ)

The frequencies are this block's own grid, fk = k·Δf for k = 0 … K−1, and P(0) = 0 as plomb sets it.

Ports

  • x – the sample values, an [N,1] column, oldest first. N is read off the wire, from 4 to 128.
  • t – the time stamp of each sample, [N,1], in seconds and in the same order as x. It should be increasing; only the last minus the first is read as the record length, and that is what the Power spectral density type divides by.
  • P – the periodogram, [K,1], bin k at frequency k·Δf hertz, DC first and zero.

Parameters

  • Number of Bins – K, the length of the output and of the frequency grid, a whole number from 2 to 1024. Defaults to 64.
  • Bin Spacing – Δf, the frequency step in hertz, a positive number; the same parameter, under the same name, that Welch PSD and the rest of this family read. Defaults to 0.1. plomb's own default grid is 1÷(4·n·Ts) apart, four times finer than the record supports; choose Δf the same way if you want plomb's resolution.
  • Spectrum Type – how the fitted power is scaled, plomb's three:
    • Power spectral density – the default: divided by the average sampling rate (N−1)÷(tN−t1), so the answer is power per hertz.
    • Normalized – divided by twice the record's variance (the unbiased one, N−1), the classical dimensionless Lomb statistic.
    • Power – divided by N, so a sinusoid of amplitude A answers about A²/4 at its frequency.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. It is the rate the BLOCK runs at, and has nothing to do with the time stamps on the t port.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text, all from one program, so every target does the same arithmetic in the same order as the simulation. The frequency grid is unrolled into the core at export time, one block of statements per bin; the three settings and the frame length are structural, so re-export after changing any of them. The sine is emitted as a shifted cosine and the quadrant of τ is taken with comparisons rather than an atan2, because PLC Structured Text has neither.

The three HDL targets run that program in real arithmetic and quantize only at the two input ports and the output: simulation-only, not offered as synthesizable. The fit divides by sums that depend on the data, and a time stamp of several seconds carried in Q16.16 would lose the phase resolution the estimate is made of.

Simulink bridge

None (Support::None). plomb is a Signal Processing Toolbox function and that toolbox ships no Simulink library; a search of every DSP System Toolbox and Simulink library on R2026a found no Lomb-Scargle or uneven-sampling estimator, so there is no path a diagram could name. The bridge reports this block rather than dropping it silently, and it has no parity testbench; code export verification covers all ten languages.

Notes

  • Algebraic: the output depends on this step's two frames alone.
  • Verified against R2026a: this program agrees with plomb(x, t, f, type) to 1.5e−14 of the largest bin over 300 records of 12 to 32 unevenly spaced samples, for all three types.
  • ⚠ plomb(x, t) with no frequency vector is a different computation: the Press-Rybicki fast approximation on a grid that follows the data. Measured on a 24-sample record, it differs from the exact sum on its own grid by 4.7e−4 per bin. This block is always the exact sum, on the grid the parameters fix.
  • MATLAB refuses a time vector that is not strictly increasing, or that has a negative entry; this block does not check, and answers what the formulas give. Repeated times are legitimate input to the fit; a decreasing vector makes the density type divide by a negative rate.
  • A record with no variation at all – every sample equal – has a zero denominator in the Normalized type and answers infinities; the other two answer zero.

Code facts#

FactValue
registered typeControl_Systems/Spectral_Measurements/Lomb_Scargle_Periodogram
familyControl_Systems/Spectral_Measurements
solver environment classICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Lomb_Scargle_Periodogram
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/Lomb_Scargle_Periodogram/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Lomb_Scargle_Periodogram.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Spectral_Measurements/Lomb_Scargle_Periodogram/ICoreBlock_0_Control_Systems_1_Spectral_Measurements_2_Lomb_Scargle_Periodogram.h
default size on canvas160 × 80 px
ports at insert2 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoublex
2inICoreDoublet
3outICoreDoubleP

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Number of Bins64not crossed
Bin Spacing0.1not crossed
Spectrum TypePower spectral density%~%Normalized%~%Power~~Power spectr…not crossed

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path—
port-count rulePortsParam::None
SampleTime parameteryes
deliberately not crossedNumber of Bins, Bin Spacing, Spectrum Type

Caveat (shown to the user): plomb is a Signal Processing Toolbox function, not a Simulink library block -- that toolbox ships no Simulink library -- and a search of 97 DSP System Toolbox and Simulink libraries (8600 blocks, R2026a) found no Lomb-Scargle or uneven-sampling spectrum block, so there is no path a diagram could name; the block is reported rather than dropped when a model crosses

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 every stimulus in the sample errored — cross-checks skipped

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Lomb-Scargle Periodogram -- MATLAB's plomb(x, t, f, type), the spectrum of unevenly sampled data For each requested frequency f, with the record's mean removed and a time offset tau that makes the sine and cosine parts orthogonal:

tan(2*w*tau) = SUM sin(2*w*t) / SUM cos(2*w*t), w = 2 pi f P(f) = (SUM x cos(w(t-tau)))^2 / SUM cos^2(w(t-tau))

  • (SUM x sin(w(t-tau)))^2 / SUM sin^2(w(t-tau))

Nothing there assumes a sampling rate: the times come in on their own port, so the samples may be as uneven as they like. The grid is this block's own -- f_k = k * Bin Spacing, k = 0 .. K-1 -- which is plomb's EXPLICIT-frequency form, plomb(x, t, f): P is zero at f = 0 by plomb's own rule, and the three spectrum types divide it by the average sampling rate (n-1)/(t_end-t_1), by n, or by twice the record's variance.

⚠ plomb WITHOUT a frequency vector IS NOT THIS: it runs the Press-Rybicki FAST approximation (extirpolation onto a 2^k grid, then two FFTs) on a data-dependent grid f_k = k / (ofac * n * Ts). Measured on R2026a over a 24-sample record: that approximation differs from the exact sum on its OWN grid by 4.7e-4 relative per bin (1.4e-5 of the largest bin), and its grid moves with the data. This block computes the exact sum on a grid the user fixes, so a Simulink-shaped signal path has a fixed output size -- and matches plomb(x, t, f) to 1.5e-14, measured over 300 records and all three types.

⚠ THE SIN IS COS SHIFTED BY pi/2. ICoreStatementProgram spells cos, atan, sqrt and log for all ten targets and not sin, so the program writes sin(a) as cos(a - pi/2) -- exact to a rounding of pi/2 -- and atan2 as atan with the quadrant taken by comparisons, which is also what PLC Structured Text needs, having no ATAN2. MATLAB's own lombscargle uses sinpi/cospi, whose exact argument reduction this cannot reproduce: over wt in [0, 400] the two differ by 1.6e-13.

Support::None: a sweep of 97 Simulink libraries (8600 blocks) found no Lomb, Scargle or uneven-sampling block, and plomb is a Signal Processing Toolbox function, which ships none.

Sample results#

No stimulus produced a sampled output in this rig — Invalid frame length at Lomb-Scargle Periodogram block: ICore Blocks/Home/Lomb Scargle Periodogram. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.

Category unsampled · sample time 0.1 · 60 steps · commit ee1ac01a4e538ed0c5e24de27bed3622cf0687b7 · produced by docsSample --out <folder> --blocks MUSIC_Spectrum Eigenvector_Spectrum Lomb_Scargle_Periodogram --steps 60

Sample data: docs/generated/samples/Control_Systems__Spectral_Measurements__Lomb_Scargle_Periodogram.json