Chapters

6 Edge Data: Sampling and Statistical Compression

analytics-ml
edge
acq
sampling

6.1 Overview

This section: Overview — This first route protects signal evidence through sampling and compares lossless, statistical, and transform reduction.

This first route protects signal evidence through sampling and compares lossless, statistical, and transform reduction.

This is part 1 of 2. Continue with Edge Data: Semantic Compression and Pipelines for the second focused route.

6.2 Start With the Story

This section: Start With the Story — Picture a motor whose vibration changes faster than a slow sensor check can see.

Keep the Shape Before Shrinking the Data

Picture a motor whose vibration changes faster than a slow sensor check can see. If the device measures too rarely, no later data trick can rebuild the missing motion.

Sampling means taking readings at chosen times. The sampling rate is how many readings are taken in one second. Start with the fastest change that matters. Measure often enough to show that change before you remove or combine any values.

Compression means using fewer bits to carry useful information. First decide what the receiver must still know. Exact records may need a lossless method, which can rebuild every bit. Trends may allow summaries. Alarms may allow the device to send only a named event plus enough context to check it.

Compare the smaller result with the original. Test normal work, sharp changes, noise, and a lost link. Record the method, settings, time window, and error.

Start with one short raw record. Mark the fastest useful change. Mark the slow trend. Mark known noise. Mark any gap. Choose the rate. Take the sample. Check the shape. Keep the time. Keep the unit. Keep the test state.

Now make a smaller copy. Count its bits. Check its shape. Check its peak. Check its mean. Check its alarm. Rebuild it when the method allows that. Measure the error. Repeat with a sharp event. Repeat with a quiet event. Repeat after a restart.

Test the full field path. Fill the local store. Remove the link. Keep taking samples. Restore the link. Send old data in order. Mark repeats. Mark lost blocks. Check the far copy. Check the power used. Check the time needed.

Write one clear rule for use. State which facts may change. State which facts must not change. State the largest allowed error. State who owns the setting. State what change forces a new test. Keep the raw test set so a later method can be judged on the same evidence.

The simple rule has limits. Less data saves power and link use, but it can also hide faults.

Use Practitioner to choose rates and reduction steps. Use Under the Hood for signal, transform, battery, and error limits.

Choose a sample rate and reduction step by testing whether faults remain visible after data is discarded.

6.3 Learning Objectives

This section: Learning Objectives

By the end of this chapter, you will be able to:

  • Apply Nyquist Theorem: Calculate appropriate sampling rates for different sensor types
  • Implement Data Reduction Techniques: Use aggregation, compression, event-based reporting, and delta encoding
  • Select Compression Algorithms: Choose optimal algorithms based on data type and edge device constraints
  • Avoid Common Pitfalls: Prevent sampling aliasing, buffer overflow, and rate mismatch errors
Quick Check: Edge Sampling & Compression
In 60 Seconds

Adaptive sampling and on-device compression are the two most powerful techniques for reducing IoT data volume at the edge — adaptive sampling matches collection frequency to signal dynamics, while compression exploits redundancy to shrink the data that is transmitted. In the worked examples below, adaptive sampling and on-device compression can reduce bandwidth requirements by 90–99% when the retained features meet the analysis goal.

Edge sampling and compression reduce the amount of data IoT devices need to transmit. Think of sending a friend the highlights of a movie instead of the entire film. By transmitting only important changes or compressed summaries, devices save battery power and network bandwidth while preserving the information that matters most.

6.4 Prerequisites

This section: Prerequisites

Before diving into this chapter, you should be familiar with:

  • Edge Data Acquisition: Architecture: Understanding device categories and data generation patterns
  • Basic signal processing concepts: Familiarity with frequency and time-domain representations
  • Python programming: Code examples use Python for data processing
Edge Data Reduction Basics

Core Concept: Transform raw sensor data into actionable information at the source - send summaries, statistics, and alerts rather than every reading.

