ng2-charts icon indicating copy to clipboard operation
ng2-charts copied to clipboard

Data Decimation not working

Open noobnoobdc137 opened this issue 2 years ago • 7 comments

Reproduction of the problem

TS file

import { Component, ViewChild } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import 'chartjs-adapter-moment';

function randNumGen(max) {
  return Math.floor((Math.random() * max) + 1)
}

const NUM_POINTS = 10000;

const START = 1617235200000;
const POINT_DATA = [];

for (let i = 0; i < NUM_POINTS; ++i) {
  const max = Math.random() < 0.001 ? 100 : 20;
  const randNumber = randNumGen(max)
  POINT_DATA.push({ x: START + i * 30000, y: randNumber });
}

@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styleUrls: ['./line-chart.component.css']
})
export class LineChartComponent {

  @ViewChild(BaseChartDirective) chart?: BaseChartDirective;



  data = {
    datasets: [
      {
        borderColor: "red",
        borderWidth: 1,
        data: POINT_DATA,
        label: "Large Dataset",
        radius: 0,
      },
    ],
  };


  plugins = {
    decimation: {
      enabled: false,
      algorithm: 'min-max',
    },
  }


  options = {
    animation: false,
    parsing: false,

    interaction: {
      mode: "nearest",
      axis: "x",
      intersect: false,
    },

    scales: {
      x: {
        type: "time",
        ticks: {
          source: "auto",
          maxRotation: 0,
          autoSkip: true,
        },
      },
    },
  }

  public buttonOnclick() {
    this.plugins.decimation.enabled = true;
    this.plugins.decimation.algorithm = 'min-max';

    this.chart.chart.update();
  }
}

Template HTML

<div class="flex">
  <div class="flex-item">
    <div style="display: block">
      <canvas
        baseChart
        width="400"
        height="400"
        [data]="data"
        [options]="options"
        [type]="'line'"
        [plugins]="plugins"
      ></canvas>
    </div>
  </div>
  <button (click)="buttonOnclick()">
    Decimation {{ plugins.decimation.enabled }}
  </button>
</div>

Versions

Package Version
chart.js 3.7.1
ng2-charts 3.0.8
chartjs-adapter-date-fns 2.0.0
chartjs-adapter-luxon 1.1.0
chartjs-adapter-moment 1.0.0

Angular Version: 12.1.1

noobnoobdc137 avatar Feb 23 '22 07:02 noobnoobdc137

@noobnoobdc137 - You mind putting this in a stackblitz or codesandbox for all of us?

tru-koto avatar Feb 24 '22 17:02 tru-koto

Not working for me either. Ideally, a simple way to have it would be;

public lineChartOptions: ChartConfiguration['options'] = {
    elements: {
      line: {
        tension: 0.5
      }
    },
    scales: {
      x: {},
      'y-axis-0':
      {
        position: 'left',
        reverse: this.reverseInput
      },
    },
    plugins: {
      legend: { display: true },
      decimation: {
        enabled: true,
        algorithm: 'lttb',
        samples:50
      },
    }

  };

And pass those option to the chart

  <canvas baseChart
          [data]="lineChartData"
          [options]="lineChartOptions"
          [type]="lineChartType"></canvas>

My line chart has too many points crowding the line. It would be great to 'thin the herd' with this simple plugin.

lunar-safari avatar Mar 11 '22 02:03 lunar-safari

Probably decimation needs a re-render of the chart? Can you try using this.chart.render(); or setting the decimation.enabled to true from the start to see if it makes any difference?

santam85 avatar Mar 23 '22 08:03 santam85

Did anybody get this to work? I am having the same problem. My data gets rendered but decimation is not applied.

nicolas-cusan avatar Oct 06 '22 14:10 nicolas-cusan

Any updates on this? I'm running into a similar issue

jmtimper avatar Oct 18 '22 01:10 jmtimper

I did get it to work, but it took some fiddling. I preprocessed my data to not need any interpolation by converting my x axis from an ISO Date to Milliseconds, that did the trick. I used luxon and the luxon chart.js adapter for the conversion and formatting.

This is the code I applied to activate decimation:

plugins: {
  // ...
  decimation: {
    algorithm: 'lttb',
    enabled: true,
    samples: 100,
    threshold: 40,
  },
 // ...
}

For display purposes I formatted the date like this:

scales: {
  x: {
    type: 'time',
    time: {
      displayFormats: {
        month: 'MMM ‘yy',
      },
    },
  },
  // ...
}

Hope it helps.

nicolas-cusan avatar Oct 18 '22 07:10 nicolas-cusan

Hope it helps.

Thank you. I realized that threshold must be specified for small values. In my case it's

{
  ...
  decimation: {
    algorithm: 'lttb',
    enabled: true,
    samples: 25,
    threshold: 25,
  }
}

and it didn't work unless explicitly stated

just-website avatar May 16 '24 16:05 just-website