d3.ticks error visualization

by Alexander Shutov

HTML

<script src="https://cdn.jsdelivr.net/npm/d3@4/build/d3.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/taucharts.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/taucharts.min.css">

CSS

html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

JavaScript

const countMin = 2;
const countMax = 100;
const step = 1;
const start = 0;
const max = 100;
const threshold = 0.25;

let maxError = -Infinity;
let worst = null;
let total = 0;
let failures = 0;
let chartData = [];

for (let end = start + step; end <= max; end += step) {
  for (let count = countMin; count <= countMax; count++) {
    let ticks = d3.ticks(start, end, count);
    let error = (ticks.length - count) / count;
    if (error > 0 && error > maxError) {
      maxError = error;
      worst = {
        start,
        end,
        count,
        result: ticks.length
      };
    }
    total++;
    if (error > threshold) {
      failures++;
    }
    if (error > 0) {
      chartData.push({
        'Ticks count': count,
        'Error': error,
        'Domain end': end
      });
    }
  }
}

const percent = (x) => `${(x * 100).toFixed()}%`;
console.log(`> Worst result: d3.ticks(${worst.start}, ${worst.end}, ${worst.count})`);
console.log(`> Array(${worst.result}) (error ${percent(maxError)})`);
console.log(`> Error more than ${percent(threshold)} in ${percent(failures / total)} cases`);

const chart = new Taucharts.Chart({
  type: 'scatterplot',
  x: 'Domain end',
  y: 'Ticks count',
  size: 'Error',
  color: 'Error',
  data: chartData,
  guide: {
    size: {
      minSize: 1,
      maxSize: 8
    }
  },
  plugins: [
    Taucharts.api.plugins.get('legend')(),
    Taucharts.api.plugins.get('tooltip')({
      formatters: {
        'Error': percent
      }
    }), {
      init(chart) {
        var header = document.createElement('h3');
        header.style.textAlign = 'center';
        header.textContent = 'd3.ticks count error';
        chart.insertToHeader(header);
      }
    }
  ]
});
chart.renderTo(document.body);