d3-array#min JavaScript Examples
The following examples show how to use
d3-array#min.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: render.js From the-eye-knows-the-garbage with MIT License | 6 votes |
// Creates a hexjson grid with the layout and dimensions of the given hexjson
export function getGridForHexJSON (hexjson) {
// Create a new HexJSON object for the grid
var grid = {};
grid.layout = hexjson.layout;
grid.hexes = {};
// Get the hex objects from the hexjson as an array
var hexes = [];
Object.keys(hexjson.hexes).forEach(function (key) {
hexes.push(hexjson.hexes[key]);
});
// Calculate the number of rows and columns in the grid
var qmax = max(hexes, function (d) { return +d.q }),
qmin = min(hexes, function (d) { return +d.q }),
rmax = max(hexes, function (d) { return +d.r }),
rmin = min(hexes, function (d) { return +d.r });
// Create the hexjson grid
var i, j, fkey;
for (i = qmin; i <= qmax; i++) {
for (j = rmin; j <= rmax; j++) {
fkey = "Q" + i + "R" + j;
grid.hexes[fkey] = {q: i, r: j};
}
}
return grid;
}
Example #2
Source File: render.js From the-eye-knows-the-garbage with MIT License | 5 votes |
// Main render method
export function renderHexJSON (hexjson, width, height) {
// Get the layout
var layout = hexjson.layout;
// Get the hex objects as an array
var hexes = [];
var hexRadius = 0;
Object.keys(hexjson.hexes).forEach(function (key) {
hexjson.hexes[key].key = key;
hexes.push(hexjson.hexes[key]);
});
// Calculate the number of rows and columns
var qmax = max(hexes, function (d) { return +d.q }),
qmin = min(hexes, function (d) { return +d.q }),
rmax = max(hexes, function (d) { return +d.r }),
rmin = min(hexes, function (d) { return +d.r });
var qnum = qmax - qmin + 1,
rnum = rmax - rmin + 1;
// Calculate maximum radius the hexagons can have to fit the svg
if (layout === "odd-r" || layout === "even-r") {
hexRadius = min([(width) / ((qnum + 0.5) * Math.sqrt(3)),
height / ((rnum + 1 / 3) * 1.5)]);
} else {
hexRadius = min([(height) / ((rnum + 0.5) * Math.sqrt(3)),
width / ((qnum + 1 / 3) * 1.5)]);
}
// Calculate the hexagon width
var hexWidth = hexRadius * Math.sqrt(3);
// Get the vertices and points for this layout
var vertices = getVertices(layout, hexWidth, hexRadius);
var points = getPoints(vertices);
// Calculate the values needed to render each hex and add to hexes
hexes.forEach(function (hex) {
// Calculate the absolute co-ordinates of each hex
hex.qc = hex.q - qmin;
hex.rc = rmax - hex.r;
// Calculate the x and y position of each hex for this svg
hex.x = getX(hex, layout, hexWidth, hexRadius);
hex.y = getY(hex, layout, hexWidth, hexRadius);
// Add the vertex positions and points relative to x and y
hex.vertices = vertices;
hex.points = points;
});
return hexes;
}
Example #3
Source File: render.js From the-eye-knows-the-garbage with MIT License | 5 votes |
// Creates a list of dots along the boundaries between
// hexes which have different values of "field"
export function getBoundaryDotsForHexJSON (hexjson, width, height, field) {
// Get the hex objects from the hexjson as an array
var hexes = [];
const layout = hexjson.layout;
Object.keys(hexjson.hexes).forEach(function (key) {
hexes.push(hexjson.hexes[key]);
});
// Calculate the number of rows and columns
var qmax = max(hexes, function (d) { return +d.q }),
qmin = min(hexes, function (d) { return +d.q }),
rmax = max(hexes, function (d) { return +d.r }),
rmin = min(hexes, function (d) { return +d.r });
var qnum = qmax - qmin + 1,
rnum = rmax - rmin + 1;
var hexRadius;
// Calculate maximum radius the hexagons can have to fit the svg
if (layout === "odd-r" || layout === "even-r") {
hexRadius = min([(width) / ((qnum + 0.5) * Math.sqrt(3)),
height / ((rnum + 1 / 3) * 1.5)]);
} else {
hexRadius = min([(height) / ((rnum + 0.5) * Math.sqrt(3)),
width / ((qnum + 1 / 3) * 1.5)]);
}
// Calculate the hexagon width
var hexWidth = hexRadius * Math.sqrt(3);
// Create an array into which we will put points along the
// boundaries between differing hexes.
// Each edge has five points, equally spaced.
var lines = [];
const hexRadiusSquared = hexRadius * hexRadius * 4;
const maxHex = hexes.length;
if (maxHex > 1) {
hexes.forEach(function (hex) {
hex.qc = hex.q - qmin;
hex.rc = rmax - hex.r;
// Calculate the x and y position of each hex for this svg
hex.x = getX(hex, layout, hexWidth, hexRadius);
hex.y = getY(hex, layout, hexWidth, hexRadius);
});
for (var i = 0; i < maxHex - 1; i++) {
for (var j = i + 1; j < maxHex; j++) {
var hex = hexes[i];
var otherHex = hexes[j];
if (hex[field] !== otherHex[field]) {
if (Math.abs(hex.q - otherHex.q) <= 1 &&
Math.abs(hex.r - otherHex.r) <= 1) {
if (((hex.x - otherHex.x) * (hex.x - otherHex.x)) +
((hex.y - otherHex.y) * (hex.y - otherHex.y)) < hexRadiusSquared) {
// They're neighbours
var midpoint = {};
midpoint.x = otherHex.x + (hex.x - otherHex.x) / 2;
midpoint.y = otherHex.y + (hex.y - otherHex.y) / 2;
var perp = {};
const denom = Math.sqrt(3) * 4;
perp.dx = (hex.y - otherHex.y) / denom;
perp.dy = -(hex.x - otherHex.x) / denom;
lines.push({x: midpoint.x - 2 * perp.dx, y: midpoint.y - 2 * perp.dy});
lines.push({x: midpoint.x - perp.dx, y: midpoint.y - perp.dy});
lines.push({x: midpoint.x, y: midpoint.y});
lines.push({x: midpoint.x + perp.dx, y: midpoint.y + perp.dy});
lines.push({x: midpoint.x + 2 * perp.dx, y: midpoint.y + 2 * perp.dy});
}
}
}
}
}
}
return lines;
}
Example #4
Source File: align.js From the-eye-knows-the-garbage with MIT License | 5 votes |
export function center(node) {
return node.targetLinks.length ? node.depth
: node.sourceLinks.length ? min(node.sourceLinks, targetDepth) - 1
: 0;
}
Example #5
Source File: TimeseriesBrush.js From covid19india-react with MIT License | 4 votes |
function TimeseriesBrush({
timeseries,
dates,
currentBrushSelection,
endDate,
lookback,
setBrushSelectionEnd,
setLookback,
animationIndex,
}) {
const chartRef = useRef();
const [wrapperRef, {width, height}] = useMeasure();
const endDateMin =
lookback !== null
? min([
formatISO(addDays(parseIndiaDate(dates[0]), lookback), {
representation: 'date',
}),
endDate,
])
: endDate;
const xScale = useMemo(() => {
const T = dates.length;
// Chart extremes
const chartRight = width - margin.right;
return scaleTime()
.clamp(true)
.domain([
parseIndiaDate(dates[0] || endDate),
parseIndiaDate(dates[T - 1] || endDate),
])
.range([margin.left, chartRight]);
}, [width, endDate, dates]);
useEffect(() => {
if (!width || !height) return;
// Chart extremes
const chartBottom = height - margin.bottom;
const xAxis = (g) =>
g
.attr('class', 'x-axis')
.call(axisBottom(xScale).ticks(numTicksX(width)));
// Switched to daily confirmed instead of cumulative ARD
const timeseriesStacked = stack()
.keys(BRUSH_STATISTICS)
.value((date, statistic) =>
Math.max(0, getStatistic(timeseries[date], 'delta', statistic))
)(dates);
const yScale = scaleLinear()
.clamp(true)
.domain([
0,
max(
timeseriesStacked[timeseriesStacked.length - 1],
([, y1]) => yBufferTop * y1
),
])
.range([chartBottom, margin.top]);
const svg = select(chartRef.current);
const t = svg.transition().duration(D3_TRANSITION_DURATION);
svg
.select('.x-axis')
.attr('pointer-events', 'none')
.style('transform', `translate3d(0, ${chartBottom}px, 0)`)
.transition(t)
.call(xAxis);
const areaPath = area()
.curve(curveMonotoneX)
.x((d) => xScale(parseIndiaDate(d.data)))
.y0((d) => yScale(d[0]))
.y1((d) => yScale(d[1]));
svg
.select('.trend-areas')
.selectAll('.trend-area')
.data(timeseriesStacked)
.join(
(enter) =>
enter
.append('path')
.attr('class', 'trend-area')
.attr('fill', ({key}) => STATISTIC_CONFIGS[key].color)
.attr('fill-opacity', 0.4)
.attr('stroke', ({key}) => STATISTIC_CONFIGS[key].color)
.attr('d', areaPath)
.attr('pointer-events', 'none'),
(update) =>
update
.transition(t)
.attrTween('d', function (date) {
const previous = select(this).attr('d');
const current = areaPath(date);
return interpolatePath(previous, current);
})
.selection()
);
}, [dates, width, height, xScale, timeseries]);
const defaultSelection = currentBrushSelection.map((date) =>
xScale(parseIndiaDate(date))
);
const brush = useMemo(() => {
if (!width || !height) return;
// Chart extremes
const chartRight = width - margin.right;
const chartBottom = height - margin.bottom;
const brush = brushX()
.extent([
[margin.left, margin.top],
[chartRight, chartBottom],
])
.handleSize(20);
return brush;
}, [width, height]);
const brushed = useCallback(
({sourceEvent, selection}) => {
if (!sourceEvent) return;
const [brushStartDate, brushEndDate] = selection.map(xScale.invert);
ReactDOM.unstable_batchedUpdates(() => {
setBrushSelectionEnd(formatISO(brushEndDate, {representation: 'date'}));
setLookback(differenceInDays(brushEndDate, brushStartDate));
});
},
[xScale, setBrushSelectionEnd, setLookback]
);
const beforebrushstarted = useCallback(
(event) => {
const svg = select(chartRef.current);
const selection = brushSelection(svg.select('.brush').node());
if (!selection) return;
const dx = selection[1] - selection[0];
const [[cx]] = pointers(event);
const [x0, x1] = [cx - dx / 2, cx + dx / 2];
const [X0, X1] = xScale.range();
svg
.select('.brush')
.call(
brush.move,
x1 > X1 ? [X1 - dx, X1] : x0 < X0 ? [X0, X0 + dx] : [x0, x1]
);
},
[brush, xScale]
);
const brushended = useCallback(
({sourceEvent, selection}) => {
if (!sourceEvent || !selection) return;
const domain = selection
.map(xScale.invert)
.map((date) => formatISO(date, {representation: 'date'}));
const svg = select(chartRef.current);
svg
.select('.brush')
.call(
brush.move,
domain.map((date) => xScale(parseIndiaDate(date)))
)
.call((g) => g.select('.overlay').attr('cursor', 'pointer'));
},
[brush, xScale]
);
useEffect(() => {
if (!brush) return;
brush.on('start brush', brushed).on('end', brushended);
const svg = select(chartRef.current);
svg
.select('.brush')
.call(brush)
.call((g) =>
g
.select('.overlay')
.attr('cursor', 'pointer')
.datum({type: 'selection'})
.on('mousedown touchstart', beforebrushstarted)
);
}, [brush, brushed, brushended, beforebrushstarted]);
useEffect(() => {
if (!brush) return;
const svg = select(chartRef.current);
svg.select('.brush').call(brush.move, defaultSelection);
}, [brush, defaultSelection]);
const handleWheel = (event) => {
if (event.deltaX) {
setBrushSelectionEnd(
max([
endDateMin,
dates[
Math.max(
0,
Math.min(
dates.length - 1,
dates.indexOf(currentBrushSelection[1]) +
Math.sign(event.deltaX) * brushWheelDelta
)
)
],
])
);
}
};
return (
<div className="Timeseries">
<div
className={classnames('svg-parent is-brush fadeInUp')}
ref={wrapperRef}
onWheel={handleWheel}
style={{animationDelay: `${animationIndex * 250}ms`}}
>
<svg ref={chartRef} preserveAspectRatio="xMidYMid meet">
<defs>
<clipPath id="clipPath">
<rect
x={0}
y={`${margin.top}`}
width={width}
height={`${Math.max(0, height - margin.bottom)}`}
/>
</clipPath>
<mask id="mask">
<rect
x={0}
y={`${margin.top}`}
width={width}
height={`${Math.max(0, height - margin.bottom)}`}
fill="hsl(0, 0%, 40%)"
/>
<use href="#selection" fill="white" />
</mask>
</defs>
<g className="brush" clipPath="url(#clipPath)">
<g mask="url(#mask)">
<rect className="overlay" />
<g className="trend-areas" />
<rect className="selection" id="selection" />
</g>
</g>
<g className="x-axis" />
</svg>
</div>
</div>
);
}
Example #6
Source File: TimeseriesExplorer.js From covid19india-react with MIT License | 4 votes |
function TimeseriesExplorer({
stateCode,
timeseries,
date: timelineDate,
regionHighlighted,
setRegionHighlighted,
anchor,
setAnchor,
expandTable = false,
hideVaccinated = false,
noRegionHighlightedDistrictData,
}) {
const {t} = useTranslation();
const [lookback, setLookback] = useLocalStorage('timeseriesLookbackDays', 90);
const [chartType, setChartType] = useLocalStorage('chartType', 'delta');
const [isUniform, setIsUniform] = useLocalStorage('isUniform', false);
const [isLog, setIsLog] = useLocalStorage('isLog', false);
const [isMovingAverage, setIsMovingAverage] = useLocalStorage(
'isMovingAverage',
false
);
const stateCodeDateRange = Object.keys(timeseries?.[stateCode]?.dates || {});
const beginningDate =
stateCodeDateRange[0] || timelineDate || getIndiaDateYesterdayISO();
const endDate = min([
stateCodeDateRange[stateCodeDateRange.length - 1],
timelineDate || getIndiaDateYesterdayISO(),
]);
const [brushSelectionEnd, setBrushSelectionEnd] = useState(endDate);
useEffect(() => {
setBrushSelectionEnd(endDate);
}, [endDate]);
const brushSelectionStart =
lookback !== null
? formatISO(subDays(parseIndiaDate(brushSelectionEnd), lookback), {
representation: 'date',
})
: beginningDate;
const explorerElement = useRef();
const isVisible = useIsVisible(explorerElement, {once: true});
const {width} = useWindowSize();
const selectedRegion = useMemo(() => {
if (timeseries?.[regionHighlighted.stateCode]?.districts) {
return {
stateCode: regionHighlighted.stateCode,
districtName: regionHighlighted.districtName,
};
} else {
return {
stateCode: regionHighlighted.stateCode,
districtName: null,
};
}
}, [timeseries, regionHighlighted.stateCode, regionHighlighted.districtName]);
const selectedTimeseries = useMemo(() => {
if (selectedRegion.districtName) {
return timeseries?.[selectedRegion.stateCode]?.districts?.[
selectedRegion.districtName
]?.dates;
} else {
return timeseries?.[selectedRegion.stateCode]?.dates;
}
}, [timeseries, selectedRegion.stateCode, selectedRegion.districtName]);
const regions = useMemo(() => {
const states = Object.keys(timeseries || {})
.filter((code) => code !== stateCode)
.sort((code1, code2) =>
STATE_NAMES[code1].localeCompare(STATE_NAMES[code2])
)
.map((code) => {
return {
stateCode: code,
districtName: null,
};
});
const districts = Object.keys(timeseries || {}).reduce((acc1, code) => {
return [
...acc1,
...Object.keys(timeseries?.[code]?.districts || {}).reduce(
(acc2, districtName) => {
return [
...acc2,
{
stateCode: code,
districtName: districtName,
},
];
},
[]
),
];
}, []);
return [
{
stateCode: stateCode,
districtName: null,
},
...states,
...districts,
];
}, [timeseries, stateCode]);
const dropdownRegions = useMemo(() => {
if (
regions.find(
(region) =>
region.stateCode === regionHighlighted.stateCode &&
region.districtName === regionHighlighted.districtName
)
)
return regions;
return [
...regions,
{
stateCode: regionHighlighted.stateCode,
districtName: regionHighlighted.districtName,
},
];
}, [regionHighlighted.stateCode, regionHighlighted.districtName, regions]);
const dates = useMemo(
() =>
Object.keys(selectedTimeseries || {}).filter((date) => date <= endDate),
[selectedTimeseries, endDate]
);
const brushSelectionDates = useMemo(
() =>
dates.filter(
(date) => brushSelectionStart <= date && date <= brushSelectionEnd
),
[dates, brushSelectionStart, brushSelectionEnd]
);
const handleChange = useCallback(
({target}) => {
setRegionHighlighted(JSON.parse(target.value));
},
[setRegionHighlighted]
);
const resetDropdown = useCallback(() => {
setRegionHighlighted({
stateCode: stateCode,
districtName: null,
});
}, [stateCode, setRegionHighlighted]);
const statistics = useMemo(
() =>
TIMESERIES_STATISTICS.filter(
(statistic) =>
(!(STATISTIC_CONFIGS[statistic]?.category === 'vaccinated') ||
!hideVaccinated) &&
// (chartType === 'total' || statistic !== 'active') &&
(chartType === 'delta' || statistic !== 'tpr')
),
[chartType, hideVaccinated]
);
return (
<div
className={classnames(
'TimeseriesExplorer fadeInUp',
{
stickied: anchor === 'timeseries',
},
{expanded: expandTable}
)}
style={{
display:
anchor && anchor !== 'timeseries' && (!expandTable || width < 769)
? 'none'
: '',
}}
ref={explorerElement}
>
<div className="timeseries-header">
<div
className={classnames('anchor', 'fadeInUp', {
stickied: anchor === 'timeseries',
})}
style={{
display: expandTable && width >= 769 ? 'none' : '',
}}
onClick={
setAnchor &&
setAnchor.bind(this, anchor === 'timeseries' ? null : 'timeseries')
}
>
<PinIcon />
</div>
<h1>{t('Spread Trends')}</h1>
<div className="tabs">
{Object.entries(TIMESERIES_CHART_TYPES).map(
([ctype, value], index) => (
<div
className={`tab ${chartType === ctype ? 'focused' : ''}`}
key={ctype}
onClick={setChartType.bind(this, ctype)}
>
<h4>{t(value)}</h4>
</div>
)
)}
</div>
<div className="timeseries-options">
<div className="scale-modes">
<label className="main">{`${t('Scale Modes')}:`}</label>
<div className="timeseries-mode">
<label htmlFor="timeseries-mode">{t('Uniform')}</label>
<input
id="timeseries-mode"
type="checkbox"
className="switch"
checked={isUniform}
aria-label={t('Checked by default to scale uniformly.')}
onChange={setIsUniform.bind(this, !isUniform)}
/>
</div>
<div
className={`timeseries-mode ${
chartType !== 'total' ? 'disabled' : ''
}`}
>
<label htmlFor="timeseries-logmode">{t('Logarithmic')}</label>
<input
id="timeseries-logmode"
type="checkbox"
checked={chartType === 'total' && isLog}
className="switch"
disabled={chartType !== 'total'}
onChange={setIsLog.bind(this, !isLog)}
/>
</div>
</div>
<div
className={`timeseries-mode ${
chartType === 'total' ? 'disabled' : ''
} moving-average`}
>
<label htmlFor="timeseries-moving-average">
{t('7 day Moving Average')}
</label>
<input
id="timeseries-moving-average"
type="checkbox"
checked={chartType === 'delta' && isMovingAverage}
className="switch"
disabled={chartType !== 'delta'}
onChange={setIsMovingAverage.bind(this, !isMovingAverage)}
/>
</div>
</div>
</div>
{dropdownRegions && (
<div className="state-selection">
<div className="dropdown">
<select
value={JSON.stringify(selectedRegion)}
onChange={handleChange}
>
{dropdownRegions
.filter(
(region) =>
STATE_NAMES[region.stateCode] !== region.districtName
)
.map((region) => {
return (
<option
value={JSON.stringify(region)}
key={`${region.stateCode}-${region.districtName}`}
>
{region.districtName
? t(region.districtName)
: t(STATE_NAMES[region.stateCode])}
</option>
);
})}
</select>
</div>
<div className="reset-icon" onClick={resetDropdown}>
<ReplyIcon />
</div>
</div>
)}
{isVisible && (
<Suspense fallback={<TimeseriesLoader />}>
<Timeseries
timeseries={selectedTimeseries}
regionHighlighted={selectedRegion}
dates={brushSelectionDates}
{...{
statistics,
endDate,
chartType,
isUniform,
isLog,
isMovingAverage,
noRegionHighlightedDistrictData,
}}
/>
<TimeseriesBrush
timeseries={selectedTimeseries}
regionHighlighted={selectedRegion}
currentBrushSelection={[brushSelectionStart, brushSelectionEnd]}
animationIndex={statistics.length}
{...{dates, endDate, lookback, setBrushSelectionEnd, setLookback}}
/>
</Suspense>
)}
{!isVisible && <div style={{height: '50rem'}} />}
<div
className="pills fadeInUp"
style={{animationDelay: `${(1 + statistics.length) * 250}ms`}}
>
{TIMESERIES_LOOKBACK_DAYS.map((numDays) => (
<button
key={numDays}
type="button"
className={classnames({
selected: numDays === lookback,
})}
onClick={setLookback.bind(this, numDays)}
>
{numDays !== null ? `${numDays} ${t('days')}` : t('Beginning')}
</button>
))}
</div>
</div>
);
}
Example #7
Source File: CurvaturePlot.js From likelihood with MIT License | 4 votes |
CurvatureChart = props => {
const vizRef = useRef(null);
// Stuff
const margin = { top: 20, right: 20, bottom: 30, left: 50 };
const durationTime = 200;
const w = props.width - margin.left - margin.right;
const h = props.width * 0.5 - margin.top - margin.bottom;
const deriv = props.deriv;
const llThetaMLE = props.llThetaMLE;
const llThetaNull = props.llThetaNull;
const test = props.test;
const n = props.n;
const muNull = props.muNull;
// Axes min and max
var xMax, xMin, llTheta;
const sigmaTheta = Math.sqrt(props.sigma2Theta);
xMax = props.muTheta + sigmaTheta * 5;
xMin = props.muTheta - sigmaTheta * 5;
llTheta = 0;
const data1 = useMemo(
() =>
genEstLogLikCurve(
10,
props.muHat,
props.sigma2Hat,
props.muTheta,
props.sigma2Theta
),
[props.width, props.sigma2Hat, props.muHat]
);
const data2 = useMemo(
() =>
genEstLogLikCurve(
n,
props.muHat,
props.sigma2Hat,
props.muTheta,
props.sigma2Theta
),
[n, props.width, props.sigma2Hat, props.muHat]
);
const yMin = min(data1.y.filter(y => isFinite(y)));
const yMax = max(data1.y);
//const yMax = 0.05;
// Create scales
const yScale = scaleLinear()
.domain([yMin, yMax])
.range([h, 0]);
const xScale = scaleLinear()
.domain([xMin, xMax])
.range([0, w]);
// Scales and Axis
const xAxis = axisBottom(xScale);
// Line function
const linex = line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
// Update
useEffect(() => {
createChart(durationTime);
}, [n, props.width]);
const createChart = () => {
const node = vizRef.current;
const gOuter = select(node).attr(
"transform",
"translate(" + margin.left + "," + margin.top + ")"
);
// x Axis
gOuter
.selectAll("g.xAxis")
.data([0])
.enter()
.append("g")
.attr("class", "xAxis");
select(node)
.select("g.xAxis")
.attr("transform", "translate(" + 0 + "," + h + ")")
.call(xAxis);
// x label
gOuter
.selectAll("#x-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("class", "x-label");
select(node)
.selectAll(".x-label")
.attr(
"transform",
"translate(" + w / 2 + " ," + (h + margin.bottom) + ")"
)
.text("μ");
// y label
gOuter
.selectAll("#y-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("id", "y-label");
select(node)
.selectAll("#y-label")
.attr("transform", "rotate(-90)")
.attr("text-anchor", "middle")
.attr("x", -(h / 2))
.attr("y", -40)
.text("Log-Likelihood");
};
const delta = xMax - xMin;
return (
<svg width={props.width} height={props.width * 0.5}>
<g id="outer" ref={vizRef}>
<g className="viz" clipPath="url(#clip)">
<path d={linex(data1.data)} id="logLikReferenceCurve" />
<path d={linex(data2.data)} id="logLikNCurve" />
<line
className={clsx("LRT", test == "LRT" && "highlight")}
x1={xScale(xMin)}
x2={xScale(xMax)}
y1={yScale(llThetaMLE)}
y2={yScale(llThetaMLE)}
/>
<line
className={clsx("LRT", test == "LRT" && "highlight")}
x1={xScale(xMin)}
x2={xScale(xMax)}
y1={yScale(llThetaNull)}
y2={yScale(llThetaNull)}
/>
<line
className={clsx("wald", test == "wald" && "highlight")}
x1={xScale(props.muHat)}
x2={xScale(props.muHat)}
y1={yScale(yMin)}
y2={yScale(yMax)}
/>
<circle
cx={xScale(muNull)}
cy={yScale(llThetaNull)}
r="5"
fill="red"
className="testPointMuNull"
/>
<circle
cx={xScale(props.muHat)}
cy={yScale(llTheta)}
r="5"
className="testPointMu"
/>
</g>
<line
className={clsx("wald", test == "wald" && "highlight")}
x1={xScale(props.muNull)}
x2={xScale(props.muNull)}
y1={yScale(yMin)}
y2={yScale(yMax)}
/>
<line
className={clsx("score", test == "score" && "highlight")}
x1={xScale(props.muNull - delta)}
x2={xScale(props.muNull + delta)}
y1={yScale(llThetaNull - delta * deriv)}
y2={yScale(llThetaNull + delta * deriv)}
/>
</g>
<defs>
<clipPath id="clip">
<rect id="clip-rect" x="0" y="-10" width={w} height={h + 10} />
</clipPath>
</defs>
</svg>
);
}
Example #8
Source File: render.js From the-eye-knows-the-garbage with MIT License | 4 votes |
// Creates a list of line segments along the boundaries
// between hexes which have different values of "field"
export function getBoundarySegmentsForHexJSON (hexjson, width, height, field) {
// Get the hex objects from the hexjson as an array
var hexes = [];
const layout = hexjson.layout;
Object.keys(hexjson.hexes).forEach(function (key) {
hexes.push(hexjson.hexes[key]);
});
// Calculate the number of rows and columns
var qmax = max(hexes, function (d) { return +d.q }),
qmin = min(hexes, function (d) { return +d.q }),
rmax = max(hexes, function (d) { return +d.r }),
rmin = min(hexes, function (d) { return +d.r });
var qnum = qmax - qmin + 1,
rnum = rmax - rmin + 1;
var hexRadius;
// Calculate maximum radius the hexagons can have to fit the svg
if (layout === "odd-r" || layout === "even-r") {
hexRadius = min([(width) / ((qnum + 0.5) * Math.sqrt(3)),
height / ((rnum + 1 / 3) * 1.5)]);
} else {
hexRadius = min([(height) / ((rnum + 0.5) * Math.sqrt(3)),
width / ((qnum + 1 / 3) * 1.5)]);
}
// Calculate the hexagon width
var hexWidth = hexRadius * Math.sqrt(3);
// Create an array into which we will put points along the
// boundaries between differing hexes.
// Each segment will be of the form
// {x: <start point X>, y: <start point Y>, cx: <difference X>, cy: <difference Y> }
// intended to be used with the simple line drawing functionality of d3
//
var segments = [];
const hexRadiusSquared = hexRadius * hexRadius * 4;
const maxHex = hexes.length;
if (maxHex > 1) {
hexes.forEach(function (hex) {
hex.qc = hex.q - qmin;
hex.rc = rmax - hex.r;
// Calculate the x and y position of each hex for this svg
hex.x = getX(hex, layout, hexWidth, hexRadius);
hex.y = getY(hex, layout, hexWidth, hexRadius);
});
for (var i = 0; i < maxHex - 1; i++) {
for (var j = i + 1; j < maxHex; j++) {
var hex = hexes[i];
var otherHex = hexes[j];
if (hex[field] !== otherHex[field]) {
if (Math.abs(hex.q - otherHex.q) <= 1 &&
Math.abs(hex.r - otherHex.r) <= 1) {
if (((hex.x - otherHex.x) * (hex.x - otherHex.x)) +
((hex.y - otherHex.y) * (hex.y - otherHex.y)) < hexRadiusSquared) {
// They're neighbours
var midpoint = {};
midpoint.x = otherHex.x + (hex.x - otherHex.x) / 2;
midpoint.y = otherHex.y + (hex.y - otherHex.y) / 2;
var perp = {};
var direction = +1;
if (hex[field] < otherHex[field]) {
direction = -1;
} // otherwise, direction will be +1
const denom = Math.sqrt(3) * 2 * direction;
perp.dx = (hex.y - otherHex.y) / denom;
perp.dy = -(hex.x - otherHex.x) / denom;
segments.push({
x1: midpoint.x - perp.dx,
y1: midpoint.y - perp.dy,
x2: midpoint.x + perp.dx,
y2: midpoint.y + perp.dy});
}
}
}
}
}
}
return segments;
}
Example #9
Source File: sankey.js From the-eye-knows-the-garbage with MIT License | 4 votes |
export default function Sankey() {
var x0 = 0, y0 = 0, x1 = 1, y1 = 1, // extent
dx = 24, // nodeWidth
py = 8, // nodePadding
id = defaultId,
align = justify,
sort,
nodes = defaultNodes,
links = defaultLinks,
iterations = 6;
function sankey() {
var graph = {nodes: nodes.apply(null, arguments), links: links.apply(null, arguments)};
computeNodeLinks(graph);
computeNodeValues(graph);
computeNodeDepths(graph);
computeNodeBreadths(graph);
computeLinkBreadths(graph);
return graph;
}
sankey.update = function(graph) {
computeLinkBreadths(graph);
return graph;
};
sankey.nodeId = function(_) {
return arguments.length ? (id = typeof _ === "function" ? _ : constant(_), sankey) : id;
};
sankey.nodeAlign = function(_) {
return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align;
};
sankey.nodeSort = function(_) {
return arguments.length ? (sort = _, sankey) : sort;
};
sankey.nodeWidth = function(_) {
return arguments.length ? (dx = +_, sankey) : dx;
};
sankey.nodePadding = function(_) {
return arguments.length ? (py = +_, sankey) : py;
};
sankey.nodes = function(_) {
return arguments.length ? (nodes = typeof _ === "function" ? _ : constant(_), sankey) : nodes;
};
sankey.links = function(_) {
return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links;
};
sankey.size = function(_) {
return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], sankey) : [x1 - x0, y1 - y0];
};
sankey.extent = function(_) {
return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], sankey) : [[x0, y0], [x1, y1]];
};
sankey.iterations = function(_) {
return arguments.length ? (iterations = +_, sankey) : iterations;
};
// Populate the sourceLinks and targetLinks for each node.
// Also, if the source and target are not objects, assume they are indices.
function computeNodeLinks(graph) {
graph.nodes.forEach(function(node, i) {
node.index = i;
node.sourceLinks = [];
node.targetLinks = [];
});
var nodeById = map(graph.nodes, id);
graph.links.forEach(function(link, i) {
link.index = i;
var source = link.source, target = link.target;
if (typeof source !== "object") source = link.source = find(nodeById, source);
if (typeof target !== "object") target = link.target = find(nodeById, target);
source.sourceLinks.push(link);
target.targetLinks.push(link);
});
}
// Compute the value (size) of each node by summing the associated links.
function computeNodeValues(graph) {
graph.nodes.forEach(function(node) {
node.value = Math.max(
sum(node.sourceLinks, value),
sum(node.targetLinks, value)
);
});
}
// Iteratively assign the depth (x-position) for each node.
// Nodes are assigned the maximum depth of incoming neighbors plus one;
// nodes with no incoming links are assigned depth zero, while
// nodes with no outgoing links are assigned the maximum depth.
function computeNodeDepths(graph) {
var nodes, next, x, n = graph.nodes.length;
for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) {
if (x > n) throw new Error("circular link");
nodes.forEach(function(node) {
node.depth = x;
node.sourceLinks.forEach(function(link) {
if (next.indexOf(link.target) < 0) {
next.push(link.target);
}
});
});
}
for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) {
if (x > n) throw new Error("circular link");
nodes.forEach(function(node) {
node.height = x;
node.targetLinks.forEach(function(link) {
if (next.indexOf(link.source) < 0) {
next.push(link.source);
}
});
});
}
var kx = (x1 - x0 - dx) / (x - 1);
graph.nodes.forEach(function(node) {
node.x1 = (node.x0 = x0 + Math.max(0, Math.min(x - 1, Math.floor(align.call(null, node, x)))) * kx) + dx;
});
}
function computeNodeBreadths(graph) {
var columns = nest()
.key(function(d) { return d.x0; })
.sortKeys(ascending)
.entries(graph.nodes)
.map(function(d) { return d.values; });
//
initializeNodeBreadth();
resolveCollisions();
for (var alpha = 0.9, n = iterations; n > 0; --n, alpha *= 0.9) {
relaxRightToLeft(alpha);
resolveCollisions();
relaxLeftToRight(alpha);
resolveCollisions();
}
function initializeNodeBreadth() {
var ky = min(columns, function(nodes) {
return (y1 - y0 - (nodes.length - 1) * py) / sum(nodes, value);
});
columns.forEach(function(nodes) {
if (sort != null) nodes.sort(sort);
nodes.forEach(function(node, i) {
node.y1 = (node.y0 = i) + node.value * ky;
});
});
graph.links.forEach(function(link) {
link.width = link.value * ky;
});
}
function relaxLeftToRight(alpha) {
columns.forEach(function(nodes) {
nodes.forEach(function(node) {
let y = node.y0;
for (const {target, width, value} of node.sourceLinks.sort(ascendingTargetBreadth)) {
if (value > 0) {
let dy = 0;
for (const {source, width} of target.targetLinks) {
if (source === node) break;
dy += width + py / 2;
}
dy = (y - dy - target.y0) * alpha * (value / Math.min(node.value, target.value));
target.y0 += dy;
target.y1 += dy;
}
y += width + py / 2;
}
});
});
}
function relaxRightToLeft(alpha) {
columns.slice().reverse().forEach(function(nodes) {
nodes.forEach(function(node) {
let y = node.y0;
for (const {source, width, value} of node.targetLinks.sort(ascendingSourceBreadth)) {
if (value > 0) {
let dy = 0;
for (const {target, width} of source.sourceLinks) {
if (target === node) break;
dy += width + py / 2;
}
dy = (y - dy - source.y0) * alpha * (value / Math.min(node.value, source.value));
source.y0 += dy;
source.y1 += dy;
}
y += width + py / 2;
}
});
});
}
function resolveCollisions() {
columns.forEach(function(nodes) {
var node,
dy,
y = y0,
n = nodes.length,
i;
// Push any overlapping nodes down.
if (sort === undefined) nodes.sort(ascendingBreadth);
for (i = 0; i < n; ++i) {
node = nodes[i];
dy = y - node.y0;
if (dy > 0) node.y0 += dy, node.y1 += dy;
y = node.y1 + py;
}
// If the bottommost node goes outside the bounds, push it back up.
dy = y - py - y1;
if (dy > 0) {
y = (node.y0 -= dy), node.y1 -= dy;
// Push any overlapping nodes back up.
for (i = n - 2; i >= 0; --i) {
node = nodes[i];
dy = node.y1 + py - y;
if (dy > 0) node.y0 -= dy, node.y1 -= dy;
y = node.y0;
}
}
});
}
}
function computeLinkBreadths(graph) {
graph.nodes.forEach(function(node) {
node.sourceLinks.sort(ascendingTargetBreadth);
node.targetLinks.sort(ascendingSourceBreadth);
});
graph.nodes.forEach(function(node) {
var y0 = node.y0, y1 = y0;
node.sourceLinks.forEach(function(link) {
link.y0 = y0 + link.width / 2, y0 += link.width;
});
node.targetLinks.forEach(function(link) {
link.y1 = y1 + link.width / 2, y1 += link.width;
});
});
}
return sankey;
}