Why It Matters: Sending one minute-average instead of 1,000 readings per minute reduces the record count 1,000-fold. Byte and radio-energy savings depend on payload and protocol overhead. An average loses within-minute peaks and timing, so retain other features or raw windows when the application needs them.

Key Takeaway: Apply the 90% rule - if 90% of your data is “normal” readings that will never be analyzed individually, aggregate them locally. Send statistical summaries (min, max, mean, std) at lower frequency, and only transmit raw data when anomalies are detected. This can extend battery life when radio energy dominates; calculate sensing, processing, sleep and transmission energy for the actual device.

6.5 Nyquist Sampling Rate

This section: Nyquist Sampling Rate

Time: ~8 min | Difficulty: Intermediate | Reference: P10.C08.U03

Key Concepts

This section: Key Concepts

  • Adaptive sampling: Dynamically adjusting the sensor sampling rate based on signal variance or event rate — increasing frequency when the signal changes rapidly and decreasing it during quiet periods.
  • Nyquist-Shannon theorem: The fundamental sampling principle stating that a signal must be sampled at least twice its highest frequency component to be reconstructed accurately — the minimum sampling rate for any IoT sensor.
  • Delta encoding: A compression technique transmitting only the change between consecutive readings rather than absolute values, highly effective for slowly varying sensors.
  • Run-length encoding (RLE): Compressing sequences of identical values into a count-value pair — very effective for binary event streams or sensors with frequent identical readings.
  • Lossless compression: Compression that allows perfect reconstruction of the original data — required for financial billing data, safety-critical readings, and regulatory compliance.
  • Lossy compression: Compression that discards some information to achieve higher compression ratios — acceptable for analytics workloads where small accuracy loss is tolerable.

Practitioner Knowledge Check

Chapter Roadmap
  1. First set the sampling rate from the highest frequency that matters, not from the most convenient device rate.
  2. Then reduce edge traffic with aggregation, event reporting, delta encoding, and outage-aware buffering.
  3. Next compare lossless, statistical, FFT, and semantic compression against the evidence the cloud still needs.
  4. Finally test the factory vibration case, choose a strategy, and use the quizzes to check that fidelity, bandwidth, and memory stay aligned.

Checkpoints recap the decision path. Deep-dive and collapsed callouts keep calculations and implementation details available without replacing the main sampling-and-compression flow.

To accurately capture a signal, the sampling rate must be at least twice the highest frequency component of interest:

fsample≥2×fmaxf_{sample} \geq 2 \times f_{max}

Practical examples:

Signal TypeMax FrequencyMin Sample RateTypical Rate
Temperature0.1 Hz (slow changes)0.2 Hz1 sample/second for 0.1 Hz changes; 1 sample/minute only for slower trends below 0.0083 Hz
Vibration500 Hz1 kHz2-5 kHz
Audio20 kHz40 kHz44.1 kHz
Motion (IMU)50 Hz100 Hz100-200 Hz

The mathematical gist. A 1,800 RPM shaft rotates at 30 Hz. For this exercise, suppose a hypothetical source produces eight impulses per shaft revolution: its repetition rate is 240 Hz, with harmonics at 480 Hz and 720 Hz. Strict Nyquist for the third harmonic needs 1,440 Hz, and the chapter’s 2.5× margin needs 3,600 Hz. At 4 kHz and two bytes per sample, raw data is 8,000 B/s; a 120 B/s peak record is a 66.7× reduction without discarding the input’s 16-bit resolution.

Math Bridge · guided foundationsWhy must impulse-signal sampling be settled before compression?Let Data Dora trace shaft speed, illustrative harmonics, Nyquist margin, aliases, and payload reduction.
Common Pitfall: Sampling Aliasing

The mistake: Sampling signals below the Nyquist rate (2x the highest frequency), causing phantom patterns (aliasing) that don’t exist in the original signal.

