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 vote down vote up
// 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 vote down vote up
// 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 vote down vote up
// 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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
// 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 vote down vote up
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;
}