KarrLab/datanator_frontend

View on GitHub
src/scenes/Stats/Plot/FrequencyPlot.js

Summary

Maintainability
C
1 day
Test Coverage
F
37%
import React, { Component } from "react";
import PropTypes from "prop-types";
import Chart from "chart.js";

import * as colorPalette from "~/colors.scss";
var kernel = require("kernel-smooth");
export default class FrequencyPlot extends Component {
  static propTypes = {
    data: PropTypes.shape({
      labels: PropTypes.array.isRequired,
      values: PropTypes.array.isRequired,
    }).isRequired,
    xAxisLabel: PropTypes.string.isRequired,
    xMin: PropTypes.number,
    xMax: PropTypes.number,
    yAxisLabel: PropTypes.string.isRequired,
    kernelBandwidth: PropTypes.number,
  };

  static defaultProps = {
    xMin: null,
    xMax: null,
    kernelBandwidth: 0.5,
  };

  constructor(props) {
    super(props);
    this.canvas = React.createRef();
    this.chart = null;
  }

  componentDidMount() {
    this.configChart();
  }

  componentDidUpdate() {
    this.configChart();
  }

  configChart() {
    if (!this.props.data.values.length) {
      return;
    }

    let xData = this.props.data.labels;
    let yData = this.props.data.values;
    let fHat = kernel.regression(
      xData,
      yData,
      kernel.fun.gaussian,
      this.props.kernelBandwidth
    );
    let xMin, xMax;
    if (this.props.xMin == null) {
      xMin = Math.min(...xData);
    } else {
      xMin = this.props.xMin;
    }
    if (this.props.xMax == null) {
      xMax = Math.max(...xData);
    } else {
      xMax = this.props.xMax;
    }
    let data = [];
    let nPoints = 101;
    for (let i = 0; i < nPoints; i++) {
      let xVal = xMin + ((xMax - xMin) * i) / (nPoints - 1);
      data.push({ x: xVal, y: fHat(xVal) });
    }
    let chartConfig = {
      type: "line",
      data: {
        datasets: [
          {
            label: "distribution",
            backgroundColor: colorPalette["primary-lighter"],
            borderColor: colorPalette["primary-light"],
            borderWidth: 2.0,
            data: data,
            pointRadius: 0,
            showLine: true,
          },
        ],
      },
      options: {
        events: [],
        responsive: true,
        maintainAspectRatio: false,
        legend: {
          display: false,
        },
        animation: null,
        title: {
          display: false,
        },
        scales: {
          yAxes: [
            {
              type: "linear",
              scaleLabel: {
                display: true,
                labelString: this.props.yAxisLabel,
              },
              ticks: {
                maxTicksLimit: 4,
              },
            },
          ],
          xAxes: [
            {
              type: "linear",
              scaleLabel: {
                display: true,
                labelString: this.props.xAxisLabel,
              },
            },
          ],
        },
      },
    };

    // build chart
    if (this.chart == null) {
      let canvasContext = this.canvas.current.getContext("2d");
      this.chart = new Chart(canvasContext, chartConfig);
    } else {
      this.chart.update(chartConfig);
    }
  }

  render() {
    if (this.props.data.values.length) {
      return (
        <canvas
          ref={this.canvas}
          className="biochemical-entity-scene-measurement-plot"
        />
      );
    } else {
      return <div className="loader"></div>;
    }
  }
}