Symptoms:

  • Vibration analysis shows unexpected low-frequency patterns
  • Motor speed readings fluctuate despite constant RPM
  • Temperature data shows oscillations that don’t match physical reality
  • Frequency analysis reveals false peaks at wrong frequencies
  • Bearing fault detection produces false positives

Why it happens: Engineers apply “common sense” sampling rates without frequency analysis. Underestimating signal bandwidth - a 60 Hz motor generates harmonics at 120 Hz, 180 Hz, etc. Cost pressure drives lower sampling rates. Copy-pasting configurations between different sensor types.

The fix: Always sample at >2x the highest frequency of interest:

Signal TypeMax FrequencyMinimum Sample RateRecommended
Room temperature0.01 Hz0.02 Hz1 sample every 30 seconds for 0.01 Hz changes; 1 sample/minute only for trends below 0.0083 Hz
HVAC response0.1 Hz0.2 Hz1/second
Motor vibration500 Hz1 kHz2.5 kHz
Bearing analysis5 kHz10 kHz25 kHz

Prevention: Perform frequency analysis on representative signals before deployment. Use anti-aliasing filters (low-pass hardware filters) before the ADC. When in doubt, oversample then downsample digitally with proper filtering.

What sampling rate captures an illustrative 240 Hz impulse train on a 1800 RPM motor shaft?

Given:

  • Motor speed: 1800 RPM = 30 Hz (revolutions per second)
  • Illustrative impulse frequency (not a bearing-defect prediction): If a source produces eight impulses per 30 Hz shaft revolution, its repetition rate is 8×30=2408 \times 30 = 240 Hz.
  • Harmonics: 2nd harmonic at 480 Hz, 3rd at 720 Hz
  • Highest illustrated frequency of interest: 3rd harmonic = 720 Hz

Nyquist calculation:

fsample≥2×fmax=2×720 Hz=1440 Hz minimumf_{sample} \geq 2 \times f_{max} = 2 \times 720 \text{ Hz} = 1440 \text{ Hz minimum}

Practical safety factor (2.5× the Nyquist minimum):

fsample=2.5×1440=3600 Hz≈4 kHzf_{sample} = 2.5 \times 1440 = 3600 \text{ Hz} \approx 4 \text{ kHz}

If sampled at only 100 Hz (common mistake):

  • Nyquist frequency = 50 Hz, but the illustrative component is at 240 Hz
  • 240 Hz aliases to ∣240−round(240/100)×100∣=∣240−200∣=40|240 - \text{round}(240/100) \times 100| = |240 - 200| = 40 Hz
  • Result: A false 40 Hz pattern appears instead of the real 240 Hz component
  • Impact: Bearing failure goes undetected until catastrophic failure

Memory and bandwidth check:

  • 4 kHz sampling × 2 bytes per sample = 8 kB/s raw data
  • 1-second FFT windows → 8 kB per analysis
  • Send top 10 frequency peaks → 120 bytes per second (67× reduction)
  • Conclusion: Edge FFT compression mandatory for battery-powered vibration monitoring

6.6 Nyquist Rate Calculator

This section: Nyquist Rate Calculator — Use this calculator to explore how motor speed, harmonic order, and safety factor affect the required sampling rate and resulting data volume.

Use this calculator to explore how motor speed, harmonic order, and safety factor affect the required sampling rate and resulting data volume.

6.7 Interactive: Nyquist Sampling Animation

This section: Interactive: Nyquist Sampling Animation

This section:

Data Dora, Data and analytics domain expertCheckpoint: Sampling Without Aliasing

You now know:

  • Nyquist starts from the highest frequency of interest, so a 60 Hz motor with 4th-harmonic faults needs a 480 Hz minimum sample rate.
  • The illustrative impulse example turns 1800 RPM into 30 Hz, then follows harmonics to 720 Hz before applying the 1440 Hz minimum and practical safety margin.
  • The calculator and animation are sanity checks for the same rule: low sample rates create false low-frequency patterns, not trustworthy compression.

