This repository was archived by the owner on Jan 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathqqplot.tsx
More file actions
113 lines (96 loc) · 2.46 KB
/
Copy pathqqplot.tsx
File metadata and controls
113 lines (96 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* author: Samuel Gratzl
* email: samuel_gratzl@gmx.at
* created: 2016-10-28T11:19:52.797Z
*/
import * as React from 'react';
import merge from 'datavisyn-scatterplot/src/merge';
import Impl, {IScatterplotOptions} from 'datavisyn-scatterplot/src';
import {quantile} from 'd3-array';
export class XY {
constructor(public x: number, public y: number, public q: number) {
}
toString() {
return `Quantile ${this.q}: x = ${this.x}, y = ${this.y}`;
}
}
/**
* all scatterplot options and the data
*/
export interface IQQPlotProps {
a: number[];
b: number[];
options?: IScatterplotOptions<XY>;
}
function byNumber(a: number, b: number) {
return a - b;
}
/**
* see R ppoints function
* (1:m - a)/(m + (1-a)-a) where m is either n, if length(n)==1, or length(n)
* ppoints(n, a = if(n <= 10) 3/8 else 1/2)
* @param length
* @returns {Array}
*/
function ppoints(n: number|number[], a?: number) {
const m = Array.isArray(n) ? n.length : n as number;
if (a === undefined) {
a = m <= 10 ? 3. / 8 : 1. / 2;
}
const factor = 1 / (m + (1 - a) - a);
const r: number[] = [];
for (let i = 1; i <= (m - a); ++i) {
r.push(i * factor);
}
return r;
}
/**
* compute data for QQ plot
* @param a
* @param b
* @returns {Array}
*/
function computeData(a: number[], b: number[]): XY[] {
const aSorted = a.slice().sort(byNumber);
const bSorted = b.slice().sort(byNumber);
return ppoints(Math.min(aSorted.length, bSorted.length)).map((q) => {
return new XY(quantile(aSorted, q), quantile(bSorted, q), q);
});
}
export default class QQPlot extends React.Component<IQQPlotProps,{}> {
static propTypes = {
a: React.PropTypes.array.isRequired,
b: React.PropTypes.array.isRequired,
options: React.PropTypes.object
};
static defaultProps = {
a: [],
b: []
};
private plot: Impl<XY> = null;
private parent: HTMLDivElement = null;
constructor(props: IQQPlotProps, context?: any) {
super(props, context);
}
componentDidMount() {
//create impl
const data = computeData(this.props.a, this.props.b);
const clone = merge({
isSelectEvent: null
}, this.props.options);
this.plot = new Impl<XY>(data, this.parent, clone);
this.plot.render();
console.log('b');
}
componentDidUpdate() {
//new data recreate
console.log('ads');
this.plot.data = computeData(this.props.a, this.props.b);
}
render() {
return (
<div ref={(div) => this.parent = div}>
</div>
);
}
}