Powrót do strony głównej

Macierzowy filtr downsamplingu 50M punktów

Macierzowy filtr zapewnia idealne renderowanie scatter-wykresów z 50 mln punktów, zachowując 100% wizualne pokrycie. Porównanie z LTTB, M4 pokazuje utratę struktury w klasycznych metodach. Pełny kod i benchmarki na przemysłowych zbiorach danych.

Idealny downsampling: 100% pokrycie scatter-wykresów
Advertisement 728x90

# Matrycowy filtr dla idealnego downsamplingu wykresów rozrzutu z 50 mln punktów

Matrycowy filtr zapewnia 100% pokrycie i wizualne podobieństwo przy renderowaniu 50 mln punktów ciśnienia w odwiertach naftowych. Klasyczne algorytmy typu LTTB tracą do 59% gęstości danych. Podejście działa w jednym przejściu bez sortowania, ograniczając wynik do liczby pikseli ekranu.

Wykresy rozrzutu są niezbędne dla nieregularnych danych z lukami: linie zniekształcają przerwy i ukrywają klastry. Standardowe metody są zoptymalizowane pod wykresy liniowe, ignorując strukturę dwuwymiarową.

Ograniczenia klasycznych algorytmów

MinMax, M4, LTTB i hybrydy dzielą oś X na kosze, wybierając 1–4 punkty po Y. W gęstych słupkach traci się 96–99% danych: chmura zapada się w ekstrema.

Google AdInline article slot
  • MinMax: minimum i maksimum — zachowuje szczyty, ale ignoruje rozkład.
  • M4: pierwsza, ostatnia, min/maks — idealne dla linii.
  • LTTB: maksymalna powierzchnia trójkąta — sylwetka krzywej.
  • MinMaxLTTB: fiksuje ekstrema, potem wygładza.

Dla rozrzutu to fundamentalna wada: algorytmy nie uwzględniają współrzędnej Y w koszach.

Zasada matrycowego filtra

Analog filtra Voxel Grid z grafiki: projektuje punkty na siatkę pikselową W×H. W każdej komórce zostaje jeden punkt w kolejności przetwarzania.

public static void downsample(
        double[] times, double[] values,
        int width, int height,
        List<double[]> result) {

    int n = times.length;
    if (n == 0) return;

    // Krok 1: granice
    double tMin = times[0], tMax = times[0];
    double vMin = values[0], vMax = values[0];
    for (int i = 1; i < n; i++) {
        if (times[i]  < tMin) tMin = times[i];
        if (times[i]  > tMax) tMax = times[i];
        if (values[i] < vMin) vMin = values[i];
        if (values[i] > vMax) vMax = values[i];
    }
    double tRange = Math.max(tMax - tMin, 1e-10);
    double vRange = Math.max(vMax - vMin, 1e-10);

    // Krok 2: siatka
    boolean[] grid = new boolean[width * height];

    // Krok 3: filtrowanie
    for (int i = 0; i < n; i++) {
        int px = (int) Math.min(width  - 1, (times[i]  - tMin) / tRange * (width  - 1));
        int py = (int) Math.min(height - 1, (values[i] - vMin) / vRange * (height - 1));
        int idx = py * width + px;
        if (!grid[idx]) {
            grid[idx] = true;
            result.add(new double[]{times[i], values[i]});
        }
    }
}

Metoda imituje renderowanie: aktywuje piksele, które zapaliłyby się przy pełnym zestawie. Ograniczenie — tylko do wizualizacji, nie do statystyki.

Google AdInline article slot

Metodologia testów

~3000 zbiorów danych telemetrii odwiertów: od 19k do 50M+ punktów. Porównanie piksel po pikselu z oryginałem w trybach rozrzut (2×2px) i linie (1px).

Metryki:

  • Pokrycie: % pikseli oryginału pokrytych przez algorytm.
  • Precyzja: % pikseli algorytmu w oryginale.
  • F1-score: średnia harmoniczna.
  • Wynik wizualny: F1 z tolerancją ±1px (uwzględnia subpiksele).

Budżet dla klasyki — wynik MatrixFilter 1920×1080. Stanowisko: i7-7700K, Java 17, jeden wątek.

Google AdInline article slot

Wyniki na rzeczywistych danych

Regularne (~20k punktów, 2930 plików)

Rozrzut: MatrixFilter 1920×1080 — 100% we wszystkich metrykach. MatrixFilter 800×600 — Wizualne 99.6%, dwukrotnie mniej punktów. Klasyka: Pokrycie 63–84%, Wizualne 76–95%.

| Algorytm | Śr. Wyj. | Razem ms | Pokrycie | Prec. | F1 | Wizualne |

|-------------------|----------|----------|----------|-------|------|----------|

| Matrix 1920×1080 | 4939 | 695 | 100% | 100% | 100% | 100% |

| Matrix 800×600 | 2867 | 497 | 84.6% | 100% | 91.5%| 99.6% |

| MinMaxLTTB x4 | 4932 | 494 | 84.1% | 100% | 90.9%| 95.2% |

Średnie i duże

Na 500k–50M punktów Matrix zachowuje 100% Wizualne przy czasie ~ms/10k punktów. LTTB spada do 16–40% Pokrycia na gęstych danych.

Co ważne

  • Matrycowy filtr daje idealny rozrzut bez sortowania, złożoność O(n).
  • Klasyczne algorytmy tracą strukturę gęstych chmur, mimo hojnego budżetu.
  • Wynik wizualny z ±1px bliższy percepcji: Matrix 800×600 nieodróżnialny od pełnego renderu.
  • Zastosowanie ściśle wizualne: dla linii/statystyki inne metody.
  • Testowane na przemysłowych zbiorach danych wydobycia ropy z nieregularnymi lukami.

— Editorial Team

Advertisement 728x90

Czytaj dalej