diff options
Diffstat (limited to 'src/client/views/nodes/DataVizBox/components/Histogram.tsx')
-rw-r--r-- | src/client/views/nodes/DataVizBox/components/Histogram.tsx | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 14063a068..c7850d8c1 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -14,6 +14,8 @@ import { PinProps, PresBox } from "../../trails"; import { Docs } from "../../../../documents/Documents"; import { List } from "../../../../../fields/List"; import './Chart.scss'; +import { minMaxRange } from "../utils/D3Utils"; +import e from "connect-flash"; export interface HistogramProps { rootDoc: Doc; @@ -37,6 +39,7 @@ export class Histogram extends React.Component<HistogramProps> { private _disposers: { [key: string]: IReactionDisposer } = {}; private _histogramRef: React.RefObject<HTMLDivElement> = React.createRef(); private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined; + private numericalData: boolean = false; @observable _currSelected: SelectedDataPoint | undefined = undefined; // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates @@ -44,12 +47,15 @@ export class Histogram extends React.Component<HistogramProps> { if (this.props.axes.length < 1) return []; if (this.props.axes.length < 2) { var ax0 = this.props.axes[0]; + if (+this.props.pairs[0][this.props.axes[0]]) { this.numericalData = true;} return this.props.pairs ?.filter(pair => (!this.incomingLinks.length ? true : Array.from(Object.keys(pair)).some(key => pair[key] && key.startsWith('select')))) .map(pair => ({ [ax0]: (pair[this.props.axes[0]])})) }; + var ax0 = this.props.axes[0]; var ax1 = this.props.axes[1]; + if (+this.props.pairs[0][this.props.axes[0]]) { this.numericalData = true;} return this.props.pairs ?.filter(pair => (!this.incomingLinks.length ? true : Array.from(Object.keys(pair)).some(key => pair[key] && key.startsWith('select')))) .map(pair => ({ [ax0]: (pair[this.props.axes[0]]), [ax1]: (pair[this.props.axes[1]]) })) @@ -73,6 +79,13 @@ export class Histogram extends React.Component<HistogramProps> { .map(dvb => dvb.pairs?.filter((pair: { [x: string]: any; }) => pair['select' + dvb.rootDoc[Id]])) // get all the datapoints they have selected field set by incoming anchor .lastElement(); } + @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } { + if (this.numericalData){ + const data = this.data(this._histogramData); + return {xMin: Math.min.apply(null, data), xMax: Math.max.apply(null, data), yMin:0, yMax:0} + } + return {xMin:0, xMax:0, yMin:0, yMax:0} + } componentWillUnmount() { Array.from(Object.keys(this._disposers)).forEach(key => this._disposers[key]()); } @@ -207,26 +220,7 @@ export class Histogram extends React.Component<HistogramProps> { this.props.pairs.forEach(pair => (pair.selected = pair[this.props.axes[0]] === x && pair[this.props.axes[1]] === y ? true : undefined)); } - drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) { - if (this._histogramSvg) { - const circleClass = '.circle-' + idx; - this._histogramSvg - .selectAll(circleClass) - .data(data) - .join('circle') // enter append - .attr('class', `${circleClass} datapoint`) - .attr('r', '3') // radius - .attr('cx', d => xScale(d.x)) - .attr('cy', d => yScale(d.y)) - .attr('data-x', d => d.x) - .attr('data-y', d => d.y); - } - } - - drawChart = (dataSet: any, width: number, height: number) => { - d3.select(this._histogramRef.current).select('svg').remove(); - d3.select(this._histogramRef.current).select('.tooltip').remove(); - + data = (dataSet: any) => { var validData = dataSet.filter((d: { [x: string]: unknown; }) => { var valid = true; Object.keys(dataSet[0]).map(key => { @@ -236,13 +230,24 @@ export class Histogram extends React.Component<HistogramProps> { }) var field = Object.keys(dataSet[0])[0] const data = validData.map((d: { [x: string]: any; }) => { - if (+d[field]) {return +d[field] } + if (this.numericalData) {return +d[field] } return d[field] }) + return data; + } + + drawChart = (dataSet: any, width: number, height: number) => { + d3.select(this._histogramRef.current).select('svg').remove(); + d3.select(this._histogramRef.current).select('.tooltip').remove(); + var field = Object.keys(dataSet[0])[0] + const data = this.data(dataSet); + let uniqueArr = [...new Set(data)] var numBins = uniqueArr.length - if (+d3.max(data)!) numBins = +d3.max(data)! + if (this.numericalData) numBins = this.rangeVals.xMax! - this.rangeVals.xMin! + 1; + var startingPoint = this.numericalData==true? this.rangeVals.xMin: 0; + console.log(startingPoint) const svg = (this._histogramSvg = d3 .select(this._histogramRef.current) @@ -254,19 +259,32 @@ export class Histogram extends React.Component<HistogramProps> { .attr("transform", "translate(" + this.props.margin.left + "," + this.props.margin.top + ")")); - var x = d3.scaleLinear() - .domain([0, numBins]) - .range([0, width]); + var x: any; + if (this.numericalData){ + x = d3.scaleLinear() + .domain([this.rangeVals.xMin!, this.rangeVals.xMax!]) + .range([0, width-(width/numBins)]); + } + else { + x = d3.scaleLinear() + .domain([0, numBins]) + .range([0, width]); + } + var xAxis = d3.axisBottom(x) - .ticks(numBins) - var translateXAxis = 0; + .ticks(numBins-1) + var translateXAxis = (width/numBins) / 2; var histogram = d3.histogram() .value(function(d) {return d}) - .domain([0, numBins]) + .domain([startingPoint!, numBins+startingPoint!]) .thresholds(x.ticks(numBins)) var bins = histogram(data) - if (!+d3.max(data)!) { // if the data is strings rather than numbers + console.log(this._histogramData) + console.log(data) + console.log(bins) + console.log(this.rangeVals.xMin, this.rangeVals.xMax, numBins) + if (!this.numericalData) { // if the data is strings rather than numbers uniqueArr.sort() for (let i=0; i<data.length; i++){ var index = 0 @@ -277,10 +295,9 @@ export class Histogram extends React.Component<HistogramProps> { } bins[index].push(data[i]) } - bins.forEach(d => d.x0 = d.x0!+1) + bins.forEach(d => d.x0 = d.x0!) xAxis = d3.axisBottom(x) - .ticks(numBins) - .tickValues([0, 1, 2, 3, 4]) + .ticks(numBins-1) .tickFormat( i => uniqueArr[i]) .tickPadding(10) translateXAxis = (width/numBins) / 2; @@ -316,7 +333,7 @@ export class Histogram extends React.Component<HistogramProps> { .enter() .append("rect") .attr("x", 1) - .attr("transform", function(d) { return "translate(" + x(d.x0! - 1) + "," + y(d.length) + ")"; }) + .attr("transform", function(d) { return "translate(" + x(d.x0!) + "," + y(d.length) + ")"; }) .attr("width", width/(numBins)) .attr("height", function(d) { return height - y(d.length); }) .attr("style", "outline: thin solid black;") |