This section:

6.8 Edge Data Reduction Techniques

This section: Edge Data Reduction Techniques

Time: ~12 min | Difficulty: Intermediate | Reference: P10.C08.U03b

Before transmitting data to the cloud, edge devices can apply several reduction strategies:

  1. Aggregation: Compute statistics over time windows (mean, min, max, variance)
  2. Compression: Apply lossless (ZIP) or lossy (threshold-based) compression
  3. Event-based reporting: Only transmit when values exceed thresholds
  4. Delta encoding: Send only changes from previous values
# Example: Edge aggregation for temperature sensor
class EdgeAggregator:
    def __init__(self, window_size=60):  # 60 samples = 1 minute at 1 Hz
        self.window_size = window_size
        self.buffer = []

    def add_sample(self, value):
        self.buffer.append(value)
        if len(self.buffer) >= self.window_size:
            return self.compute_summary()
        return None

    def compute_summary(self):
        summary = {
            "min": min(self.buffer),
            "max": max(self.buffer),
            "mean": sum(self.buffer) / len(self.buffer),
            "samples": len(self.buffer)
        }
        self.buffer = []
        return summary

# Usage: Send 1 summary per minute instead of 60 raw samples
aggregator = EdgeAggregator(window_size=60)
for temp_reading in sensor_stream:
    summary = aggregator.add_sample(temp_reading)
    if summary:
        transmit_to_cloud(summary)  # 60x bandwidth reduction
Try It: Edge Aggregation Data Reduction

Adjust the sensor sampling rate and aggregation window size to see how edge aggregation reduces data volume. The widget calculates the bandwidth reduction and shows what information is preserved versus lost.

Battery life impact of edge aggregation vs raw transmission:

Scenario: Temperature sensor with 2500 mAh battery, 1 reading/minute

Option A: Raw transmission (every reading sent):

  • LoRa TX: 120 mA for 1.5s per transmission
  • Transmissions per hour: 60
  • TX energy per hour: (120 mA×1.5 s×60)/3600=3.0 mAh(120 \text{ mA} \times 1.5 \text{ s} \times 60) / 3600 = 3.0 \text{ mAh}
  • Plus sleep: 0.01 mAh/hour
  • Total: 3.01 mAh/hour → battery life = 2500 / 3.01 = 831 hours = 35 days

Option B: Edge aggregation (1 summary every 15 minutes):

  • Transmissions per hour: 4
  • TX energy per hour: (120 mA×1.5 s×4)/3600=0.20 mAh(120 \text{ mA} \times 1.5 \text{ s} \times 4) / 3600 = 0.20 \text{ mAh}
  • Plus sleep: 0.01 mAh/hour
  • Total: 0.21 mAh/hour → battery life = 2500 / 0.21 = 11,905 hours = 496 days = 1.4 years

Battery life improvement: 49635=14.2×\frac{496}{35} = 14.2\times longer

Data volume comparison:

  • Raw: 60 packets/hour × 20 bytes = 1.2 kB/hour = 28.8 kB/day
  • Aggregated: 4 packets/hour × 32 bytes (min/max/mean/count) = 128 bytes/hour = 3.1 kB/day
  • Bandwidth reduction: 28.83.1=9.3×\frac{28.8}{3.1} = 9.3\times

Key insight: Transmission dominates power budget. Aggregation provides 14× battery improvement with minimal information loss for trend analysis.

6.9 Battery vs Aggregation Calculator

This section: Battery vs Aggregation Calculator — Adjust the parameters below to see how edge aggregation affects battery life and bandwidth for a LoRa-connected sensor.

Adjust the parameters below to see how edge aggregation affects battery life and bandwidth for a LoRa-connected sensor.

Common Pitfall: Sampling Rate Mismatch

