Skip to content

Composed ALSSM Windows (Weighting Window) [code104.0]

Each cost segment in lmlib.statespace.cost is weighted by its own exponential window function. This guide script demonstrates the basic exponentially decaying window of both finite and infinite support, and shows how a more complex symmetric window is built by composing four such segments.

The composed window consists of two exponentially decaying tails (left and right) and a near-rectangular centre region, all joined into a single CompositeCost.

See also: window, Window

Plot

Plot

Code

"""
Composed ALSSM Windows (Weighting Window) [code104.0]
===================================================

Each cost segment in [`lmlib.statespace.cost`][lmlib.statespace.cost] is weighted by its own
exponential window function.  This guide script demonstrates the basic
exponentially decaying window of both finite and infinite support, and shows
how a more complex symmetric window is built by composing four such segments.

The composed window consists of two exponentially decaying tails (left and
right) and a near-rectangular centre region, all joined into a single
[`CompositeCost`][lmlib.statespace.cost.CompositeCost].

See also:
[`window`][lmlib.statespace.segment.Segment.window],
[`Window`][lmlib.statespace.window.Window]

"""

import numpy as np
import matplotlib.pyplot as plt
import lmlib as lm

K = 1000  # signal length
ks = 500  # (arbitrary) window location
k = range(K)

segment_left_infinite = lm.Segment(a=-np.inf, b=-40, direction=lm.FORWARD, g=100, delta=-40)  # left decaying window
segment_left_finite = lm.Segment(a=-39, b=-1, direction=lm.FORWARD, g=1e6, delta=0)  # (nearly) rectangular window
segment_right_finite = lm.Segment(a=0, b=39, direction=lm.BACKWARD, g=1e6, delta=0)  # (nearly) rectangular window
segment_right_infinite = lm.Segment(a=40, b=np.inf, direction=lm.BACKWARD, g=100, delta=40)  # right decaying window

cost = lm.CompositeCost((lm.AlssmPoly(3),),
                        [segment_left_infinite, segment_left_finite, segment_right_finite, segment_right_infinite],
                        F=[[1, 1, 1, 1]])

# Generating Windows - for illustrative and plotting purposes only
# ---------------------------------------------------------------

# Minimum window weight below which samples are treated as zero.
# Only relevant for exponentially decaying windows with infinite support,
# which never reach exactly 0.
display_thd = 0.1
# Per-segment windows without thresholding
wins = lm.Window.eval_y(cost, ks, K, merged_seg=False)

# Combined window with thresholding applied (infinite tails clipped at display_thd)
wins_all_no_thd = lm.Window.eval_y(cost, ks, K, merged_seg=True,thd=display_thd)
# Combined window without thresholding (infinite tails shown in full)
wins_all = lm.Window.eval_y(cost, ks, K, merged_seg=True)

# Plot
# ----
plt.figure(figsize=(6, 2))
for p, win in enumerate(wins):
    line = plt.plot(k, win, '-', lw=0.3, label=f'Segment {p}')
    plt.fill_between(k, win, color=line[0].get_color(), alpha=0.3)
plt.plot(k, wins_all, '--k', lw=1.0, label='Overall window \n with threshold')
plt.plot(k, wins_all_no_thd, '-k', lw=1.0, label='Overall window \n without threshold')

plt.axhline(display_thd, lw=0.6, c='k', ls='--', label='')
plt.xlabel('time index $k$')
plt.ylabel('window weight(s)')
plt.title(f'(Composed) window localized at index $k={ks}$')
plt.legend(loc=1, fontsize=8)
plt.show()