d3-array#range JavaScript Examples

The following examples show how to use d3-array#range. 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: utils.js    From likelihood with MIT License 7 votes vote down vote up
genEstLogLikCurve = (n, muHat, sigma2, muMLE, sigma2MLE) => {
  const sigmaMLE = Math.sqrt(sigma2MLE);
  const xStart = muMLE - 5 * sigmaMLE;
  const xEnd = muMLE + 5 * sigmaMLE;
  const x = range(xStart, xEnd, Math.abs(xStart - xEnd) / 50);
  const y = x.map(x => estimatedLogLik(n, muHat, x, sigma2));

  const tmp = [];
  for (var i = 0; i < x.length; i++) {
    tmp.push([x[i], y[i]]);
  }
  var data = {
    data: tmp,
    x: x,
    y: y
  };
  return data;
}
Example #2
Source File: healpix.js    From the-eye-knows-the-garbage with MIT License 6 votes vote down vote up
function sphere(step) {
  return {
    type: "Polygon",
    coordinates: [
      range(-180, 180 + step / 2, step).map(function(x, i) { return [x, i & 1 ? 90 - 1e-6 : healpixParallel]; })
      .concat(range(180, -180 - step / 2, -step).map(function(x, i) { return [x, i & 1 ? -90 + 1e-6 : -healpixParallel]; }))
    ]
  };
}
Example #3
Source File: ContourLogLik.js    From likelihood with MIT License 6 votes vote down vote up
createGrid = (muMin, muMax, sigma2Min, sigma2Max, sample) => {
  const n = 100,
    m = 100,
    values = new Array(n * m);

  const muStep = (muMax - muMin) / m;
  const sigmaStep = (sigma2Max - sigma2Min) / n;
  const mu = range(muMin, muMax, muStep);
  const sigma2 = range(sigma2Min, sigma2Max, sigmaStep);

  for (let j = 0, k = 0; j < m; ++j) {
    for (let i = 0; i < n; ++i, ++k) {
      values[k] = logLikSum(sample, mu[i], sigma2[j]);
    }
  }

  values.n = n;
  values.m = m;
  values.muStep = muStep;
  values.sigmaStep = sigmaStep;
  return values;
}
Example #4
Source File: Viz.js    From likelihood with MIT License 6 votes vote down vote up
genLogLikCurve = (d, mu, sigma2, theta, muTheta, sigma2Theta) => {
  var y;
  var x;
  const sigmaTheta = Math.sqrt(sigma2Theta);
  if (theta == "mu") {
    const xStart = muTheta - 5 * sigmaTheta;
    const xEnd = muTheta + 5 * sigmaTheta;
    x = range(xStart, xEnd, Math.abs(xStart - xEnd) / 50);
    y = x.map(x => logLikSum(d, x, sigma2));
  } else if (theta == "sigma") {
    let xStart = 1;
    const xEnd = Math.sqrt(1500);
    x = range(xStart, xEnd, (xEnd - xStart) / 50);
    x = x.map(d => d * d);
    y = x.map(x => logLikSum(d, mu, x));
  }
  const tmp = [];
  for (var i = 0; i < x.length; i++) {
    tmp.push([x[i], y[i]]);
  }
  var data = {
    data: tmp,
    x: x,
    y: y
  };
  return data;
}
Example #5
Source File: helpers.test.js    From hill-chart with MIT License 6 votes vote down vote up
describe('uId helper', () => {
  it('generates random IDs', () => {
    expect.hasAssertions();

    const data = range(1, 1000).map(() => uId());

    const isArrayUnique = (arr) =>
      Array.isArray(arr) && new Set(arr).size === arr.length;

    expect(isArrayUnique(data)).toBe(true);
  });
});
Example #6
Source File: patterns.js    From Turnip-Calculator with MIT License 6 votes vote down vote up
samplesReducer = (prev, current, i) => {
  let arr = prev;
  if (i === 1) {
    arr = Array.from({ length: 12 }, (v, i) => i);
    return arr.map((index) => {
      const [a, b] = prev[index];
      const [c, d] = current[index];
      const stepA = 0.1 * (1 / prev.probability);
      const stepB = 0.1 * (1 / current.probability);
      return range(a, b + 1, stepA).concat(range(c, d + 1, stepB));
    });
  } else {
    return prev.map((value, index) => {
      const [a, b] = current[index];
      const step = 0.1 * (1 / current.probability);
      return value.concat(range(a, b + 1, step));
    });
  }
}
Example #7
Source File: graticule.js    From gamedesign with GNU General Public License v3.0 5 votes vote down vote up
function graticuleY(x0, x1, dx) {
  var x = range(x0, x1 - epsilon, dx).concat(x1);
  return function(y) { return x.map(function(x) { return [x, y]; }); };
}
Example #8
Source File: graticule.js    From gamedesign with GNU General Public License v3.0 5 votes vote down vote up
function graticuleX(y0, y1, dy) {
  var y = range(y0, y1 - epsilon, dy).concat(y1);
  return function(x) { return y.map(function(y) { return [x, y]; }); };
}
Example #9
Source File: graticule.js    From cs-wiki with GNU General Public License v3.0 5 votes vote down vote up
function graticuleY(x0, x1, dx) {
  var x = range(x0, x1 - epsilon, dx).concat(x1);
  return function(y) { return x.map(function(x) { return [x, y]; }); };
}
Example #10
Source File: graticule.js    From cs-wiki with GNU General Public License v3.0 5 votes vote down vote up
function graticuleX(y0, y1, dy) {
  var y = range(y0, y1 - epsilon, dy).concat(y1);
  return function(x) { return y.map(function(y) { return [x, y]; }); };
}
Example #11
Source File: MapLegend.js    From covid19india-react with MIT License 4 votes vote down vote up
function legend({
  svg,
  color,
  title,
  tickSize = 6,
  width = 320,
  height = 44 + tickSize,
  marginTop = 18,
  marginRight = 0,
  marginBottom = 16 + tickSize,
  marginLeft = 0,
  ticks = width / 64,
  tickFormat,
  tickValues,
  ordinalWeights,
} = {}) {
  const t = svg.transition().duration(D3_TRANSITION_DURATION);

  let tickAdjust = (g) => {
    const ticks = g.selectAll('.tick line');
    ticks.attr('y1', marginTop + marginBottom - height);
    // select(ticks.nodes()[ticks.size() - 1]).remove();
  };
  let x;

  // Continuous
  if (color.interpolate) {
    const n = Math.min(color.domain().length, color.range().length);

    x = color
      .copy()
      .rangeRound(quantize(interpolate(marginLeft, width - marginRight), n));

    svg
      .select('.ramp')
      .attr('x', marginLeft)
      .attr('y', marginTop)
      .attr('width', width - marginLeft - marginRight)
      .attr('height', height - marginTop - marginBottom)
      .attr(
        'xlink:href',
        ramp(color.copy().domain(quantize(interpolate(0, 1), n))).toDataURL()
      );
  }

  // Sequential
  else if (color.interpolator) {
    svg
      .select('.bars')
      .selectAll('rect')
      .transition(t)
      .attr('opacity', 0)
      .remove();

    x = Object.assign(
      color
        .copy()
        .interpolator(interpolateRound(marginLeft, width - marginRight)),
      {
        range() {
          return [marginLeft, width - marginRight];
        },
      }
    );

    svg
      .select('.ramp')
      .attr('x', marginLeft)
      .attr('y', marginTop)
      .attr('width', width - marginLeft - marginRight)
      .attr('height', height - marginTop - marginBottom)
      .attr('xlink:href', ramp(color.interpolator()).toDataURL())
      .attr('display', 'visible')
      .transition(t)
      .attr('opacity', 1);

    // scaleSequentialQuantile doesn’t implement ticks or tickFormat.
    if (!x.ticks) {
      if (tickValues === undefined) {
        const n = Math.round(ticks + 1);
        tickValues = range(n).map((i) => quantile(color.domain(), i / (n - 1)));
      }
      if (typeof tickFormat !== 'function') {
        tickFormat = format(tickFormat === undefined ? ',f' : tickFormat);
      }
    }
  }

  // Threshold
  else if (color.invertExtent) {
    const thresholds = color.thresholds
      ? color.thresholds() // scaleQuantize
      : color.quantiles
      ? color.quantiles() // scaleQuantile
      : color.domain(); // scaleThreshold

    const thresholdFormat =
      tickFormat === undefined
        ? (d) => d
        : typeof tickFormat === 'string'
        ? format(tickFormat)
        : tickFormat;

    x = scaleLinear()
      .domain([-1, color.range().length - 1])
      .rangeRound([marginLeft, width - marginRight]);

    svg
      .append('g')
      .selectAll('rect')
      .data(color.range())
      .join('rect')
      .attr('x', (d, i) => x(i - 1))
      .attr('y', marginTop)
      .attr('width', (d, i) => x(i) - x(i - 1))
      .attr('height', height - marginTop - marginBottom)
      .attr('fill', (d) => d);

    tickValues = range(-1, thresholds.length);
    tickFormat = (i) => {
      if (i === -1) return thresholdFormat(1);
      else if (i === thresholds.length - 1) return;
      else if (i === thresholds.length - 2)
        return thresholdFormat(thresholds[i] + '+', i);
      return thresholdFormat(thresholds[i], i);
    };
  }

  // Ordinal
  else {
    svg
      .select('.ramp')
      .transition(t)
      .attr('opacity', 0)
      .attr('xlink:href', null);
    if (!ordinalWeights) {
      x = scaleBand()
        .domain(color.domain().filter((d) => d))
        .rangeRound([marginLeft, width - marginRight]);
      svg
        .select('.bars')
        .selectAll('rect')
        .data(color.domain().filter((d) => d))
        .join('rect')
        .attr('x', x)
        .attr('y', marginTop)
        .attr('width', Math.max(0, x.bandwidth() - 1))
        .attr('height', height - marginTop - marginBottom)
        .attr('fill', color);
    } else {
      const widthScale = scaleLinear()
        .domain([0, ordinalWeights.reduce((a, b) => a + b)])
        .rangeRound([0, width - marginLeft - marginRight]);

      const xPos = ordinalWeights.map((w, i) =>
        ordinalWeights
          .slice(0, i)
          .reduce((acc, w) => acc + widthScale(w), marginLeft)
      );

      x = scaleOrdinal().domain(color.domain()).range(xPos);

      svg
        .select('.bars')
        .selectAll('rect')
        .data(color.domain())
        .join((enter) =>
          enter
            .append('rect')
            .attr('x', x)
            .attr('width', (d, i) => widthScale(ordinalWeights[i]))
        )
        .attr('y', marginTop)
        .attr('height', height - marginTop - marginBottom)
        .attr('fill', color)
        .transition(t)
        .attr('x', x)
        .attr('width', (d, i) => widthScale(ordinalWeights[i]))
        .attr('opacity', 1);
    }

    tickAdjust = () => {};
  }

  svg
    .select('.axis')
    .attr('transform', `translate(0,${height - marginBottom})`)
    .transition(t)
    .attr('class', 'axis')
    .call(
      axisBottom(x)
        .ticks(ticks, typeof tickFormat === 'string' ? tickFormat : undefined)
        .tickFormat(typeof tickFormat === 'function' ? tickFormat : undefined)
        .tickSize(tickSize)
        .tickValues(tickValues)
    )
    .on('start', () => {
      svg.call(tickAdjust).call((svg) => svg.select('.domain').remove());
    })
    .call((g) =>
      g
        .select('.axistext')
        .attr('class', 'axistext')
        .attr('x', marginLeft)
        .attr('y', marginTop + marginBottom - height - 6)
        .attr('fill', 'currentColor')
        .attr('text-anchor', 'start')
        .attr('font-weight', 'bold')
        .text(title)
    );

  return svg.node();
}
Example #12
Source File: MapLegend.js    From covid19india-react with MIT License 4 votes vote down vote up
function MapLegend({data, statistic, mapViz, mapScale}) {
  const {t} = useTranslation();
  const svgLegendRef = useRef(null);
  const svgLegendChoroRef = useRef(null);
  const [wrapperRef, {width}] = useMeasure();

  useEffect(() => {
    const t = transition().duration(D3_TRANSITION_DURATION);

    if (mapViz !== MAP_VIZS.CHOROPLETH) {
      const svg = select(svgLegendChoroRef.current);
      svg
        .select('.ramp')
        .transition(t)
        .attr('opacity', 0)
        .attr('display', 'none')
        .attr('xlink:href', null);

      svg
        .select('.bars')
        .selectAll('rect')
        .transition(t)
        .attr('opacity', 0)
        .remove();
      svg.selectAll('.axis > *:not(.axistext)').remove();
      svg.select('.axistext').text('');
    }

    if (mapViz !== MAP_VIZS.BUBBLE) {
      const svg = select(svgLegendRef.current);
      svg
        .select('.circles')
        .selectAll('circle')
        .transition(t)
        .attr('r', 0)
        .attr('cy', 0)
        .remove();
      svg.selectAll('.circle-axis > *').remove();
    }

    if (mapViz !== MAP_VIZS.SPIKES) {
      const svg = select(svgLegendRef.current);
      svg
        .select('.spikes')
        .call((g) =>
          g.selectAll('path').transition(t).attr('d', spike(0)).remove()
        )
        .call((g) => g.selectAll('text').remove())
        .transition(t)
        .selectAll('g')
        .remove();
      svg.selectAll('.spike-axis > *').remove();
    }
  }, [mapViz]);

  useEffect(() => {
    if (!width) return;

    const statisticConfig = STATISTIC_CONFIGS[statistic];
    const zoom = width / MAP_DIMENSIONS[0];

    if (mapViz === MAP_VIZS.BUBBLE) {
      const svg = select(svgLegendRef.current);

      const [, domainMax] = mapScale.domain();

      const legend = svg
        .select('.circles')
        .attr('transform', `translate(48,40)`)
        .attr('text-anchor', 'middle');

      const legendRadius = [0.1, 0.4, 1].map((d) => d * domainMax);

      legend
        .selectAll('circle')
        .data(legendRadius)
        .join('circle')
        .attr('fill', 'none')
        .attr('stroke', statisticConfig.color + '70')
        .transition(t)
        .attr('cy', (d) => -mapScale(d))
        .attr('r', (d) => mapScale(d));

      const yScale = mapScale.copy().range([0, -2 * mapScale(domainMax)]);

      svg
        .select('.circle-axis')
        .attr('transform', `translate(48,50)`)
        .transition(t)
        .call(
          axisRight(yScale)
            .tickSize(0)
            .tickPadding(0)
            .tickValues(legendRadius)
            .tickFormat((num) =>
              formatNumber(
                num,
                statisticConfig.format === 'long'
                  ? 'short'
                  : statisticConfig.format
              )
            )
        )
        .selectAll('.tick text')
        .style('text-anchor', 'middle')
        .attr('font-size', 10 / zoom);

      svg.select('.circle-axis').call((g) => g.select('.domain').remove());
    } else if (mapViz === MAP_VIZS.SPIKE) {
      const svg = select(svgLegendRef.current);
      const ticks = mapScale.ticks(3).slice(1).reverse();

      const gap = 28 / zoom;

      svg
        .select('.spikes')
        .attr('transform', `translate(32,24)`)
        .selectAll('g')
        .data(ticks)
        .join((enter) =>
          enter.append('g').call((g) =>
            g
              .append('path')
              .attr('fill-opacity', 0.3)
              .attr('d', (d) => spike(0))
          )
        )
        .attr('transform', (d, i) => `translate(${i * gap},0)`)
        .call((g) =>
          g
            .select('path')
            .transition(t)
            .attr('d', (d) => spike(mapScale(d)))
            .attr('fill', statisticConfig.color + '70')
            .attr('stroke', statisticConfig.color + '70')
        );

      const xScale = mapScale.copy().range([gap * ticks.length, 0]);
      svg
        .select('.spike-axis')
        .attr('transform', `translate(32,32)`)
        .transition(t)
        .call(
          axisBottom(xScale)
            .tickSize(0)
            .tickPadding(0)
            .tickValues(ticks)
            .tickFormat((num) =>
              formatNumber(
                num,
                statisticConfig.format === 'long'
                  ? 'short'
                  : statisticConfig.format
              )
            )
        )
        .selectAll('.tick text')
        .style('text-anchor', 'middle')
        .attr('font-size', 10 / zoom);

      svg.select('.spike-axis').call((g) => g.select('.domain').remove());
    } else {
      const svg = select(svgLegendChoroRef.current);
      svg.call(() =>
        legend({
          svg: svg,
          color: mapScale,
          width: width,
          height: MAP_LEGEND_HEIGHT,
          ticks: 5,
          tickFormat: function (d, i, n) {
            if (statisticConfig?.mapConfig?.colorScale) {
              return d;
            } else if (mapViz === MAP_VIZS.CHOROPLETH && !Number.isInteger(d)) {
              return '';
            } else if (i === n.length - 1) {
              return formatNumber(d, statisticConfig.format) + '+';
            } else {
              return formatNumber(d, statisticConfig.format);
            }
          },
          marginLeft: 2,
          marginRight: 0,
        })
      );
      svg.attr('class', statisticConfig?.mapConfig?.colorScale ? 'zone' : '');
    }
  }, [t, width, statistic, mapScale, mapViz]);

  return (
    <div
      className="svg-parent maplegend"
      ref={wrapperRef}
      style={{height: 2 * MAP_LEGEND_HEIGHT}}
    >
      <svg
        id="legend"
        preserveAspectRatio="xMinYMid meet"
        ref={svgLegendRef}
        viewBox={`0 0 ${MAP_DIMENSIONS[0]} ${MAP_LEGEND_HEIGHT}`}
      >
        <g className="circles"></g>
        <g className="spikes"></g>
        <g className="circle-axis"></g>
        <g className="spike-axis"></g>
        <g className="axis">
          <text className="axistext" />
        </g>
      </svg>
      <svg
        id="legend-choro"
        preserveAspectRatio="xMinYMid meet"
        ref={svgLegendChoroRef}
      >
        <image className="ramp" preserveAspectRatio="none" />
        <g className="bars"></g>
        <g className="axis">
          <text className="axistext" />
        </g>
      </svg>
      <canvas
        className="color-scale"
        style={{position: 'absolute', height: 0}}
      />
    </div>
  );
}
Example #13
Source File: density.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export default function() {
  var x = defaultX,
      y = defaultY,
      weight = defaultWeight,
      dx = 960,
      dy = 500,
      r = 20, // blur radius
      k = 2, // log2(grid cell size)
      o = r * 3, // grid offset, to pad for blur
      n = (dx + o * 2) >> k, // grid width
      m = (dy + o * 2) >> k, // grid height
      threshold = constant(20);

  function density(data) {
    var values0 = new Float32Array(n * m),
        values1 = new Float32Array(n * m);

    data.forEach(function(d, i, data) {
      var xi = (+x(d, i, data) + o) >> k,
          yi = (+y(d, i, data) + o) >> k,
          wi = +weight(d, i, data);
      if (xi >= 0 && xi < n && yi >= 0 && yi < m) {
        values0[xi + yi * n] += wi;
      }
    });

    // TODO Optimize.
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);

    var tz = threshold(values0);

    // Convert number of thresholds into uniform thresholds.
    if (!Array.isArray(tz)) {
      var stop = max(values0);
      tz = tickStep(0, stop, tz);
      tz = range(0, Math.floor(stop / tz) * tz, tz);
      tz.shift();
    }

    return contours()
        .thresholds(tz)
        .size([n, m])
      (values0)
        .map(transform);
  }

  function transform(geometry) {
    geometry.value *= Math.pow(2, -2 * k); // Density in points per square pixel.
    geometry.coordinates.forEach(transformPolygon);
    return geometry;
  }

  function transformPolygon(coordinates) {
    coordinates.forEach(transformRing);
  }

  function transformRing(coordinates) {
    coordinates.forEach(transformPoint);
  }

  // TODO Optimize.
  function transformPoint(coordinates) {
    coordinates[0] = coordinates[0] * Math.pow(2, k) - o;
    coordinates[1] = coordinates[1] * Math.pow(2, k) - o;
  }

  function resize() {
    o = r * 3;
    n = (dx + o * 2) >> k;
    m = (dy + o * 2) >> k;
    return density;
  }

  density.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), density) : x;
  };

  density.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), density) : y;
  };

  density.weight = function(_) {
    return arguments.length ? (weight = typeof _ === "function" ? _ : constant(+_), density) : weight;
  };

  density.size = function(_) {
    if (!arguments.length) return [dx, dy];
    var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]);
    if (!(_0 >= 0) && !(_0 >= 0)) throw new Error("invalid size");
    return dx = _0, dy = _1, resize();
  };

  density.cellSize = function(_) {
    if (!arguments.length) return 1 << k;
    if (!((_ = +_) >= 1)) throw new Error("invalid cell size");
    return k = Math.floor(Math.log(_) / Math.LN2), resize();
  };

  density.thresholds = function(_) {
    return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), density) : threshold;
  };

  density.bandwidth = function(_) {
    if (!arguments.length) return Math.sqrt(r * (r + 1));
    if (!((_ = +_) >= 0)) throw new Error("invalid bandwidth");
    return r = Math.round((Math.sqrt(4 * _ * _ + 1) - 1) / 2), resize();
  };

  return density;
}
Example #14
Source File: density.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export default function() {
  var x = defaultX,
      y = defaultY,
      weight = defaultWeight,
      dx = 960,
      dy = 500,
      r = 20, // blur radius
      k = 2, // log2(grid cell size)
      o = r * 3, // grid offset, to pad for blur
      n = (dx + o * 2) >> k, // grid width
      m = (dy + o * 2) >> k, // grid height
      threshold = constant(20);

  function density(data) {
    var values0 = new Float32Array(n * m),
        values1 = new Float32Array(n * m),
        pow2k = Math.pow(2, -k);

    data.forEach(function(d, i, data) {
      var xi = (x(d, i, data) + o) * pow2k,
          yi = (y(d, i, data) + o) * pow2k,
          wi = +weight(d, i, data);
      if (xi >= 0 && xi < n && yi >= 0 && yi < m) {
        var x0 = Math.floor(xi),
            y0 = Math.floor(yi),
            xt = xi - x0 - 0.5,
            yt = yi - y0 - 0.5;
        values0[x0 + y0 * n] += (1 - xt) * (1 - yt) * wi;
        values0[x0 + 1 + y0 * n] += xt * (1 - yt) * wi;
        values0[x0 + 1 + (y0 + 1) * n] += xt * yt * wi;
        values0[x0 + (y0 + 1) * n] += (1 - xt) * yt * wi;
      }
    });

    // TODO Optimize.
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);
    blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k);
    blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k);

    var tz = threshold(values0);

    // Convert number of thresholds into uniform thresholds.
    if (!Array.isArray(tz)) {
      var stop = max(values0);
      tz = tickStep(0, stop, tz);
      tz = range(0, Math.floor(stop / tz) * tz, tz);
      tz.shift();
    }

    return contours()
        .thresholds(tz)
        .size([n, m])
      (values0)
        .map(transform);
  }

  function transform(geometry) {
    geometry.value *= Math.pow(2, -2 * k); // Density in points per square pixel.
    geometry.coordinates.forEach(transformPolygon);
    return geometry;
  }

  function transformPolygon(coordinates) {
    coordinates.forEach(transformRing);
  }

  function transformRing(coordinates) {
    coordinates.forEach(transformPoint);
  }

  // TODO Optimize.
  function transformPoint(coordinates) {
    coordinates[0] = coordinates[0] * Math.pow(2, k) - o;
    coordinates[1] = coordinates[1] * Math.pow(2, k) - o;
  }

  function resize() {
    o = r * 3;
    n = (dx + o * 2) >> k;
    m = (dy + o * 2) >> k;
    return density;
  }

  density.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), density) : x;
  };

  density.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), density) : y;
  };

  density.weight = function(_) {
    return arguments.length ? (weight = typeof _ === "function" ? _ : constant(+_), density) : weight;
  };

  density.size = function(_) {
    if (!arguments.length) return [dx, dy];
    var _0 = +_[0], _1 = +_[1];
    if (!(_0 >= 0 && _1 >= 0)) throw new Error("invalid size");
    return dx = _0, dy = _1, resize();
  };

  density.cellSize = function(_) {
    if (!arguments.length) return 1 << k;
    if (!((_ = +_) >= 1)) throw new Error("invalid cell size");
    return k = Math.floor(Math.log(_) / Math.LN2), resize();
  };

  density.thresholds = function(_) {
    return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), density) : threshold;
  };

  density.bandwidth = function(_) {
    if (!arguments.length) return Math.sqrt(r * (r + 1));
    if (!((_ = +_) >= 0)) throw new Error("invalid bandwidth");
    return r = Math.round((Math.sqrt(4 * _ * _ + 1) - 1) / 2), resize();
  };

  return density;
}
Example #15
Source File: graticule.js    From gamedesign with GNU General Public License v3.0 4 votes vote down vote up
export default function graticule() {
  var x1, x0, X1, X0,
      y1, y0, Y1, Y0,
      dx = 10, dy = dx, DX = 90, DY = 360,
      x, y, X, Y,
      precision = 2.5;

  function graticule() {
    return {type: "MultiLineString", coordinates: lines()};
  }

  function lines() {
    return range(ceil(X0 / DX) * DX, X1, DX).map(X)
        .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
        .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x))
        .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).map(y));
  }

  graticule.lines = function() {
    return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
  };

  graticule.outline = function() {
    return {
      type: "Polygon",
      coordinates: [
        X(X0).concat(
        Y(Y1).slice(1),
        X(X1).reverse().slice(1),
        Y(Y0).reverse().slice(1))
      ]
    };
  };

  graticule.extent = function(_) {
    if (!arguments.length) return graticule.extentMinor();
    return graticule.extentMajor(_).extentMinor(_);
  };

  graticule.extentMajor = function(_) {
    if (!arguments.length) return [[X0, Y0], [X1, Y1]];
    X0 = +_[0][0], X1 = +_[1][0];
    Y0 = +_[0][1], Y1 = +_[1][1];
    if (X0 > X1) _ = X0, X0 = X1, X1 = _;
    if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
    return graticule.precision(precision);
  };

  graticule.extentMinor = function(_) {
    if (!arguments.length) return [[x0, y0], [x1, y1]];
    x0 = +_[0][0], x1 = +_[1][0];
    y0 = +_[0][1], y1 = +_[1][1];
    if (x0 > x1) _ = x0, x0 = x1, x1 = _;
    if (y0 > y1) _ = y0, y0 = y1, y1 = _;
    return graticule.precision(precision);
  };

  graticule.step = function(_) {
    if (!arguments.length) return graticule.stepMinor();
    return graticule.stepMajor(_).stepMinor(_);
  };

  graticule.stepMajor = function(_) {
    if (!arguments.length) return [DX, DY];
    DX = +_[0], DY = +_[1];
    return graticule;
  };

  graticule.stepMinor = function(_) {
    if (!arguments.length) return [dx, dy];
    dx = +_[0], dy = +_[1];
    return graticule;
  };

  graticule.precision = function(_) {
    if (!arguments.length) return precision;
    precision = +_;
    x = graticuleX(y0, y1, 90);
    y = graticuleY(x0, x1, precision);
    X = graticuleX(Y0, Y1, 90);
    Y = graticuleY(X0, X1, precision);
    return graticule;
  };

  return graticule
      .extentMajor([[-180, -90 + epsilon], [180, 90 - epsilon]])
      .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]);
}
Example #16
Source File: contours.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export default function() {
  var dx = 1,
      dy = 1,
      threshold = thresholdSturges,
      smooth = smoothLinear;

  function contours(values) {
    var tz = threshold(values);

    // Convert number of thresholds into uniform thresholds.
    if (!Array.isArray(tz)) {
      var domain = extent(values), start = domain[0], stop = domain[1];
      tz = tickStep(start, stop, tz);
      tz = range(Math.floor(start / tz) * tz, Math.floor(stop / tz) * tz, tz);
    } else {
      tz = tz.slice().sort(ascending);
    }

    return tz.map(function(value) {
      return contour(values, value);
    });
  }

  // Accumulate, smooth contour rings, assign holes to exterior rings.
  // Based on https://github.com/mbostock/shapefile/blob/v0.6.2/shp/polygon.js
  function contour(values, value) {
    var polygons = [],
        holes = [];

    isorings(values, value, function(ring) {
      smooth(ring, values, value);
      if (area(ring) > 0) polygons.push([ring]);
      else holes.push(ring);
    });

    holes.forEach(function(hole) {
      for (var i = 0, n = polygons.length, polygon; i < n; ++i) {
        if (contains((polygon = polygons[i])[0], hole) !== -1) {
          polygon.push(hole);
          return;
        }
      }
    });

    return {
      type: "MultiPolygon",
      value: value,
      coordinates: polygons
    };
  }

  // Marching squares with isolines stitched into rings.
  // Based on https://github.com/topojson/topojson-client/blob/v3.0.0/src/stitch.js
  function isorings(values, value, callback) {
    var fragmentByStart = new Array,
        fragmentByEnd = new Array,
        x, y, t0, t1, t2, t3;

    // Special case for the first row (y = -1, t2 = t3 = 0).
    x = y = -1;
    t1 = values[0] >= value;
    cases[t1 << 1].forEach(stitch);
    while (++x < dx - 1) {
      t0 = t1, t1 = values[x + 1] >= value;
      cases[t0 | t1 << 1].forEach(stitch);
    }
    cases[t1 << 0].forEach(stitch);

    // General case for the intermediate rows.
    while (++y < dy - 1) {
      x = -1;
      t1 = values[y * dx + dx] >= value;
      t2 = values[y * dx] >= value;
      cases[t1 << 1 | t2 << 2].forEach(stitch);
      while (++x < dx - 1) {
        t0 = t1, t1 = values[y * dx + dx + x + 1] >= value;
        t3 = t2, t2 = values[y * dx + x + 1] >= value;
        cases[t0 | t1 << 1 | t2 << 2 | t3 << 3].forEach(stitch);
      }
      cases[t1 | t2 << 3].forEach(stitch);
    }

    // Special case for the last row (y = dy - 1, t0 = t1 = 0).
    x = -1;
    t2 = values[y * dx] >= value;
    cases[t2 << 2].forEach(stitch);
    while (++x < dx - 1) {
      t3 = t2, t2 = values[y * dx + x + 1] >= value;
      cases[t2 << 2 | t3 << 3].forEach(stitch);
    }
    cases[t2 << 3].forEach(stitch);

    function stitch(line) {
      var start = [line[0][0] + x, line[0][1] + y],
          end = [line[1][0] + x, line[1][1] + y],
          startIndex = index(start),
          endIndex = index(end),
          f, g;
      if (f = fragmentByEnd[startIndex]) {
        if (g = fragmentByStart[endIndex]) {
          delete fragmentByEnd[f.end];
          delete fragmentByStart[g.start];
          if (f === g) {
            f.ring.push(end);
            callback(f.ring);
          } else {
            fragmentByStart[f.start] = fragmentByEnd[g.end] = {start: f.start, end: g.end, ring: f.ring.concat(g.ring)};
          }
        } else {
          delete fragmentByEnd[f.end];
          f.ring.push(end);
          fragmentByEnd[f.end = endIndex] = f;
        }
      } else if (f = fragmentByStart[endIndex]) {
        if (g = fragmentByEnd[startIndex]) {
          delete fragmentByStart[f.start];
          delete fragmentByEnd[g.end];
          if (f === g) {
            f.ring.push(end);
            callback(f.ring);
          } else {
            fragmentByStart[g.start] = fragmentByEnd[f.end] = {start: g.start, end: f.end, ring: g.ring.concat(f.ring)};
          }
        } else {
          delete fragmentByStart[f.start];
          f.ring.unshift(start);
          fragmentByStart[f.start = startIndex] = f;
        }
      } else {
        fragmentByStart[startIndex] = fragmentByEnd[endIndex] = {start: startIndex, end: endIndex, ring: [start, end]};
      }
    }
  }

  function index(point) {
    return point[0] * 2 + point[1] * (dx + 1) * 4;
  }

  function smoothLinear(ring, values, value) {
    ring.forEach(function(point) {
      var x = point[0],
          y = point[1],
          xt = x | 0,
          yt = y | 0,
          v0,
          v1 = values[yt * dx + xt];
      if (x > 0 && x < dx && xt === x) {
        v0 = values[yt * dx + xt - 1];
        point[0] = x + (value - v0) / (v1 - v0) - 0.5;
      }
      if (y > 0 && y < dy && yt === y) {
        v0 = values[(yt - 1) * dx + xt];
        point[1] = y + (value - v0) / (v1 - v0) - 0.5;
      }
    });
  }

  contours.contour = contour;

  contours.size = function(_) {
    if (!arguments.length) return [dx, dy];
    var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]);
    if (!(_0 > 0) || !(_1 > 0)) throw new Error("invalid size");
    return dx = _0, dy = _1, contours;
  };

  contours.thresholds = function(_) {
    return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), contours) : threshold;
  };

  contours.smooth = function(_) {
    return arguments.length ? (smooth = _ ? smoothLinear : noop, contours) : smooth === smoothLinear;
  };

  return contours;
}
Example #17
Source File: chord.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export default function() {
  var padAngle = 0,
      sortGroups = null,
      sortSubgroups = null,
      sortChords = null;

  function chord(matrix) {
    var n = matrix.length,
        groupSums = [],
        groupIndex = range(n),
        subgroupIndex = [],
        chords = [],
        groups = chords.groups = new Array(n),
        subgroups = new Array(n * n),
        k,
        x,
        x0,
        dx,
        i,
        j;

    // Compute the sum.
    k = 0, i = -1; while (++i < n) {
      x = 0, j = -1; while (++j < n) {
        x += matrix[i][j];
      }
      groupSums.push(x);
      subgroupIndex.push(range(n));
      k += x;
    }

    // Sort groups…
    if (sortGroups) groupIndex.sort(function(a, b) {
      return sortGroups(groupSums[a], groupSums[b]);
    });

    // Sort subgroups…
    if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
      d.sort(function(a, b) {
        return sortSubgroups(matrix[i][a], matrix[i][b]);
      });
    });

    // Convert the sum to scaling factor for [0, 2pi].
    // TODO Allow start and end angle to be specified?
    // TODO Allow padding to be specified as percentage?
    k = max(0, tau - padAngle * n) / k;
    dx = k ? padAngle : tau / n;

    // Compute the start and end angle for each group and subgroup.
    // Note: Opera has a bug reordering object literal properties!
    x = 0, i = -1; while (++i < n) {
      x0 = x, j = -1; while (++j < n) {
        var di = groupIndex[i],
            dj = subgroupIndex[di][j],
            v = matrix[di][dj],
            a0 = x,
            a1 = x += v * k;
        subgroups[dj * n + di] = {
          index: di,
          subindex: dj,
          startAngle: a0,
          endAngle: a1,
          value: v
        };
      }
      groups[di] = {
        index: di,
        startAngle: x0,
        endAngle: x,
        value: groupSums[di]
      };
      x += dx;
    }

    // Generate chords for each (non-empty) subgroup-subgroup link.
    i = -1; while (++i < n) {
      j = i - 1; while (++j < n) {
        var source = subgroups[j * n + i],
            target = subgroups[i * n + j];
        if (source.value || target.value) {
          chords.push(source.value < target.value
              ? {source: target, target: source}
              : {source: source, target: target});
        }
      }
    }

    return sortChords ? chords.sort(sortChords) : chords;
  }

  chord.padAngle = function(_) {
    return arguments.length ? (padAngle = max(0, _), chord) : padAngle;
  };

  chord.sortGroups = function(_) {
    return arguments.length ? (sortGroups = _, chord) : sortGroups;
  };

  chord.sortSubgroups = function(_) {
    return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
  };

  chord.sortChords = function(_) {
    return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
  };

  return chord;
}
Example #18
Source File: graticule.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export default function graticule() {
  var x1, x0, X1, X0,
      y1, y0, Y1, Y0,
      dx = 10, dy = dx, DX = 90, DY = 360,
      x, y, X, Y,
      precision = 2.5;

  function graticule() {
    return {type: "MultiLineString", coordinates: lines()};
  }

  function lines() {
    return range(ceil(X0 / DX) * DX, X1, DX).map(X)
        .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
        .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x))
        .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).map(y));
  }

  graticule.lines = function() {
    return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
  };

  graticule.outline = function() {
    return {
      type: "Polygon",
      coordinates: [
        X(X0).concat(
        Y(Y1).slice(1),
        X(X1).reverse().slice(1),
        Y(Y0).reverse().slice(1))
      ]
    };
  };

  graticule.extent = function(_) {
    if (!arguments.length) return graticule.extentMinor();
    return graticule.extentMajor(_).extentMinor(_);
  };

  graticule.extentMajor = function(_) {
    if (!arguments.length) return [[X0, Y0], [X1, Y1]];
    X0 = +_[0][0], X1 = +_[1][0];
    Y0 = +_[0][1], Y1 = +_[1][1];
    if (X0 > X1) _ = X0, X0 = X1, X1 = _;
    if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
    return graticule.precision(precision);
  };

  graticule.extentMinor = function(_) {
    if (!arguments.length) return [[x0, y0], [x1, y1]];
    x0 = +_[0][0], x1 = +_[1][0];
    y0 = +_[0][1], y1 = +_[1][1];
    if (x0 > x1) _ = x0, x0 = x1, x1 = _;
    if (y0 > y1) _ = y0, y0 = y1, y1 = _;
    return graticule.precision(precision);
  };

  graticule.step = function(_) {
    if (!arguments.length) return graticule.stepMinor();
    return graticule.stepMajor(_).stepMinor(_);
  };

  graticule.stepMajor = function(_) {
    if (!arguments.length) return [DX, DY];
    DX = +_[0], DY = +_[1];
    return graticule;
  };

  graticule.stepMinor = function(_) {
    if (!arguments.length) return [dx, dy];
    dx = +_[0], dy = +_[1];
    return graticule;
  };

  graticule.precision = function(_) {
    if (!arguments.length) return precision;
    precision = +_;
    x = graticuleX(y0, y1, 90);
    y = graticuleY(x0, x1, precision);
    X = graticuleX(Y0, Y1, 90);
    Y = graticuleY(X0, X1, precision);
    return graticule;
  };

  return graticule
      .extentMajor([[-180, -90 + epsilon], [180, 90 - epsilon]])
      .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]);
}
Example #19
Source File: ContourLogLik.js    From likelihood with MIT License 4 votes vote down vote up
ContourChart = props => {
  const vizRef = useRef(null);
  const dispatch = useContext(VizDispatch);
  // Stuff
  const margin = { top: 0, right: 20, bottom: 40, left: 50 };
  const w = props.width - margin.left - margin.right;
  const h = props.width * 0.75 - margin.top - margin.bottom;
  const sample = props.sample;
  const sigmaTheta = Math.sqrt(props.sigma2Theta);
  const muMax = props.muTheta + sigmaTheta * 5;
  const muMin = props.muTheta - sigmaTheta * 5;
  const sigma2MLE = props.sigma2Theta;
  const sigma2Max = 1500;
  const sigma2Min = 1;

  // For gradient ascent illustration
  const [spring, set] = useSpring(() => ({
    xy: [props.mu, props.sigma2],
    immediate: false,
    config: { duration: 500 }
  }));

  const bind = useDrag(({ movement: [mx, my], first, memo }) => {
    const muStart = first ? props.mu : memo[0];
    const sigma2Start = first ? props.sigma2 : memo[1];
    const mu = xScale.invert(xScale(muStart) + mx);
    const sigma2 = yScale.invert(yScale(sigma2Start) + my);
    dispatch({
      name: "contourDrag",
      value: { mu: mu, sigma2: sigma2 }
    });
    return [muStart, sigma2Start];
  });

  const iterate = () => {
    dispatch({
      name: "algoIterate",
      value: {
        increment: 1,
      }
    });
  };

  useInterval(() => {
    iterate();
  }, props.algoDelay);

  set({ xy: [props.mu, props.sigma2], immediate: !props.animating });

  const llMin = -300;
  const llMax = -20;
  const thresholds = useMemo(
    () => range(llMin, llMax, (llMax - llMin) / 100),
    []
  );

  const yScale = scaleLinear([sigma2Min, sigma2Max], [h, 0]);

  const xScale = scaleLinear([muMin, muMax], [0, w]);

  const linex = useMemo(
    () =>
      line()
        .x(d => xScale(d.mu))
        .y(d => yScale(d.sigma2)),
    [w]
  );

  const grid = useMemo(
    () => createGrid(muMin, muMax, sigma2Min, sigma2Max, sample),
    [props.sample]
  );

  const color = useMemo(
    () =>
      scaleLinear()
        .domain([-100, max(grid)])
        .range(["#82b3aa", "#fff"])
        .interpolate(interpolateRgb.gamma(0.6)),
    [props.sample]
  );

  const contour = useMemo(
    () =>
      contours()
        .size([grid.n, grid.m])
        .thresholds(thresholds)(grid)
        .map(({ type, value, coordinates }) => {
          return {
            type,
            value,
            coordinates: coordinates.map(rings => {
              return rings.map(points => {
                return points.map(([mu, sigma2]) => [
                  xScale(muMin + mu * grid.muStep),
                  yScale(sigma2Min + sigma2 * grid.sigmaStep)
                ]);
              });
            })
          };
        }),
    [props.sample, w]
  );

  const contourPaths = useMemo(
    () =>
      contour.map((d, i) => {
        return (
          <path
            d={geoPath()(d)}
            className="contour"
            fill={color(d.value)}
            fillOpacity={1}
            stroke="#485460"
            strokeWidth={i % 5 ? 0.5 : 1.5}
            strokeOpacity={0.75}
            strokeLinejoin="round"
            key={i}
          />
        );
      }),
    [props.sample, w]
  );

  const ll = useMemo(
    () => format(".2f")(logLikSum(sample, props.mu, props.sigma2)),
    [sample, props.mu, props.sigma2]
  );

  return (
    <svg width={props.width} height={h + margin.bottom}>
      <g ref={vizRef}>
        <g
          className="viz"
          transform={"translate(" + margin.left + "," + 0 + ")"}
        >
          {contourPaths}
          <animated.line
            x1={xScale(muMin)}
            x2={xScale(muMax)}
            y1={0}
            y2={0}
            className="LogLikMu"
            transform={spring.xy.interpolate(
              (x, y) => `translate(0, ${yScale(y)})`
            )}
          />
          <animated.line
            y1={yScale(sigma2Min)}
            y2={yScale(sigma2Max)}
            x1={0}
            x2={0}
            transform={spring.xy.interpolate(
              (x, y) => `translate(${xScale(x)}, 0)`
            )}
            className="LogLikSigma"
          />

          <animated.g
            {...bind()}
            transform={spring.xy.interpolate(
              (x, y) => `translate(${xScale(x)}, ${yScale(y)})`
            )}
            className="draggable"
          >
            <circle cx={0} cy={0} r="5" className="logLikX" />
            <Tooltip x={0} y={0} equation={eqLogLik(ll)} margin={margin} />
          </animated.g>
          <path d={linex(props.drawGradientPath)} className="gradientDescent" />
          <rect
            id="clip-rect"
            x="0"
            y="0"
            width={w}
            height={h}
            fill="none"
            stroke="#fff"
            strokeWidth="3px"
          />
        </g>
      </g>
    </svg>
  );
}
Example #20
Source File: LogLikPlot.js    From likelihood with MIT License 4 votes vote down vote up
logLikCart = props => {
  const vizRef = useRef(null);
  const dispatch = useContext(VizDispatch);
  // Stuff
  const margin = { top: 60, right: 20, bottom: 40, left: 50 };
  const durationTime = 200;
  const w = props.width - margin.left - margin.right;
  const h = props.width * 0.4 - margin.top - margin.bottom;
  const sample = props.sample;
  const sigmaTheta = Math.sqrt(props.sigma2Theta);
  const deriv = props.deriv;
  const data1 = props.data;
  // Axes min and max
  var xMax, xMin, llTheta;
  if (props.thetaLab == "mu") {
    xMax = props.muTheta + sigmaTheta * 5;
    xMin = props.muTheta - sigmaTheta * 5;
    llTheta = useMemo(() => logLikSum(sample, props.mu, props.sigma2), [
      props.mu,
      props.sigma2,
      props.sample
    ]);
  } else if (props.thetaLab == "sigma") {
    const sigma2MLE = props.sigma2Theta;
    xMax = sigma2MLE + sigma2MLE * 2;
    xMin = sigma2MLE - sigma2MLE * 5;
    xMin = xMin < 0 ? 0.1 : xMin;
    llTheta = useMemo(() =>
      logLikSum(sample, props.mu, props.sigma2, [
        props.mu,
        props.sigma2,
        props.sample
      ])
    );
  }

  const x_range = range(xMin, xMax, Math.abs(xMax - xMin) / 50);
  const newtonParabola = x_range.map(x1 => {
    return [
      x1,
      quadraticApprox(x1 - props.mu, 1, llTheta, deriv, -10 / props.sigma2)
    ];
  });
  const yMin = -100;
  const yMax = -20;

  const [spring, set] = useSpring(() => ({
    xy: [props.mu, props.sigma2],
    immediate: false,
    config: { duration: 500 }
  }));

  set({ xy: [props.mu, props.sigma2], immediate: !props.animating });

  const bind = useDrag(({ movement: [mx, my], first, memo }) => {
    const muStart = first ? props.mu : memo[0];
    const sigma2Start = first ? props.sigma2 : memo[1];
    const mu = xScale.invert(xScale(muStart) + mx);
    const sigma2 = yScale.invert(yScale(sigma2Start) + my);
    dispatch({
      name: "contourDrag",
      value: { mu: mu, sigma2: props.sigma2 }
    });
    return [muStart, sigma2Start];
  });

  //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);
  const yAxis = axisLeft(yScale).ticks(4);

  // Line function
  const linex = line()
    .x(d => xScale(d[0]))
    .y(d => yScale(d[1]));

  // Update
  useEffect(() => {
    createChart(durationTime);
  }, [props.mu, props.sigma2, w, props.sample]);

  const gradientNext = gradientStep(props);
  const gradientNextLL = logLikSum(
    sample,
    gradientNext.points.mu,
    props.sigma2
  );

  // Tooltip
  const Tooltip = ({ theta, thetaLab, ll, deriv }) => {
    const x = 0;
    const y = 0;
    const width = 100;
    const path = topTooltipPath(width, 40, 10, 10);
    const thetaSymb = thetaLab == "mu" ? "mu" : "sigma^2";
    const eqLogLik = katex.renderToString(
      `\\frac{\\partial}{\\partial \\${thetaSymb}}\\ell = `,
      {
        displayMode: false,
        throwOnError: false
      }
    );
    return (
      <g>
        <path
          d={path}
          className="polygonTip"
          transform={`translate(${x + margin.left}, ${y + margin.top - 5})`}
        />
        <foreignObject
          x={x - width / 2 + margin.left}
          y={y}
          width={width}
          height={50}
        >
          <div className="vizTooltip">
            <p>
              <span dangerouslySetInnerHTML={{ __html: eqLogLik }} />
              {format(".2f")(deriv)}
            </p>
          </div>
        </foreignObject>
      </g>
    );
  };

  const createChart = () => {
    const node = vizRef.current;

    select(node)
      .selectAll("g.viz")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // x Axis
    select(node)
      .selectAll("g.xAxis")
      .data([0])
      .enter()
      .append("g")
      .attr("class", "xAxis");

    select(node)
      .select("g.xAxis")
      .attr(
        "transform",
        "translate(" + margin.left + "," + (h + margin.top) + ")"
      )
      .call(xAxis);

    // y Axis
    select(node)
      .selectAll("g.yAxis")
      .data([0])
      .enter()
      .append("g")
      .attr("class", "yAxis");

    select(node)
      .select("g.yAxis")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(yAxis);

    const gViz = select(node)
      .selectAll("g.viz")
      .data([0])
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // x label
    gViz
      .selectAll(".x-label")
      .data([0])
      .enter()
      .append("text")
      .style("text-anchor", "middle")
      .attr("class", "x-label MuiTypography-body1");

    select(node)
      .selectAll(".x-label")
      .attr(
        "transform",
        "translate(" + w / 2 + " ," + (h + margin.bottom - 5) + ")"
      )
      .text(props.thetaLab == "mu" ? "μ" : "σ²");

    // y label
    gViz
      .selectAll(".y-label")
      .data([0])
      .enter()
      .append("text")
      .style("text-anchor", "middle")
      .attr("class", "y-label MuiTypography-body2");

    select(node)
      .selectAll(".y-label")
      .attr("transform", "rotate(-90)")
      .attr("text-anchor", "middle")
      .attr("x", -(h / 2))
      .attr("y", -40)
      .text(`ℓ(μ, σ² = ${format(".2f")(props.sigma2)})`);
  };
  const delta = xMax - xMin;
  return (
    <svg width={props.width} height={props.width * 0.4}>
      <g ref={vizRef}>
        <g className="viz">
          <g clipPath="url(#clipMu)">
            <AnimatedPath
              data={data1.data}
              x={100}
              sigma2={props.sigma2}
              xScale={xScale}
              yScale={yScale}
              linex={linex}
              mu={props.mu}
              sample={sample}
              animating={props.animating}
              className="LogLikMu"
            />
            {props.algo == "newtonRaphson" && (
              <AnimatedPath
                data={newtonParabola}
                x={100}
                sigma2={props.sigma2}
                xScale={xScale}
                yScale={yScale}
                linex={linex}
                mu={props.mu}
                sample={sample}
                animating={props.animating}
                className="LogLikNewton"
              />
            )}
            {props.algo == "gradientAscent" && (
              <>
                <circle
                  cx={xScale(gradientNext.points.mu)}
                  cy={yScale(gradientNextLL)}
                  r="5"
                  className="logLikNewtonX--approx"
                />
                <line
                  className="LogLikNewton--maxima"
                  y1={yScale(yMin)}
                  y2={yScale(gradientNextLL)}
                  x1={xScale(gradientNext.points.mu)}
                  x2={xScale(gradientNext.points.mu)}
                />
              </>
            )}
          </g>
        </g>
      </g>
      <g clipPath="url(#clipMu2)">
        <animated.g
          {...bind()}
          transform={spring.xy.interpolate(
            (x, y) =>
              `translate(${xScale(x)}, ${yScale(logLikSum(sample, x, y))})`
          )}
          className="draggable"
        >
          <circle
            cx={margin.left}
            cy={margin.top}
            r="5"
            className="logLikX"
          />
          <animated.line
            className="deriv"
            y1={spring.xy.interpolate(
              (x, y) =>
                margin.top + yScale(yMax - delta * dMu(10, x, props.muHat, y))
            )}
            y2={spring.xy.interpolate(
              (x, y) =>
                margin.top + yScale(yMax + delta * dMu(10, x, props.muHat, y))
            )}
            x1={margin.left + xScale(xMin - delta)}
            x2={margin.left + xScale(xMin + delta)}
          />

          <Tooltip
            theta={props.theta}
            thetaLab={props.thetaLab}
            ll={llTheta}
            deriv={deriv}
          />
        </animated.g>
      </g>
      <defs>
        <clipPath id="clipMu">
          <rect id="clip-rectMu" x="0" y="-10" width={w} height={h + 10} />
        </clipPath>
        <clipPath id="clipMu2">
          <rect
            id="clip-rectMu"
            x={margin.left}
            y={-margin.bottom}
            width={w}
            height={h + 100}
          />
        </clipPath>
      </defs>
    </svg>
  );
}
Example #21
Source File: NewtonParabola.js    From likelihood with MIT License 4 votes vote down vote up
AnimatedPath = ({
  mu,
  sigma2,
  yMin,
  yMax,
  xMin,
  xScale,
  yScale,
  linex,
  llTheta,
  deriv,
  hessian,
  count
}) => {


  const [props, set] = useSpring(() => ({ opacity: 0, offset: 1000 }));


  useEffect(() => {
    // reset when count updates
    set({
      to: { offset: 1000, opacity: 0 },
      config: { duration: 500 },
      immediate: true,
    })

    // Run after AnimatedPath/Circle finishes
    const timer = setTimeout(() => {
      // animate parabola first
      set({
        to: { offset: 0  },
        config: { duration: 500 },
        immediate: false,
      })
      setTimeout(() => {
        // animate maxima objects
        set({
          to: { opacity: 1 },
          config: { duration: 500 },
          immediate: false,
        })
      }, 500);
    }, 500);
    return () => clearTimeout(timer);
  }, [count])



  const x_range = range(yMin, yMax, Math.abs(yMax - yMin) / 50);
  const newtonParabola = x_range.map(x1 => {
    return [x1, quadraticApprox(x1 - sigma2, 1, llTheta, deriv, hessian)];
  });

  const x1 = sigma2 + deriv / -hessian;

  const x1ApproxLL = quadraticApprox(x1 - sigma2, 1, llTheta, deriv, hessian);

  return (
    <g>
      <animated.path
        d={linex(newtonParabola)}
        className="LogLikNewton--test"
        strokeDasharray={1000}
        strokeDashoffset={props.offset}
      />
      <animated.g style={{ opacity: props.opacity }}>
        <line
          className="LogLikNewton--maxima"
          x1={xScale(xMin)}
          x2={xScale(x1ApproxLL)}
          y1={yScale(x1)}
          y2={yScale(x1)}
        />
        <circle
          cx={xScale(x1ApproxLL)}
          cy={yScale(x1)}
          r="5"
          className="logLikNewtonX--approx"
        />
      </animated.g>
    </g>
  );
}
Example #22
Source File: SamplePlot.js    From likelihood with MIT License 4 votes vote down vote up
SampleChart = props => {
  const vizRef = useRef(null);

  // Stuff
  const margin = { top: 60, right: 20, bottom: 30, left: 50 };
 
  const durationTime = 200;
  const w = props.width - margin.left - margin.right;
  const h = props.width * aspect - margin.top - margin.bottom;
  const sample = props.sample;
  const sigma = Math.sqrt(props.sigma2)
  const sigmaTheta = Math.sqrt(props.sigma2Theta)
  // x.values
  const x_start = props.muTheta - 10 * sigmaTheta;
  const x_end = props.muTheta + 10 * sigmaTheta;

  const x_start2 = props.mu - 3 * sigma;
  const x_end2 = props.mu + 3 * sigma;
  const x = range( props.mu - 3 * sigma,
     props.mu + 3 * sigma, Math.abs(x_start2 - x_end2) / 50);
  x.push(x_end)
  x.unshift(x_start)
  

  // Data sets
  const data1 = genData(props.mu, sigma, x);

  // Axes min and max
  const x_max = props.muTheta + sigmaTheta * 5;
  const x_min = props.muTheta - sigmaTheta * 5;
  //const y_max = max(data1.y);
  const y_max = 0.04;
  // Create scales
  const yScale = scaleLinear()
    .domain([0, y_max])
    .range([h, 0]);

  const xScale = scaleLinear()
    .domain([x_min, x_max])
    .range([0, w]);

  // Scales and Axis
  const xAxis = axisBottom(xScale);
  const yAxis = axisLeft(yScale);

  // Update
  useEffect(() => {
    createSampleChart(durationTime);
  }, [props.mu, props.sigma2, props.highlight, props.sample, w]);

  // Tooltip
  const Tooltip = ({ d, i }) => {
    const x = xScale(d);
    const L = normal.pdf(d, props.mu, sigma);
    const y = yScale(L);
    const path = topTooltipPath(150, 50, 10, 10);
    const width = 150;
    const eqLogLik = katex.renderToString(`\\ell_{${i + 1}} = `, {
      displayMode: false,
      throwOnError: false
    });
    return (
      <g>
        <path
          d={path}
          className="polygonTip1"
          transform={`translate(${x + margin.left}, ${y + margin.top })`}
        />
        <foreignObject
          x={x - width / 2 + margin.left}
          y={y }
          width={width}
          height={50}
        >
          <div className="vizTooltip">
            <p>
              <span dangerouslySetInnerHTML={{ __html: eqLogLik }} />
              log({format(".2n")(L)})
            </p>
          </div>
        </foreignObject>
      </g>
    );
  };

  const createSampleChart = () => {
    const node = vizRef.current;

    // Line function
    const linex = line()
      .x(d => xScale(d[0]))
      .y(d => yScale(d[1]));

    select(node)
      .selectAll("g.viz")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // x Axis
    select(node)
      .selectAll("g.xAxis")
      .data([0])
      .enter()
      .append("g")
      .attr("class", "xAxis");

    select(node)
      .select("g.xAxis")
      .attr(
        "transform",
        "translate(" + margin.left + "," + (h + margin.top) + ")"
      )
      .call(xAxis);

    // y Axis
    select(node)
      .selectAll("g.yAxis")
      .data([0])
      .enter()
      .append("g")
      .attr("class", "yAxis");

    select(node)
      .select("g.yAxis")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(yAxis);

    const gViz = select(node)
      .selectAll("g.viz")
      .data([0])
      .enter()
      .append("g")
      .attr("class", "viz")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // x label
    gViz
      .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(props.xLabel);

    // y label
    gViz
      .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("Density");

    // Append dists

    // DIST1
    gViz
      .selectAll("#dist1")
      .data([data1.data])
      .enter()
      .append("svg:path")
      .attr("d", linex)
      .attr("id", "dist1");

    select(node)
      .selectAll("#dist1")
      .data([data1.data])
      .attr("d", linex);


    // mu vertical lines
    const sampleLines = (mu, id) => {
      gViz
        .selectAll("#" + id)
        .data([0])
        .enter()
        .append("line")
        .attr("class", "logLikLines")
        .attr("id", id);

      select(node)
        .selectAll("#" + id)
        .data([0])
        .attr("x1", xScale(mu))
        .attr("x2", xScale(mu))
        .attr("y1", yScale(normal.pdf(mu, props.mu, sigma)))
        .attr("y2", yScale(0));
    };

    //muLines(props.mu0, "mu0");
    sample.map((x, i) => sampleLines(x, `sample${i}`));
        // Points
        gViz
        .selectAll("circle")
        .data(sample)
        .enter()
        .append("svg:circle")
        .attr("cy", d => yScale(normal.pdf(d, props.mu, sigma)))
        .attr("cx", d => xScale(d));
  
      select(node)
        .selectAll("circle")
        .data(sample)
        .attr("cy", d => yScale(normal.pdf(d, props.mu, sigma)))
        .attr("cx", d => xScale(d))
        .attr("class", "sampleCircles")
        .on("mouseover", function(d, i) {
          props.setHighlight(i);
          select(this).attr("r", 10)
        })
        .on("mouseout", function() {
          props.setHighlight();
          select(this).attr("r", 5)
        })
        .attr("r", (d, i) => {
          const r = props.highlight == i ? 10 : 5;
          return r;
        });
  
  };

  return (
    <svg width={props.width} height={props.width * aspect}>
      <g ref={vizRef} />
      {props.highlight >= 0 && (
        <Tooltip d={sample[props.highlight]} i={props.highlight} />
      )}
    </svg>
  );
}