The mistake: Combining data from sensors with different sampling rates without proper resampling, leading to incorrect correlations and temporal misalignment.

Symptoms:

  • Correlation analysis shows unexpected null or spurious relationships
  • Merged datasets have many NaN/missing values at certain timestamps
  • Time-series plots show “jagged” or misaligned signals
  • ML models perform poorly despite good individual sensor data

Why it happens: Teams often assume all sensors operate at the same rate. A temperature sensor at 1 Hz combined with a vibration sensor at 100 Hz creates 99 missing values per temperature reading. Naive timestamp matching drops 99% of vibration data.

The fix: Use proper resampling/interpolation before combining:

# Resample high-frequency data to match low-frequency
vibration_1hz = vibration_100hz.resample('1S').mean()
# Or upsample low-frequency with interpolation
temp_100hz = temp_1hz.resample('10ms').interpolate(method='linear')
# Then merge on aligned timestamps
merged = pd.merge_asof(vibration_1hz, temp_1hz, on='timestamp', tolerance=pd.Timedelta('500ms'))

Prevention: Document sampling rates in sensor metadata. Create a data alignment layer that resamples all sources to a common time base before analysis.

Common Pitfall: Edge Buffer Overflow
  1. Data Dora crosses out an average-only buffer plan in red; the same panel shows a network outage, a burst filling the buffer, dropped readings, and a larger worst-case plan.

    Wrong: Average traffic is enough to size the buffer. Outages and bursts can fill it and erase readings.

CP-0048 misconception buster: Configuring edge device buffers without considering worst-case scenarios, causing data loss during network outages or traffic spikes.

The mistake: Configuring edge device buffers without considering worst-case scenarios, causing data loss during network outages or traffic spikes.

Symptoms:

  • Gaps in time-series data after network recovery
  • “Buffer full, dropping oldest data” warnings in device logs
  • Critical events missing during high-activity periods
  • Inconsistent data counts between edge and cloud
  • Post-incident analysis reveals missing sensor readings

Why it happens: Buffer sizes calculated for average conditions, not peak loads. Network outage duration underestimated. Sensor burst rates during events (motion, vibration) exceed steady-state assumptions. Memory constraints on edge devices force small buffers.

The fix: Size the buffer for the maximum accepted outage using the measured peak arrival rate; add a safety margin and state the overflow policy.

# Measured peak accepted arrival rate during the outage
samples_per_second = 10
max_outage_duration_seconds = 3600  # 1 hour
safety_margin = 1.5

min_buffer_size = samples_per_second * max_outage_duration_seconds * safety_margin
# = 10 * 3600 * 1.5 = 54,000 samples

# If memory-constrained, implement tiered retention:
# - Last 5 minutes: Full resolution
# - 5-60 minutes: 10x downsampled
# - Beyond 60 minutes: Statistical summary only
Buffer Sizing for Outages

Calculate the required buffer size for your edge device based on sampling rate, expected outage duration, and available memory. The rate input must be the peak accepted arrival rate, not the calm average. See how tiered retention can help when memory is constrained.

Prevention: Monitor buffer utilization as a health metric. Alert at 70% capacity. Implement graceful degradation (reduce resolution before dropping data). Test with simulated network outages lasting 2x your expected maximum.

Data Dora, Data and analytics domain expertCheckpoint: Reduce Before Transmit

You now know:

  • Aggregation can replace 60 raw samples with 1 summary when min, max, mean, and count preserve the decision evidence.
  • Transmission dominates many edge power budgets: the worked LoRa case moves from 35 days to 496 days by sending 4 summaries per hour.
  • Buffer plans need peak-load math, including the 54,000-sample outage calculation, before teams trust compressed or tiered retention data.

6.10 Compression Algorithms Deep Dive

This section: Compression Algorithms Deep Dive

Time: ~20 min | Difficulty: Advanced | Reference: P10.C08.U03c

