X-log
This commit is contained in:
parent
e77b1c2e60
commit
825f5e19b2
|
@ -156,7 +156,8 @@ module DistPlusChart = {
|
|||
let (yMaxDiscreteDomainFactor, yMaxContinuousDomainFactor) =
|
||||
adjustBoth(toDiscreteProbabilityMass);
|
||||
<DistributionPlot
|
||||
scale={config.log ? "log" : "linear"}
|
||||
xScale={config.xLog ? "log" : "linear"}
|
||||
yScale={config.yLog ? "log" : "linear"}
|
||||
height={DistPlusPlotReducer.heightToPix(config.height)}
|
||||
minX
|
||||
maxX
|
||||
|
@ -191,7 +192,8 @@ module IntegralChart = {
|
|||
let maxX = integral |> Distributions.Continuous.T.maxX;
|
||||
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
|
||||
<DistributionPlot
|
||||
scale={config.log ? "log" : "linear"}
|
||||
xScale={config.xLog ? "log" : "linear"}
|
||||
yScale={config.yLog ? "log" : "linear"}
|
||||
height={DistPlusPlotReducer.heightToPix(config.height)}
|
||||
minX
|
||||
maxX
|
||||
|
@ -244,8 +246,13 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
|||
<div className="opacity-50 hover:opacity-100">
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(CHANGE_LOG(index))}>
|
||||
{(config.log ? "x-log" : "x-linear") |> ReasonReact.string}
|
||||
onClick={_ => dispatch(CHANGE_X_LOG(index))}>
|
||||
{(config.xLog ? "x-log" : "x-linear") |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(CHANGE_Y_LOG(index))}>
|
||||
{(config.yLog ? "y-log" : "y-linear") |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
|
@ -293,4 +300,4 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
|||
{state.showParams ? showAsForm(distPlus) : ReasonReact.null}
|
||||
{state.showStats ? table(distPlus, x) : ReasonReact.null}
|
||||
</div>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
type chartConfig = {
|
||||
log: bool,
|
||||
xLog: bool,
|
||||
yLog: bool,
|
||||
isCumulative: bool,
|
||||
height: int,
|
||||
};
|
||||
|
@ -15,7 +16,8 @@ type action =
|
|||
| CHANGE_SHOW_PARAMS
|
||||
| REMOVE_DIST(int)
|
||||
| ADD_DIST
|
||||
| CHANGE_LOG(int)
|
||||
| CHANGE_X_LOG(int)
|
||||
| CHANGE_Y_LOG(int)
|
||||
| CHANGE_IS_CUMULATIVE(int, bool)
|
||||
| HEIGHT_INCREMENT(int)
|
||||
| HEIGHT_DECREMENT(int);
|
||||
|
@ -42,7 +44,6 @@ let heightToPix =
|
|||
| _ => 140;
|
||||
|
||||
let distributionReducer = (index, state: list(chartConfig), action) => {
|
||||
Js.log3(index, action, state);
|
||||
switch (action, E.L.get(state, index)) {
|
||||
| (HEIGHT_INCREMENT(_), Some(dist)) =>
|
||||
E.L.update(
|
||||
|
@ -58,18 +59,24 @@ let distributionReducer = (index, state: list(chartConfig), action) => {
|
|||
)
|
||||
| (CHANGE_IS_CUMULATIVE(_, isCumulative), Some(dist)) =>
|
||||
E.L.update({...dist, isCumulative}, index, state)
|
||||
| (CHANGE_LOG(_), Some(dist)) =>
|
||||
E.L.update({...dist, log: !dist.log}, index, state)
|
||||
| (CHANGE_X_LOG(_), Some(dist)) =>
|
||||
E.L.update({...dist, xLog: !dist.xLog}, index, state)
|
||||
| (CHANGE_Y_LOG(_), Some(dist)) =>
|
||||
E.L.update({...dist, yLog: !dist.yLog}, index, state)
|
||||
| (REMOVE_DIST(_), Some(_)) => E.L.remove(index, 1, state)
|
||||
| (ADD_DIST, Some(_)) =>
|
||||
E.L.append(state, [{log: false, isCumulative: false, height: 2}])
|
||||
E.L.append(
|
||||
state,
|
||||
[{yLog: false, xLog: false, isCumulative: false, height: 2}],
|
||||
)
|
||||
| _ => state
|
||||
};
|
||||
};
|
||||
|
||||
let reducer = (state: state, action: action) =>
|
||||
switch (action) {
|
||||
| CHANGE_LOG(i)
|
||||
| CHANGE_X_LOG(i)
|
||||
| CHANGE_Y_LOG(i)
|
||||
| CHANGE_IS_CUMULATIVE(i, _)
|
||||
| HEIGHT_DECREMENT(i)
|
||||
| REMOVE_DIST(i)
|
||||
|
@ -89,7 +96,7 @@ let init = {
|
|||
showStats: false,
|
||||
showParams: false,
|
||||
distributions: [
|
||||
{log: false, isCumulative: false, height: 2},
|
||||
{log: false, isCumulative: true, height: 1},
|
||||
{yLog: false, xLog: false, isCumulative: false, height: 2},
|
||||
{yLog: false, xLog: false, isCumulative: true, height: 1},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
|
|
@ -29,7 +29,8 @@ module RawPlot = {
|
|||
~onHover=(f: float) => (),
|
||||
~continuous=?,
|
||||
~discrete=?,
|
||||
~scale=?,
|
||||
~xScale=?,
|
||||
~yScale=?,
|
||||
~showDistributionLines=?,
|
||||
~showDistributionYAxis=?,
|
||||
~showVerticalLine=?,
|
||||
|
@ -51,7 +52,8 @@ module RawPlot = {
|
|||
~onHover,
|
||||
~continuous?,
|
||||
~discrete?,
|
||||
~scale?,
|
||||
~xScale?,
|
||||
~yScale?,
|
||||
~showDistributionLines?,
|
||||
~showDistributionYAxis?,
|
||||
~showVerticalLine?,
|
||||
|
@ -116,7 +118,8 @@ let make =
|
|||
~yMaxContinuousDomainFactor=?,
|
||||
~onHover: float => unit=_ => (),
|
||||
~continuous=?,
|
||||
~scale=?,
|
||||
~xScale=?,
|
||||
~yScale=?,
|
||||
~showDistributionLines=false,
|
||||
~showDistributionYAxis=false,
|
||||
~showVerticalLine=false,
|
||||
|
@ -128,7 +131,8 @@ let make =
|
|||
?minX
|
||||
?yMaxDiscreteDomainFactor
|
||||
?yMaxContinuousDomainFactor
|
||||
?scale
|
||||
?xScale
|
||||
?yScale
|
||||
?timeScale
|
||||
discrete={discrete |> E.O.fmap(XYShape.toJs)}
|
||||
height
|
||||
|
|
|
@ -32,11 +32,20 @@ export class DistPlotD3 {
|
|||
xScaleLogBase: 10,
|
||||
|
||||
// Y
|
||||
minY: null,
|
||||
maxY: null,
|
||||
yScaleType: 'linear',
|
||||
yScaleTimeOptions: null,
|
||||
yScaleLogBase: 10,
|
||||
|
||||
xMinContinuousDomainFactor: 1,
|
||||
xMaxContinuousDomainFactor: 1,
|
||||
yMaxContinuousDomainFactor: 1,
|
||||
yMaxDiscreteDomainFactor: 1,
|
||||
showDistributionYAxis: false,
|
||||
|
||||
showDistributionYAxis: false,
|
||||
showDistributionLines: true,
|
||||
|
||||
areaColors: ['#E1E5EC', '#E1E5EC'],
|
||||
verticalLine: 110,
|
||||
showVerticalLine: true,
|
||||
|
@ -102,11 +111,18 @@ export class DistPlotD3 {
|
|||
if (!['log', 'linear'].includes(this.attrs.xScaleType)) {
|
||||
throw new Error('X-scale type should be either "log" or "linear".');
|
||||
}
|
||||
if (!['log', 'linear'].includes(this.attrs.yScaleType)) {
|
||||
throw new Error('Y-scale type should be either "log" or "linear".');
|
||||
}
|
||||
|
||||
// Log Scale.
|
||||
if (this.attrs.xScaleType === 'log') {
|
||||
this.logFilter('continuous');
|
||||
this.logFilter('discrete');
|
||||
this.logFilter('continuous', (x, y) => x > 0);
|
||||
this.logFilter('discrete', (x, y) => x > 0);
|
||||
}
|
||||
if (this.attrs.yScaleType === 'log') {
|
||||
this.logFilter('continuous', (x, y) => y > 0);
|
||||
this.logFilter('discrete', (x, y) => y > 0);
|
||||
}
|
||||
if (
|
||||
this.attrs.xScaleType === 'log'
|
||||
|
@ -116,6 +132,14 @@ export class DistPlotD3 {
|
|||
console.warn('minX should be positive.');
|
||||
this.attrs.minX = undefined;
|
||||
}
|
||||
if (
|
||||
this.attrs.yScaleType === 'log'
|
||||
&& this.attrs.minY !== null
|
||||
&& this.attrs.minY < 0
|
||||
) {
|
||||
console.warn('minY should be positive.');
|
||||
this.attrs.minY = undefined;
|
||||
}
|
||||
|
||||
// Fields.
|
||||
const fields = [
|
||||
|
@ -124,7 +148,7 @@ export class DistPlotD3 {
|
|||
'svgWidth', 'svgHeight',
|
||||
'yMaxContinuousDomainFactor',
|
||||
'yMaxDiscreteDomainFactor',
|
||||
'xScaleLogBase',
|
||||
'xScaleLogBase', 'yScaleLogBase',
|
||||
];
|
||||
for (const field of fields) {
|
||||
if (!_.isNumber(this.attrs[field])) {
|
||||
|
@ -212,10 +236,14 @@ export class DistPlotD3 {
|
|||
if (!_.isFinite(yMax)) throw new Error('yMax is undefined');
|
||||
|
||||
// X-domains.
|
||||
const xMinDomainFactor = _.get(this.attrs, 'xMinContinuousDomainFactor', 1);
|
||||
const xMaxDomainFactor = _.get(this.attrs, 'xMaxContinuousDomainFactor', 1);
|
||||
const yMinDomainFactor = _.get(this.attrs, 'yMinContinuousDomainFactor', 1);
|
||||
const yMaxDomainFactor = _.get(this.attrs, 'yMaxContinuousDomainFactor', 1);
|
||||
const xMinDomain = xMin;
|
||||
const xMaxDomain = xMax;
|
||||
const yMinDomain = yMin;
|
||||
|
||||
const xMinDomain = xMin * xMinDomainFactor;
|
||||
const xMaxDomain = xMax * xMaxDomainFactor;
|
||||
const yMinDomain = yMin * yMinDomainFactor;
|
||||
const yMaxDomain = yMax * yMaxDomainFactor;
|
||||
|
||||
// X-scale.
|
||||
|
@ -229,9 +257,14 @@ export class DistPlotD3 {
|
|||
.range([0, this.calc.chartWidth]);
|
||||
|
||||
// Y-scale.
|
||||
const yScale = d3.scaleLinear()
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0]);
|
||||
const yScale = this.attrs.yScaleType === 'linear'
|
||||
? d3.scaleLinear()
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0])
|
||||
: d3.scaleLog()
|
||||
.base(this.attrs.yScaleLogBase)
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0]);
|
||||
|
||||
return {
|
||||
xMin, xMax,
|
||||
|
@ -394,7 +427,7 @@ export class DistPlotD3 {
|
|||
addLollipopsChart(common) {
|
||||
const data = this.getDataPoints('discrete');
|
||||
|
||||
const _yMin = d3.min(this.attrs.data.discrete.ys);
|
||||
const yMin = d3.min(this.attrs.data.discrete.ys);
|
||||
const yMax = d3.max(this.attrs.data.discrete.ys);
|
||||
|
||||
// X axis.
|
||||
|
@ -404,15 +437,22 @@ export class DistPlotD3 {
|
|||
.call(d3.axisBottom(common.xScale));
|
||||
|
||||
// Y-domain.
|
||||
const yMinDomainFactor = _.get(this.attrs, 'yMinDiscreteDomainFactor', 1);
|
||||
const yMaxDomainFactor = _.get(this.attrs, 'yMaxDiscreteDomainFactor', 1);
|
||||
const yMinDomain = 0;
|
||||
const yMinDomain = 0 * yMinDomainFactor;
|
||||
const yMaxDomain = yMax * yMaxDomainFactor;
|
||||
|
||||
// Y-scale.
|
||||
const yScale = d3.scaleLinear()
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0]);
|
||||
const yScale = this.attrs.yScaleType === 'linear'
|
||||
? d3.scaleLinear()
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0])
|
||||
: d3.scaleLog()
|
||||
.base(this.attrs.yScaleLogBase)
|
||||
.domain([yMinDomain, yMaxDomain])
|
||||
.range([this.calc.chartHeight, 0]);
|
||||
|
||||
//
|
||||
const yTicks = Math.floor(this.calc.chartHeight / 20);
|
||||
const yAxis = d3.axisLeft(yScale).ticks(yTicks);
|
||||
|
||||
|
@ -554,7 +594,7 @@ export class DistPlotD3 {
|
|||
* @param {string} key
|
||||
* @returns {{x: number[], y: number[]}}
|
||||
*/
|
||||
logFilter(key) {
|
||||
logFilter(key, pred) {
|
||||
const xs = [];
|
||||
const ys = [];
|
||||
const emptyShape = { xs: [], ys: [] };
|
||||
|
@ -563,7 +603,7 @@ export class DistPlotD3 {
|
|||
for (let i = 0, len = data.xs.length; i < len; i++) {
|
||||
const x = data.xs[i];
|
||||
const y = data.ys[i];
|
||||
if (x > 0) {
|
||||
if (pred(x, y)) {
|
||||
xs.push(x);
|
||||
ys.push(y);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ function getRandomInt(min, max) {
|
|||
function DistPlotReact(props) {
|
||||
const containerRef = React.createRef();
|
||||
const key = "cdf-chart-react-" + getRandomInt(0, 1000);
|
||||
const scale = props.scale || 'linear';
|
||||
const style = !!props.width ? { width: props.width + "px" } : {};
|
||||
|
||||
const [sized, { width }] = useSize(() => {
|
||||
|
@ -49,7 +48,8 @@ function DistPlotReact(props) {
|
|||
.set('verticalLine', props.verticalLine || 110)
|
||||
.set('showVerticalLine', props.showVerticalLine)
|
||||
.set('container', containerRef.current)
|
||||
.set('xScaleType', scale)
|
||||
.set('xScaleType', props.xScale || 'linear')
|
||||
.set('yScaleType', props.yScale || 'linear')
|
||||
.set('xScaleTimeOptions', props.timeScale)
|
||||
.set('yMaxContinuousDomainFactor', props.yMaxContinuousDomainFactor || 1)
|
||||
.set('yMaxDiscreteDomainFactor', props.yMaxDiscreteDomainFactor || 1)
|
||||
|
|
Loading…
Reference in New Issue
Block a user