Examples
For theoretical background, see:
QSignature 1.0 Framework : IEEE ISDFS 2026 :cite:`qsignature2026_isdfs`
Theorems for Environmental Signature : Research Square :cite:`qsignature2026_theorems`
Example 1: Quick Start
import numpy as np
import QSignature
t = np.linspace(0, 10, 1000)
R = 1 - np.exp(-0.3 * t) * np.cos(2 * np.pi * t)
tau_s = QSignature.tau_s(t, R)
tau_u = QSignature.tau_u(t, R)
R_su = tau_s / tau_u
print(f"R_su = {R_su:.4f}")
Output:
R_su = -0.1841
Interpretation: R_su < 0 indicates decaying amplitude (weakly damped regime).
Example 2: Growth vs Decay Detection
import numpy as np
import QSignature
t = np.linspace(0, 10, 1000)
# Decaying signal
R_decay = 1 - np.exp(-0.3 * t) * np.cos(2 * np.pi * t)
# Growing signal
R_grow = 1 - np.exp(0.15 * t) * np.cos(2 * np.pi * t)
R_grow = (R_grow - R_grow.min()) / (R_grow.max() - R_grow.min())
R_su_decay = QSignature.tau_s(t, R_decay) / QSignature.tau_u(t, R_decay)
R_su_grow = QSignature.tau_s(t, R_grow) / QSignature.tau_u(t, R_grow)
print(f"Decay: R_su = {R_su_decay:.4f}")
print(f"Growth: R_su = {R_su_grow:.4f}")
Output:
Decay: R_su = -0.1841
Growth: R_su = +2.0728
Key insight: QSignature clearly distinguishes between decaying and growing amplitude signals.
Example 3: QSpace Classification
import numpy as np
import QSignature
t = np.linspace(0, 20, 2000)
systems = {
'Exponential Decay': 1 - np.exp(-0.5 * t),
'Underdamped': 1 - np.exp(-0.2 * t) * np.cos(3 * t),
'Weakly Damped': 1 - np.exp(-0.05 * t) * np.cos(5 * t),
'Growth': 1 - np.exp(0.1 * t) * np.cos(2 * t),
}
for name, R in systems.items():
if name == 'Growth':
R = (R - R.min()) / (R.max() - R.min())
tau_s = QSignature.tau_s(t, R)
tau_u = QSignature.tau_u(t, R)
R_su = tau_s / tau_u
print(f"{name}: R_su = {R_su:+.4f}")
Output:
Exponential Decay: R_su = +1.0000
Underdamped: R_su = +0.0788
Weakly Damped: R_su = -1.1150
Growth: R_su = +1.2872
Example 4: Noise Reduction with QSmooth
import numpy as np
import QSignature
t = np.linspace(0, 10, 1000)
R_clean = 1 - np.exp(-0.2 * t) * np.cos(6 * t)
np.random.seed(42)
noise = 0.05 * np.random.randn(len(t))
R_noisy = R_clean + noise
qs = QSignature.QSmooth()
R_smooth = qs.savgol(t, R_noisy, window_frac=0.1, polyorder=3)
R_su_clean = QSignature.tau_s(t, R_clean) / QSignature.tau_u(t, R_clean)
R_su_noisy = QSignature.tau_s(t, R_noisy) / QSignature.tau_u(t, R_noisy)
R_su_smooth = QSignature.tau_s(t, R_smooth) / QSignature.tau_u(t, R_smooth)
print(f"Clean: R_su = {R_su_clean:.4f}")
print(f"Noisy: R_su = {R_su_noisy:.4f}")
print(f"Smoothed: R_su = {R_su_smooth:.4f}")
Output:
Clean: R_su = +0.3333
Noisy: R_su = +0.2973
Smoothed: R_su = +0.3241
Conclusion: QSmooth recovers the correct diagnostic from noisy data.
Example 5: Synthetic Data Generation
import QSignature
syn = QSignature.QSynthetic()
t1, R1 = syn.exponential_decay(tau=2.0)
t2, R2 = syn.underdamped_oscillator(alpha=0.2, omega_d=6.0)
t3, R3 = syn.overdamped_system(tau1=0.5, tau2=3.0)
t4, R4 = syn.conservative_oscillator(omega0=2*np.pi, modes=1)
R_su1 = QSignature.tau_s(t1, R1) / QSignature.tau_u(t1, R1)
R_su2 = QSignature.tau_s(t2, R2) / QSignature.tau_u(t2, R2)
R_su3 = QSignature.tau_s(t3, R3) / QSignature.tau_u(t3, R3)
R_su4 = QSignature.tau_s(t4, R4) / QSignature.tau_u(t4, R4)
print(f"Exponential Decay: R_su = {R_su1:+.4f}")
print(f"Underdamped: R_su = {R_su2:+.4f}")
print(f"Overdamped: R_su = {R_su3:+.4f}")
print(f"Conservative: R_su = {R_su4:+.4f}")
Output:
Exponential Decay: R_su = +1.0000
Underdamped: R_su = +0.0011
Overdamped: R_su = +1.0000
Conservative: R_su = -2.0010
All example scripts are available in the examples/ folder of the GitHub repository.