Edge devices face a fundamental trade-off: transmit less data (save power, bandwidth, cost) while preserving information needed for downstream analytics. This deep dive compares compression techniques across three dimensions: compression ratio, computational cost, and information preservation.

6.11 Compression Algorithm Categories

CategoryCompression RatioCPU CostInformation LossBest For
Lossless2:1 - 4:1MediumNoneCritical data, audit logs
Lossy Statistical10:1 - 100:1LowControlledTrend analysis, dashboards
Lossy Transform50:1 - 500:1HighControlledPattern detection, ML features
Semantic100:1 - 1000:1Low-MediumSignificantEvent detection, alerts

6.12 Lossless Compression: DEFLATE/GZIP

Standard lossless compression works well for structured IoT data:

import gzip
import json

def compress_batch(readings: list[dict]) -> bytes:
    """
    Compress a batch of sensor readings losslessly.
    Typical compression: 3-5x for JSON sensor data.
    """
    json_str = json.dumps(readings)
    compressed = gzip.compress(json_str.encode('utf-8'), compresslevel=6)
    return compressed

# Example: 100 temperature readings
readings = [{"ts": 1704067200 + i, "v": 22.5 + (i % 10) * 0.1} for i in range(100)]
raw_size = len(json.dumps(readings).encode())       # ~4,500 bytes
compressed_size = len(compress_batch(readings))     # ~1,200 bytes
# Compression ratio: 3.75:1
Try It: GZIP Compression Estimator

Explore how batch size, data format, and compression level affect lossless GZIP compression of IoT sensor readings.

Performance characteristics:

MetricGZIP Level 1GZIP Level 6GZIP Level 9
Compression ratio2.5:13.5:14:1
Compress speed50 MB/s20 MB/s5 MB/s
Decompress speed100 MB/s100 MB/s100 MB/s
Edge CPU impactLowMediumHigh

When to use: Audit trails, compliance data, any data that may be queried in original form. Do not use for real-time streams on constrained MCUs.

6.13 Lossy Statistical: Aggregation Windows

Compute statistics over time windows, discard raw samples:

import statistics
from dataclasses import dataclass
from typing import Optional

@dataclass
class AggregatedWindow:
    timestamp: int      # Window start
    count: int          # Number of samples
    mean: float
    min_val: float
    max_val: float
    std_dev: float
    p95: Optional[float] = None  # Optional percentile

class WindowAggregator:
    def __init__(self, window_seconds: int = 60):
        self.window_seconds = window_seconds
        self.buffer: list[float] = []
        self.window_start: Optional[int] = None

    def add_sample(self, timestamp: int, value: float) -> Optional[AggregatedWindow]:
        if self.window_start is None:
            self.window_start = timestamp

        # Check if window complete
        if timestamp - self.window_start >= self.window_seconds:
            result = self._compute_aggregate()
            self.buffer = [value]
            self.window_start = timestamp
            return result

        self.buffer.append(value)
        return None

    def _compute_aggregate(self) -> AggregatedWindow:
        sorted_buffer = sorted(self.buffer)
        p95_idx = int(len(sorted_buffer) * 0.95)

        return AggregatedWindow(
            timestamp=self.window_start,
            count=len(self.buffer),
            mean=statistics.mean(self.buffer),
            min_val=min(self.buffer),
            max_val=max(self.buffer),
            std_dev=statistics.stdev(self.buffer) if len(self.buffer) > 1 else 0,
            p95=sorted_buffer[p95_idx] if p95_idx < len(sorted_buffer) else None
        )

# Example: 1 Hz sensor, 60-second windows
# Input: 60 samples x 8 bytes = 480 bytes
# Output: 1 aggregate x 48 bytes = 48 bytes
# Compression ratio: 10:1
# Preserved: Trend (mean), anomaly detection (min/max/std), health (count)
Window Aggregation Calculator

Configure the sensor rate and aggregation window to see how statistical summaries compress continuous data while preserving trend and anomaly detection capability.

Information loss analysis:

What’s PreservedWhat’s Lost
Average value (trend)Individual sample timing
Min/max (bounds)Exact sequence of values
Standard deviation (stability)Sub-window patterns
Sample count (health)Correlation with other sensors at sample level

When to use: Temperature, humidity, air quality - any slowly changing signal where trends matter more than exact samples.

6.14 Lossy Transform: FFT-Based Compression

Transform to frequency domain, keep only significant components:

import numpy as np
from dataclasses import dataclass

@dataclass
class FFTCompressed:
    timestamp: int
    sample_rate: float
    duration: float
    frequencies: list[float]    # Top N frequency components
    magnitudes: list[float]     # Corresponding magnitudes
    phases: list[float]         # Phase angles for reconstruction

def fft_compress(samples: np.ndarray, sample_rate: float,
                 timestamp: int, top_n: int = 10) -> FFTCompressed:
    """
    Compress time-series data using FFT, keeping top N frequency components.

    Typical compression: 100:1 to 500:1 depending on signal complexity.
    Best for: Vibration, audio, periodic signals.
    """
    # Compute FFT
    fft_result = np.fft.rfft(samples)
    freqs = np.fft.rfftfreq(len(samples), 1/sample_rate)

    # Get magnitudes and find top N (excluding DC component)
    magnitudes = np.abs(fft_result[1:])  # Skip DC
    phases = np.angle(fft_result[1:])
    freqs = freqs[1:]

    # Select top N by magnitude
    top_indices = np.argsort(magnitudes)[-top_n:]

    return FFTCompressed(
        timestamp=timestamp,
        sample_rate=sample_rate,
        duration=len(samples) / sample_rate,
        frequencies=freqs[top_indices].tolist(),
        magnitudes=magnitudes[top_indices].tolist(),
        phases=phases[top_indices].tolist()
    )

def fft_decompress(compressed: FFTCompressed, num_samples: int) -> np.ndarray:
    """
    Reconstruct signal from FFT components (lossy reconstruction).
    """
    t = np.linspace(0, compressed.duration, num_samples)
    signal = np.zeros(num_samples)

    for freq, mag, phase in zip(compressed.frequencies,
                                 compressed.magnitudes,
                                 compressed.phases):
        signal += mag * np.cos(2 * np.pi * freq * t + phase)

    return signal

# Example: Vibration sensor, 1 second at 1000 Hz
samples = np.sin(2*np.pi*50*np.linspace(0, 1, 1000))  # 50 Hz signal
samples += 0.3 * np.sin(2*np.pi*150*np.linspace(0, 1, 1000))  # 150 Hz harmonic

# Input: 1000 samples x 4 bytes = 4000 bytes
# Output: 10 freq-mag-phase tuples x 12 bytes = 120 bytes + 20 bytes metadata
# Compression ratio: ~30:1

compressed = fft_compress(samples, 1000.0, 1704067200, top_n=10)
reconstructed = fft_decompress(compressed, 1000)

# Reconstruction error for this example: ~5% RMS
# Selected spectral features remain available; validate fault detection on representative traces
Try It: FFT Compression Explorer

Explore how FFT-based compression trades off between keeping more frequency components (higher fidelity) and achieving higher compression. Adjust the signal parameters and number of retained components.

When to use: Vibration analysis, acoustic monitoring, any signal where frequency content matters more than exact waveform.

6.15 Continue to Part 2

This section: Continue to Part 2 — Continue with Edge Data: Semantic Compression and Pipelines.

Continue with Edge Data: Semantic Compression and Pipelines.

Find help

3 reviewed answers.

Where should I start in a module?

Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.

Modules and paths

Reviewed

What can I try when a project does not work?

Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.

When you are stuck

Reviewed

How do interactive examples work?

Use the interactive guide to check how examples and simulations work before changing your project.

Interactive examples guide

Reviewed