d3-format#format JavaScript Examples

The following examples show how to use d3-format#format. 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: tickFormat.js    From cs-wiki with GNU General Public License v3.0 6 votes vote down vote up
export default function tickFormat(start, stop, count, specifier) {
  var step = tickStep(start, stop, count),
      precision;
  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
  switch (specifier.type) {
    case "s": {
      var value = Math.max(Math.abs(start), Math.abs(stop));
      if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
      return formatPrefix(specifier, value);
    }
    case "":
    case "e":
    case "g":
    case "p":
    case "r": {
      if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
      break;
    }
    case "f":
    case "%": {
      if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
      break;
    }
  }
  return format(specifier);
}
Example #2
Source File: tickFormat.js    From cs-wiki with GNU General Public License v3.0 6 votes vote down vote up
export default function(start, stop, count, specifier) {
  var step = tickStep(start, stop, count),
      precision;
  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
  switch (specifier.type) {
    case "s": {
      var value = Math.max(Math.abs(start), Math.abs(stop));
      if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
      return formatPrefix(specifier, value);
    }
    case "":
    case "e":
    case "g":
    case "p":
    case "r": {
      if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
      break;
    }
    case "f":
    case "%": {
      if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
      break;
    }
  }
  return format(specifier);
}
Example #3
Source File: TestTabs.js    From likelihood with MIT License 6 votes vote down vote up
ScorePanel = React.memo(({derivMuNull, deriv2MuNull, eqChisq}) => {
  const classes = useStyles()
  const score = (derivMuNull * derivMuNull) / -deriv2MuNull;
  const eqScore = katex.renderToString(
    `
    \\begin{aligned}
    S(\\mu_0, \\hat\\sigma_0^2) =& \\frac{U(\\mu_0, \\hat\\sigma_0^2)^2}{I(\\mu_0, \\hat\\sigma_0^2)} \\\\
    &= \\frac{${f2n(derivMuNull)}^2}{${f2n(-deriv2MuNull)}} \\\\
    &= ${f3n(score)}
    \\end{aligned}
    `,
    {
      displayMode: true,
      throwOnError: false
    }
  );
  const pvalScore = 1 - chisquare.cdf(score, 1);
  return (
    <TabPanel className={classes.panel}>
      <Typography variant="body1">
        The Score test (also known as the Lagrange multiplier test) is
        slightly different in the sense that we only evaluate it at the null.
        It involves both the first and second derivative evaluated at the
        null.
      </Typography>
      <Typography
        variant="body1"
        dangerouslySetInnerHTML={{ __html: eqScore }}
      />
      <Typography variant="body1">
        Asymptotically <em>S</em> follows a{" "}
        <span dangerouslySetInnerHTML={{ __html: eqChisq }} /> distribution
        with 1 degrees of freedom, which gives <em>p</em> ={" "}
        {format(".2f")(pvalScore)}.
      </Typography>
    </TabPanel>
  )
})
Example #4
Source File: tickFormat.js    From gamedesign with GNU General Public License v3.0 6 votes vote down vote up
export default function(domain, count, specifier) {
  var start = domain[0],
      stop = domain[domain.length - 1],
      step = tickStep(start, stop, count == null ? 10 : count),
      precision;
  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
  switch (specifier.type) {
    case "s": {
      var value = Math.max(Math.abs(start), Math.abs(stop));
      if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
      return formatPrefix(specifier, value);
    }
    case "":
    case "e":
    case "g":
    case "p":
    case "r": {
      if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
      break;
    }
    case "f":
    case "%": {
      if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
      break;
    }
  }
  return format(specifier);
}
Example #5
Source File: format.js    From here-covid-19-tracker with MIT License 5 votes vote down vote up
formatThousand = num => {
  return format(",.8r")(num).split(".")[0]
}
Example #6
Source File: SurveillancePlot.js    From covidcg with MIT License 5 votes vote down vote up
countsFormatter = format('.2s')
Example #7
Source File: MutationList.js    From covidcg with MIT License 5 votes vote down vote up
countsFormatter = format('.0%')
Example #8
Source File: TestTabs.js    From likelihood with MIT License 5 votes vote down vote up
LrtPanel = React.memo(({sigma, sigma0, n, eqChisq}) => {
  const classes = useStyles()
  const calcLR = (sigma, sigma0, n) => {
    const W = Math.pow((sigma0 * sigma0) / (sigma * sigma), -n / 2);
    return -2 * Math.log(W);
  };
  const LR = calcLR(sigma, sigma0, n);
  const LRFormat = format(".3n")(LR);
  const eqLogLik = katex.renderToString(
    `\\begin{aligned}
      \\text{LR} &= -2[\\ell(\\mu_{0}, \\hat\\sigma^2_{0}) - [\\ell(\\hat\\mu, \\hat\\sigma^2)]\\\\
      &= ${LRFormat}
      \\end{aligned}`,
    {
      displayMode: true,
      throwOnError: false
    }
  );
  const pvalLRT = format(".2f")(1 - chisquare.cdf(LR, 1));
  return (
    <TabPanel className={classes.panel}>
      <Typography variant="body1">
        The likelihood ratio test compares the likelihood ratios of two
        models. In this example {"it's"} the likelihood evaluated at the MLE and
        at the null. This is illustrated in the plot by the vertical
        distance between the two horizontal lines. If we multiply the
        difference in log-likelihood by -2 we get the statistic,
      </Typography>
      <Typography
        variant="body1"
        dangerouslySetInnerHTML={{ __html: eqLogLik }}
      />
      <Typography variant="body1">
        Asymptotically LR follows a{" "}
        <span dangerouslySetInnerHTML={{ __html: eqChisq }} /> distribution
        with 1 degrees of freedom, which gives <em>p</em> = {pvalLRT}.
      </Typography>
      <Typography variant="body1">
        Note: The figure is simplified and does not account for the fact that
        each likelihood is based on different variance estimates.
      </Typography>
    </TabPanel>
  )
})
Example #9
Source File: TestTabs.js    From likelihood with MIT License 5 votes vote down vote up
WaldPanel = React.memo(({sigma, muHat, muNull, n}) => {
  const classes = useStyles();
  const se = sigma / Math.sqrt(n);
  const waldZ = (muHat - muNull) / se;
  const pvalZ = 2 * (1 - normal.cdf(Math.abs(waldZ), 0, 1));

  const eqSE = katex.renderToString(
    `\\text{se}(\\hat\\mu) = I(\\hat\\mu, \\hat\\sigma^2)^{-1/2}`,
    {
      displayMode: false,
      throwOnError: false
    }
  )

  const eqWald = katex.renderToString(`
    \\begin{aligned}
    Z =& \\frac{\\hat\\mu - \\mu_0}{\\text{se}(\\hat\\mu)} \\\\
      =& \\frac{${f3n(muHat)} - ${f3n(muNull)}}{${f3n(se)}} \\\\
      =& ${f3n(waldZ)}
    \\end{aligned}
  `, {
    displayMode: true,
    throwOnError: false
  })

  return (
    <TabPanel className={classes.panel}>
      <Typography variant="body1">
        The Wald test is based on the difference between the maximum
        likelihood estimate of the mean and μ0 divided by the standard error
        of the MLE, <span dangerouslySetInnerHTML={{ __html: eqSE }} />
      </Typography>
      <Typography
        variant="body1"
        dangerouslySetInnerHTML={{ __html: eqWald }}
      />
      <Typography variant="body1">
        Asymptotically <em>Z</em> follows a standard normal distribution,
        giving <em>p</em> = {format(".2f")(pvalZ)}.
      </Typography>
    </TabPanel>
  )
})
Example #10
Source File: TestTabs.js    From likelihood with MIT License 5 votes vote down vote up
f3n = format(".3n")
Example #11
Source File: TestTabs.js    From likelihood with MIT License 5 votes vote down vote up
f2n = format(".2n")
Example #12
Source File: CalcLogLik.js    From likelihood with MIT License 5 votes vote down vote up
CalcLogLik = ({ sample, mu, sigma, highlight, setHighlight }) => {
  const classes = useStyles();
  const ll = sample.map(x => logLik(x, mu, sigma));
  const llSum = ll.reduce((a, b) => a + b, 0);
  const eqLogLik = katex.renderToString(
    "\\ell(\\mu, \\sigma^2) = \\sum_i^n \\text{ln} \\thinspace f_y(y_i)=",
    {
      displayMode: false,
      throwOnError: false
    }
  );
  return (
    <div>
      <Typography variant="body1" gutterBottom>
        <span dangerouslySetInnerHTML={{ __html: eqLogLik }} />
        {ll.map((y, i) => {
          y = format(".1f")(y);
          return (
            <span key={i}>
              <span
                className={clsx(
                  classes.logLikSpan,
                  highlight == i && "highlight"
                )}
                onMouseOver={() => setHighlight(i)}
                onMouseOut={() => setHighlight()}
                id={"logLikSpan" + i}
              >
                {y}
              </span>
              {i != sample.length - 1 && <span>+</span>}
            </span>
          );
        })}
        =
        <span className={clsx(classes.logLikSpan, "sum")}>
          {format(".1f")(llSum)}
        </span>
      </Typography>
    </div>
  );
}
Example #13
Source File: horizontal-bar-chart.js    From website with Apache License 2.0 5 votes vote down vote up
HorizontalBarChart = ({
  data,
  fill,
  height,
  marginBottom = 0,
  marginLeft = 0,
  marginRight = 0,
  marginTop = 0,
  xTicks,
  width,
  xMax = null,
}) => {
  const totalXMargin = marginLeft + marginRight
  const totalYMargin = marginTop + marginBottom
  const yScale = scaleBand()
    .domain(data.map(d => d.name))
    .range([0, height - totalYMargin])
    .padding(0.2)
  const formatTick = format('~s')
  const xScale = scaleLinear()
    .domain([120, xMax || max(data, d => d.value)])
    .nice()
    .range([0, width - totalXMargin])

  return (
    <svg
      className={chartStyles.chart}
      viewBox={`0 0 ${width} ${height}`}
      aria-hidden
    >
      <g transform={`translate(${marginLeft} ${marginTop})`}>
        {xScale.ticks(xTicks).map(tick => (
          <g key={tick}>
            <text
              className={`${chartStyles.label} ${chartStyles.xTickLabel}`}
              x={xScale(tick)}
              y={height - marginBottom}
            >
              {formatTick(tick)}
            </text>
            <line
              className={chartStyles.gridLine}
              x1={xScale(tick)}
              x2={xScale(tick)}
              y1={0}
              y2={height - totalYMargin}
            />
          </g>
        ))}
      </g>

      <g transform={`translate(0, ${marginTop})`}>
        {data.map(d => (
          /* Do not remove nested svg. See https://github.com/COVID19Tracking/website/pull/645#discussion_r411676987 */
          <svg
            y={yScale(d.name) + 20}
            x={marginLeft - 10}
            className={chartStyles.yTickLabel}
            key={d.name}
          >
            <text className={chartStyles.label}>{`${d.name}`}</text>
          </svg>
        ))}
      </g>

      <g transform={`translate(${marginLeft}, ${marginTop})`}>
        {data.map(d => (
          <rect
            key={d.name}
            x={0}
            y={yScale(d.name)}
            height={yScale.bandwidth()}
            width={xScale(d.value)}
            fill={fill}
          />
        ))}
      </g>
    </svg>
  )
}
Example #14
Source File: visualization.js    From website with Apache License 2.0 5 votes vote down vote up
formatNumber = format(',.0f')
Example #15
Source File: test.legendsymbol.js    From t-viSNE with MIT License 5 votes vote down vote up
describe('d3-legend #legendSymbol', function() {
	it('exports a function', function() {
		expect(symbol).to.be.a('function');
	});

  it('should have a locale', function () {
    let result = symbol();
    expect(result.locale).to.be.a('function');
  });

  it('should redefine label\'s format with a string', function () {
    let result = symbol();
    let testValue = 1.00;
    let initial = result.labelFormat();

    result.labelFormat('.2f');

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine label\'s format with a format function', function () {
    let result = symbol();
    let testValue = 1.00;
    let initial = result.labelFormat();
    result.labelFormat(format('.2f'));

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine the locale with a new locale definition', function () {
    let result = symbol();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,0')
  })

  it('should keep the format specifier after a locale update', function () {
    let result = symbol();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.labelFormat(format('.2f'));
    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,00')
  })
});
Example #16
Source File: test.legendsize.js    From t-viSNE with MIT License 5 votes vote down vote up
describe('d3-legend #legendSize', function() {
	it('exports a function', function() {
		expect(size).to.be.a('function');
	});

  it('should have a locale', function () {
    let result = size();
    expect(result.locale).to.be.a('function');
  });

  it('should redefine label\'s format with a string', function () {
    let result = size();
    let testValue = 1.00;
    let initial = result.labelFormat();

    result.labelFormat('.2f');

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine label\'s format with a format function', function () {
    let result = size();
    let testValue = 1.00;
    let initial = result.labelFormat();
    result.labelFormat(format('.2f'));

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine the locale with a new locale definition', function () {
    let result = size();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,0')
  })

  it('should keep the format specifier after a locale update', function () {
    let result = size();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.labelFormat(format('.2f'));
    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,00')
  })
});
Example #17
Source File: indexRollupNext.js    From t-viSNE with MIT License 4 votes vote down vote up
helper = {

  d3_drawShapes: function d3_drawShapes(shape, shapes, shapeHeight, shapeWidth, shapeRadius, path) {
    if (shape === "rect") {
      shapes.attr("height", shapeHeight).attr("width", shapeWidth);
    } else if (shape === "circle") {
      shapes.attr("r", shapeRadius);
    } else if (shape === "line") {
      shapes.attr("x1", 0).attr("x2", shapeWidth).attr("y1", 0).attr("y2", 0);
    } else if (shape === "path") {
      shapes.attr("d", path);
    }
  },

  d3_addText: function d3_addText(svg, enter, labels, classPrefix, labelWidth) {
    enter.append("text").attr("class", classPrefix + "label");
    var text = svg.selectAll('g.' + classPrefix + 'cell text.' + classPrefix + 'label').data(labels).text(d3_identity);

    if (labelWidth) {
      svg.selectAll('g.' + classPrefix + 'cell text.' + classPrefix + 'label').call(d3_textWrapping, labelWidth);
    }

    return text;
  },

  d3_calcType: function d3_calcType(scale, ascending, cells, labels, labelFormat, labelDelimiter) {
    var type = scale.invertExtent ? d3_quantLegend(scale, labelFormat, labelDelimiter) : scale.ticks ? d3_linearLegend(scale, cells, labelFormat) : d3_ordinalLegend(scale);

    //for d3.scaleSequential that doesn't have a range function
    var range = scale.range && scale.range() || scale.domain();
    type.labels = d3_mergeLabels(type.labels, labels, scale.domain(), range);

    if (ascending) {
      type.labels = d3_reverse(type.labels);
      type.data = d3_reverse(type.data);
    }

    return type;
  },

  d3_filterCells: function d3_filterCells(type, cellFilter) {
    var filterCells = type.data.map(function (d, i) {
      return { data: d, label: type.labels[i] };
    }).filter(cellFilter);
    var dataValues = filterCells.map(function (d) {
      return d.data;
    });
    var labelValues = filterCells.map(function (d) {
      return d.label;
    });
    type.data = type.data.filter(function (d) {
      return dataValues.indexOf(d) !== -1;
    });
    type.labels = type.labels.filter(function (d) {
      return labelValues.indexOf(d) !== -1;
    });
    return type;
  },

  d3_placement: function d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign) {
    cell.attr("transform", cellTrans);
    text.attr("transform", textTrans);
    if (orient === "horizontal") {
      text.style("text-anchor", labelAlign);
    }
  },

  d3_addEvents: function d3_addEvents(cells, dispatcher) {
    cells.on("mouseover.legend", function (d) {
      d3_cellOver(dispatcher, d, this);
    }).on("mouseout.legend", function (d) {
      d3_cellOut(dispatcher, d, this);
    }).on("click.legend", function (d) {
      d3_cellClick(dispatcher, d, this);
    });
  },

  d3_title: function d3_title(svg, title, classPrefix, titleWidth) {
    if (title !== "") {

      var titleText = svg.selectAll('text.' + classPrefix + 'legendTitle');

      titleText.data([title]).enter().append('text').attr('class', classPrefix + 'legendTitle');

      svg.selectAll('text.' + classPrefix + 'legendTitle').text(title);

      if (titleWidth) {
        svg.selectAll('text.' + classPrefix + 'legendTitle').call(d3_textWrapping, titleWidth);
      }

      var cellsSvg = svg.select('.' + classPrefix + 'legendCells');
      var yOffset = svg.select('.' + classPrefix + 'legendTitle').nodes().map(function (d) {
        return d.getBBox().height;
      })[0],
          xOffset = -cellsSvg.nodes().map(function (d) {
        return d.getBBox().x;
      })[0];
      cellsSvg.attr('transform', 'translate(' + xOffset + ',' + yOffset + ')');
    }
  },

  d3_defaultLocale: {
    format: format,
    formatPrefix: formatPrefix
  },

  d3_defaultFormatSpecifier: '.01f',

  d3_defaultDelimiter: 'to'
}
Example #18
Source File: log.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export function loggish(transform) {
  const scale = transform(transformLog, transformExp);
  const domain = scale.domain;
  let base = 10;
  let logs;
  let pows;

  function rescale() {
    logs = logp(base), pows = powp(base);
    if (domain()[0] < 0) {
      logs = reflect(logs), pows = reflect(pows);
      transform(transformLogn, transformExpn);
    } else {
      transform(transformLog, transformExp);
    }
    return scale;
  }

  scale.base = function(_) {
    return arguments.length ? (base = +_, rescale()) : base;
  };

  scale.domain = function(_) {
    return arguments.length ? (domain(_), rescale()) : domain();
  };

  scale.ticks = count => {
    const d = domain();
    let u = d[0];
    let v = d[d.length - 1];
    const r = v < u;

    if (r) ([u, v] = [v, u]);

    let i = logs(u);
    let j = logs(v);
    let k;
    let t;
    const n = count == null ? 10 : +count;
    let z = [];

    if (!(base % 1) && j - i < n) {
      i = Math.floor(i), j = Math.ceil(j);
      if (u > 0) for (; i <= j; ++i) {
        for (k = 1; k < base; ++k) {
          t = i < 0 ? k / pows(-i) : k * pows(i);
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      } else for (; i <= j; ++i) {
        for (k = base - 1; k >= 1; --k) {
          t = i > 0 ? k / pows(-i) : k * pows(i);
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      }
      if (z.length * 2 < n) z = ticks(u, v, n);
    } else {
      z = ticks(i, j, Math.min(j - i, n)).map(pows);
    }
    return r ? z.reverse() : z;
  };

  scale.tickFormat = (count, specifier) => {
    if (count == null) count = 10;
    if (specifier == null) specifier = base === 10 ? "s" : ",";
    if (typeof specifier !== "function") {
      if (!(base % 1) && (specifier = formatSpecifier(specifier)).precision == null) specifier.trim = true;
      specifier = format(specifier);
    }
    if (count === Infinity) return specifier;
    const k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
    return d => {
      let i = d / pows(Math.round(logs(d)));
      if (i * base < base - 0.5) i *= base;
      return i <= k ? specifier(d) : "";
    };
  };

  scale.nice = () => {
    return domain(nice(domain(), {
      floor: x => pows(Math.floor(logs(x))),
      ceil: x => pows(Math.ceil(logs(x)))
    }));
  };

  return scale;
}
Example #19
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>
  );
}
Example #20
Source File: LogLikPlotSigma.js    From likelihood with MIT License 4 votes vote down vote up
OverlapChart = props => {
  const vizRef = useRef(null);
  const dispatch = useContext(VizDispatch);
  // Stuff
  const margin = { top: 0, right: 20, bottom: 40, left: 50 };
  const durationTime = 200;
  const w = props.width * 0.4 - margin.left - margin.right;
  const h = props.width * 0.75 - margin.top - margin.bottom;
  const sample = props.sample;
  const deriv = props.deriv;
  const data1 = props.data;
  // Axes min and max
  var yMin, yMax, llTheta;

  yMax = 1500;
  yMin = 1;
  llTheta = useMemo(() => logLikSum(sample, props.mu, props.sigma2), [
    props.mu,
    props.sigma2,
    props.sample
  ]);

  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: props.mu, sigma2: sigma2 }
    });
    return [muStart, sigma2Start];
  });

  const xMin = -100;
  const xMax = -20;

  const hessian = -10 / (2 * props.sigma2 * props.sigma2);

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

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

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

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

  // Tooltip
  const Tooltip = ({ theta, thetaLab, ll, deriv }) => {
    const x = 0;
    const y = 0;
    const width = 40;
    const path = topTooltipPath(width, 100, 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 + 5}, ${y +
            margin.top}) rotate(90)`}
        />
        <foreignObject
          x={x + margin.right / 2 + margin.left}
          y={y - margin.bottom + 15}
          width={100}
          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-body2");

    select(node)
      .selectAll(".x-label")
      .attr(
        "transform",
        "translate(" + w / 2 + " ," + (h + margin.bottom - 5) + ")"
      )
      .text(`ℓ(μ = ${format(".2f")(props.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("σ²");
  };
  const delta = yMax - yMin;

  return (
    <svg width={props.width} height={h + margin.bottom}>
      <g ref={vizRef}>
        <g className="viz">
          <g clipPath="url(#clipQuadApprox)">
            <AnimatedPath
              data={data1.data}
              x={100}
              sigma2={props.sigma2}
              xScale={xScale}
              yScale={yScale}
              linex={linex}
              mu={props.mu}
              sample={sample}
              animating={props.animating}
            />
            {props.algo == "newtonRaphson" && (
              <NewtonParabola
                mu={props.mu}
                sigma2={props.sigma2}
                yMin={yMin}
                yMax={yMax}
                xMin={xMin}
                xScale={xScale}
                yScale={yScale}
                linex={linex}
                llTheta={llTheta}
                deriv={deriv}
                hessian={hessian}
                count={props.count}
              />
            )}
            {props.algo == "gradientAscent" && (
              <>
                <circle
                  cy={yScale(gradientNext.points.sigma2)}
                  cx={xScale(gradientNextLL)}
                  r="5"
                  className="logLikNewtonX--approx"
                />
                <line
                  className="LogLikNewton--maxima"
                  x1={xScale(xMin)}
                  x2={xScale(gradientNextLL)}
                  y1={yScale(gradientNext.points.sigma2)}
                  y2={yScale(gradientNext.points.sigma2)}
                />
              </>
            )}
          </g>
        </g>
        <g clipPath="url(#clipSigma2)">
          <animated.g
            {...bind()}
            transform={spring.xy.interpolate(
              (x, y) =>
                `translate(${xScale(logLikSum(sample, x, y))}, ${yScale(y)})`
            )}
            className="draggable"
          >
            <circle cx={margin.left} cy={0} r="5" className="logLikX" />
            <animated.line
              className="deriv"
              x1={spring.xy.interpolate(
                (x, y) =>
                  margin.left + xScale(xMin - delta * dSigma2(sample, x, y))
              )}
              x2={spring.xy.interpolate(
                (x, y) =>
                  margin.left + xScale(xMin + delta * dSigma2(sample, x, y))
              )}
              y1={yScale(yMax - delta)}
              y2={yScale(yMax + delta)}
            />

            <Tooltip
              theta={props.theta}
              thetaLab={props.thetaLab}
              ll={llTheta}
              deriv={deriv}
            />
          </animated.g>
        </g>
      </g>

      <defs>
        <clipPath id="clipSigma">
          <rect id="clip-rect2" x="0" y="-10" width={w} height={h + 10} />
        </clipPath>
        <clipPath id="clipSigma2">
          <rect
            id="clip-rect2"
            x={margin.left}
            y={-10}
            width={w + 100}
            height={h + 10}
          />
        </clipPath>
        <clipPath id="clipQuadApprox">
          <rect id="clip-rect2" x="0" y="-10" width={h + 100} height={h + 10} />
        </clipPath>
      </defs>
    </svg>
  );
}
Example #21
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 #22
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 #23
Source File: log.js    From cs-wiki with GNU General Public License v3.0 4 votes vote down vote up
export function loggish(transform) {
  var scale = transform(transformLog, transformExp),
      domain = scale.domain,
      base = 10,
      logs,
      pows;

  function rescale() {
    logs = logp(base), pows = powp(base);
    if (domain()[0] < 0) {
      logs = reflect(logs), pows = reflect(pows);
      transform(transformLogn, transformExpn);
    } else {
      transform(transformLog, transformExp);
    }
    return scale;
  }

  scale.base = function(_) {
    return arguments.length ? (base = +_, rescale()) : base;
  };

  scale.domain = function(_) {
    return arguments.length ? (domain(_), rescale()) : domain();
  };

  scale.ticks = function(count) {
    var d = domain(),
        u = d[0],
        v = d[d.length - 1],
        r;

    if (r = v < u) i = u, u = v, v = i;

    var i = logs(u),
        j = logs(v),
        p,
        k,
        t,
        n = count == null ? 10 : +count,
        z = [];

    if (!(base % 1) && j - i < n) {
      i = Math.round(i) - 1, j = Math.round(j) + 1;
      if (u > 0) for (; i < j; ++i) {
        for (k = 1, p = pows(i); k < base; ++k) {
          t = p * k;
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      } else for (; i < j; ++i) {
        for (k = base - 1, p = pows(i); k >= 1; --k) {
          t = p * k;
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      }
    } else {
      z = ticks(i, j, Math.min(j - i, n)).map(pows);
    }

    return r ? z.reverse() : z;
  };

  scale.tickFormat = function(count, specifier) {
    if (specifier == null) specifier = base === 10 ? ".0e" : ",";
    if (typeof specifier !== "function") specifier = format(specifier);
    if (count === Infinity) return specifier;
    if (count == null) count = 10;
    var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
    return function(d) {
      var i = d / pows(Math.round(logs(d)));
      if (i * base < base - 0.5) i *= base;
      return i <= k ? specifier(d) : "";
    };
  };

  scale.nice = function() {
    return domain(nice(domain(), {
      floor: function(x) { return pows(Math.floor(logs(x))); },
      ceil: function(x) { return pows(Math.ceil(logs(x))); }
    }));
  };

  return scale;
}
Example #24
Source File: indexRollupNext.js    From t-viSNE with MIT License 4 votes vote down vote up
function color() {
  var scale = scaleLinear(),
      shape = "rect",
      shapeWidth = 15,
      shapeHeight = 15,
      shapeRadius = 10,
      shapePadding = 2,
      cells = [5],
      cellFilter = void 0,
      labels = [],
      classPrefix = "",
      useClass = false,
      title = "",
      locale = helper.d3_defaultLocale,
      specifier = helper.d3_defaultFormatSpecifier,
      labelOffset = 10,
      labelAlign = "middle",
      labelDelimiter = helper.d3_defaultDelimiter,
      labelWrap = void 0,
      orient = "vertical",
      ascending = false,
      path = void 0,
      titleWidth = void 0,
      legendDispatcher = dispatch("cellover", "cellout", "cellclick");

  function legend(svg) {
    var type = helper.d3_calcType(scale, ascending, cells, labels, locale.format(specifier), labelDelimiter),
        legendG = svg.selectAll("g").data([scale]);

    legendG.enter().append("g").attr("class", classPrefix + "legendCells");

    if (cellFilter) {
      helper.d3_filterCells(type, cellFilter);
    }

    var cell = svg.select("." + classPrefix + "legendCells").selectAll("." + classPrefix + "cell").data(type.data);

    var cellEnter = cell.enter().append("g").attr("class", classPrefix + "cell");
    cellEnter.append(shape).attr("class", classPrefix + "swatch");

    var shapes = svg.selectAll("g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch").data(type.data);

    //add event handlers
    helper.d3_addEvents(cellEnter, legendDispatcher);

    cell.exit().transition().style("opacity", 0).remove();
    shapes.exit().transition().style("opacity", 0).remove();

    shapes = shapes.merge(shapes);

    helper.d3_drawShapes(shape, shapes, shapeHeight, shapeWidth, shapeRadius, path);
    var text = helper.d3_addText(svg, cellEnter, type.labels, classPrefix, labelWrap);

    // we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
    cell = cellEnter.merge(cell);

    // sets placement
    var textSize = text.nodes().map(function (d) {
      return d.getBBox();
    }),
        shapeSize = shapes.nodes().map(function (d) {
      return d.getBBox();
    });
    //sets scale
    //everything is fill except for line which is stroke,
    if (!useClass) {
      if (shape == "line") {
        shapes.style("stroke", type.feature);
      } else {
        shapes.style("fill", type.feature);
      }
    } else {
      shapes.attr("class", function (d) {
        return classPrefix + "swatch " + type.feature(d);
      });
    }

    var cellTrans = void 0,
        textTrans = void 0,
        textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1;

    //positions cells and text
    if (orient === "vertical") {
      (function () {
        var cellSize = textSize.map(function (d, i) {
          return Math.max(d.height, shapeSize[i].height);
        });

        cellTrans = function cellTrans(d, i) {
          var height = sum(cellSize.slice(0, i));
          return "translate(0, " + (height + i * shapePadding) + ")";
        };

        textTrans = function textTrans(d, i) {
          return "translate( " + (shapeSize[i].width + shapeSize[i].x + labelOffset) + ", " + (shapeSize[i].y + shapeSize[i].height / 2 + 5) + ")";
        };
      })();
    } else if (orient === "horizontal") {
      cellTrans = function cellTrans(d, i) {
        return "translate(" + i * (shapeSize[i].width + shapePadding) + ",0)";
      };
      textTrans = function textTrans(d, i) {
        return "translate(" + (shapeSize[i].width * textAlign + shapeSize[i].x) + ",\n          " + (shapeSize[i].height + shapeSize[i].y + labelOffset + 8) + ")";
      };
    }

    helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign);
    helper.d3_title(svg, title, classPrefix, titleWidth);

    cell.transition().style("opacity", 1);
  }

  legend.scale = function (_) {
    if (!arguments.length) return scale;
    scale = _;
    return legend;
  };

  legend.cells = function (_) {
    if (!arguments.length) return cells;
    if (_.length > 1 || _ >= 2) {
      cells = _;
    }
    return legend;
  };

  legend.cellFilter = function (_) {
    if (!arguments.length) return cellFilter;
    cellFilter = _;
    return legend;
  };

  legend.shape = function (_, d) {
    if (!arguments.length) return shape;
    if (_ == "rect" || _ == "circle" || _ == "line" || _ == "path" && typeof d === "string") {
      shape = _;
      path = d;
    }
    return legend;
  };

  legend.shapeWidth = function (_) {
    if (!arguments.length) return shapeWidth;
    shapeWidth = +_;
    return legend;
  };

  legend.shapeHeight = function (_) {
    if (!arguments.length) return shapeHeight;
    shapeHeight = +_;
    return legend;
  };

  legend.shapeRadius = function (_) {
    if (!arguments.length) return shapeRadius;
    shapeRadius = +_;
    return legend;
  };

  legend.shapePadding = function (_) {
    if (!arguments.length) return shapePadding;
    shapePadding = +_;
    return legend;
  };

  legend.labels = function (_) {
    if (!arguments.length) return labels;
    labels = _;
    return legend;
  };

  legend.labelAlign = function (_) {
    if (!arguments.length) return labelAlign;
    if (_ == "start" || _ == "end" || _ == "middle") {
      labelAlign = _;
    }
    return legend;
  };

  legend.locale = function (_) {
    if (!arguments.length) return locale;
    locale = formatLocale(_);
    return legend;
  };

  legend.labelFormat = function (_) {
    if (!arguments.length) return legend.locale().format(specifier);
    specifier = formatSpecifier(_);
    return legend;
  };

  legend.labelOffset = function (_) {
    if (!arguments.length) return labelOffset;
    labelOffset = +_;
    return legend;
  };

  legend.labelDelimiter = function (_) {
    if (!arguments.length) return labelDelimiter;
    labelDelimiter = _;
    return legend;
  };

  legend.labelWrap = function (_) {
    if (!arguments.length) return labelWrap;
    labelWrap = _;
    return legend;
  };

  legend.useClass = function (_) {
    if (!arguments.length) return useClass;
    if (_ === true || _ === false) {
      useClass = _;
    }
    return legend;
  };

  legend.orient = function (_) {
    if (!arguments.length) return orient;
    _ = _.toLowerCase();
    if (_ == "horizontal" || _ == "vertical") {
      orient = _;
    }
    return legend;
  };

  legend.ascending = function (_) {
    if (!arguments.length) return ascending;
    ascending = !!_;
    return legend;
  };

  legend.classPrefix = function (_) {
    if (!arguments.length) return classPrefix;
    classPrefix = _;
    return legend;
  };

  legend.title = function (_) {
    if (!arguments.length) return title;
    title = _;
    return legend;
  };

  legend.titleWidth = function (_) {
    if (!arguments.length) return titleWidth;
    titleWidth = _;
    return legend;
  };

  legend.textWrap = function (_) {
    if (!arguments.length) return textWrap;
    textWrap = _;
    return legend;
  };

  legend.on = function () {
    var value = legendDispatcher.on.apply(legendDispatcher, arguments);
    return value === legendDispatcher ? legend : value;
  };

  return legend;
}
Example #25
Source File: indexRollupNext.js    From t-viSNE with MIT License 4 votes vote down vote up
function size() {
  var scale = scaleLinear(),
      shape = "rect",
      shapeWidth = 15,
      shapePadding = 2,
      cells = [5],
      cellFilter = void 0,
      labels = [],
      classPrefix = "",
      title = "",
      locale = helper.d3_defaultLocale,
      specifier = helper.d3_defaultFormatSpecifier,
      labelOffset = 10,
      labelAlign = "middle",
      labelDelimiter = helper.d3_defaultDelimiter,
      labelWrap = void 0,
      orient = "vertical",
      ascending = false,
      path = void 0,
      titleWidth = void 0,
      legendDispatcher = dispatch("cellover", "cellout", "cellclick");

  function legend(svg) {
    var type = helper.d3_calcType(scale, ascending, cells, labels, locale.format(specifier), labelDelimiter),
        legendG = svg.selectAll("g").data([scale]);

    if (cellFilter) {
      helper.d3_filterCells(type, cellFilter);
    }

    legendG.enter().append("g").attr("class", classPrefix + "legendCells");

    var cell = svg.select("." + classPrefix + "legendCells").selectAll("." + classPrefix + "cell").data(type.data);
    var cellEnter = cell.enter().append("g").attr("class", classPrefix + "cell");
    cellEnter.append(shape).attr("class", classPrefix + "swatch");

    var shapes = svg.selectAll("g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch");

    //add event handlers
    helper.d3_addEvents(cellEnter, legendDispatcher);

    cell.exit().transition().style("opacity", 0).remove();

    shapes.exit().transition().style("opacity", 0).remove();
    shapes = shapes.merge(shapes);

    //creates shape
    if (shape === "line") {
      helper.d3_drawShapes(shape, shapes, 0, shapeWidth);
      shapes.attr("stroke-width", type.feature);
    } else {
      helper.d3_drawShapes(shape, shapes, type.feature, type.feature, type.feature, path);
    }

    var text = helper.d3_addText(svg, cellEnter, type.labels, classPrefix, labelWrap);

    // we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
    cell = cellEnter.merge(cell);

    //sets placement

    var textSize = text.nodes().map(function (d) {
      return d.getBBox();
    }),
        shapeSize = shapes.nodes().map(function (d, i) {
      var bbox = d.getBBox();
      var stroke = scale(type.data[i]);

      if (shape === "line" && orient === "horizontal") {
        bbox.height = bbox.height + stroke;
      } else if (shape === "line" && orient === "vertical") {
        bbox.width = bbox.width;
      }
      return bbox;
    });

    var maxH = max(shapeSize, function (d) {
      return d.height + d.y;
    }),
        maxW = max(shapeSize, function (d) {
      return d.width + d.x;
    });

    var cellTrans = void 0,
        textTrans = void 0,
        textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1;

    //positions cells and text
    if (orient === "vertical") {
      (function () {
        var cellSize = textSize.map(function (d, i) {
          return Math.max(d.height, shapeSize[i].height);
        });
        var y = shape == "circle" || shape == "line" ? shapeSize[0].height / 2 : 0;
        cellTrans = function cellTrans(d, i) {
          var height = sum(cellSize.slice(0, i));

          return "translate(0, " + (y + height + i * shapePadding) + ")";
        };

        textTrans = function textTrans(d, i) {
          return "translate( " + (maxW + labelOffset) + ",\n          " + (shapeSize[i].y + shapeSize[i].height / 2 + 5) + ")";
        };
      })();
    } else if (orient === "horizontal") {
      (function () {
        cellTrans = function cellTrans(d, i) {
          var width = sum(shapeSize.slice(0, i), function (d) {
            return d.width;
          });
          var y = shape == "circle" || shape == "line" ? maxH / 2 : 0;
          return "translate(" + (width + i * shapePadding) + ", " + y + ")";
        };

        var offset = shape == "line" ? maxH / 2 : maxH;
        textTrans = function textTrans(d, i) {
          return "translate( " + (shapeSize[i].width * textAlign + shapeSize[i].x) + ",\n              " + (offset + labelOffset) + ")";
        };
      })();
    }

    helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign);
    helper.d3_title(svg, title, classPrefix, titleWidth);

    cell.transition().style("opacity", 1);
  }

  legend.scale = function (_) {
    if (!arguments.length) return scale;
    scale = _;
    return legend;
  };

  legend.cells = function (_) {
    if (!arguments.length) return cells;
    if (_.length > 1 || _ >= 2) {
      cells = _;
    }
    return legend;
  };

  legend.cellFilter = function (_) {
    if (!arguments.length) return cellFilter;
    cellFilter = _;
    return legend;
  };

  legend.shape = function (_, d) {
    if (!arguments.length) return shape;
    if (_ == "rect" || _ == "circle" || _ == "line") {
      shape = _;
      path = d;
    }
    return legend;
  };

  legend.shapeWidth = function (_) {
    if (!arguments.length) return shapeWidth;
    shapeWidth = +_;
    return legend;
  };

  legend.shapePadding = function (_) {
    if (!arguments.length) return shapePadding;
    shapePadding = +_;
    return legend;
  };

  legend.labels = function (_) {
    if (!arguments.length) return labels;
    labels = _;
    return legend;
  };

  legend.labelAlign = function (_) {
    if (!arguments.length) return labelAlign;
    if (_ == "start" || _ == "end" || _ == "middle") {
      labelAlign = _;
    }
    return legend;
  };

  legend.locale = function (_) {
    if (!arguments.length) return locale;
    locale = formatLocale(_);
    return legend;
  };

  legend.labelFormat = function (_) {
    if (!arguments.length) return legend.locale().format(specifier);
    specifier = formatSpecifier(_);
    return legend;
  };

  legend.labelOffset = function (_) {
    if (!arguments.length) return labelOffset;
    labelOffset = +_;
    return legend;
  };

  legend.labelDelimiter = function (_) {
    if (!arguments.length) return labelDelimiter;
    labelDelimiter = _;
    return legend;
  };

  legend.labelWrap = function (_) {
    if (!arguments.length) return labelWrap;
    labelWrap = _;
    return legend;
  };

  legend.orient = function (_) {
    if (!arguments.length) return orient;
    _ = _.toLowerCase();
    if (_ == "horizontal" || _ == "vertical") {
      orient = _;
    }
    return legend;
  };

  legend.ascending = function (_) {
    if (!arguments.length) return ascending;
    ascending = !!_;
    return legend;
  };

  legend.classPrefix = function (_) {
    if (!arguments.length) return classPrefix;
    classPrefix = _;
    return legend;
  };

  legend.title = function (_) {
    if (!arguments.length) return title;
    title = _;
    return legend;
  };

  legend.titleWidth = function (_) {
    if (!arguments.length) return titleWidth;
    titleWidth = _;
    return legend;
  };

  legend.on = function () {
    var value = legendDispatcher.on.apply(legendDispatcher, arguments);
    return value === legendDispatcher ? legend : value;
  };

  return legend;
}
Example #26
Source File: indexRollupNext.js    From t-viSNE with MIT License 4 votes vote down vote up
function symbol() {
  var scale = scaleLinear(),
      shape = "path",
      shapeWidth = 15,
      shapeHeight = 15,
      shapeRadius = 10,
      shapePadding = 5,
      cells = [5],
      cellFilter = void 0,
      labels = [],
      classPrefix = "",
      title = "",
      locale = helper.d3_defaultLocale,
      specifier = helper.d3_defaultFormatSpecifier,
      labelAlign = "middle",
      labelOffset = 10,
      labelDelimiter = helper.d3_defaultDelimiter,
      labelWrap = void 0,
      orient = "vertical",
      ascending = false,
      titleWidth = void 0,
      legendDispatcher = dispatch("cellover", "cellout", "cellclick");

  function legend(svg) {
    var type = helper.d3_calcType(scale, ascending, cells, labels, locale.format(specifier), labelDelimiter),
        legendG = svg.selectAll("g").data([scale]);

    if (cellFilter) {
      helper.d3_filterCells(type, cellFilter);
    }

    legendG.enter().append("g").attr("class", classPrefix + "legendCells");

    var cell = svg.select("." + classPrefix + "legendCells").selectAll("." + classPrefix + "cell").data(type.data);
    var cellEnter = cell.enter().append("g").attr("class", classPrefix + "cell");
    cellEnter.append(shape).attr("class", classPrefix + "swatch");

    var shapes = svg.selectAll("g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch");

    //add event handlers
    helper.d3_addEvents(cellEnter, legendDispatcher);

    //remove old shapes
    cell.exit().transition().style("opacity", 0).remove();
    shapes.exit().transition().style("opacity", 0).remove();
    shapes = shapes.merge(shapes);

    helper.d3_drawShapes(shape, shapes, shapeHeight, shapeWidth, shapeRadius, type.feature);
    var text = helper.d3_addText(svg, cellEnter, type.labels, classPrefix, labelWrap);

    // we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
    cell = cellEnter.merge(cell);

    // sets placement
    var textSize = text.nodes().map(function (d) {
      return d.getBBox();
    }),
        shapeSize = shapes.nodes().map(function (d) {
      return d.getBBox();
    });

    var maxH = max(shapeSize, function (d) {
      return d.height;
    }),
        maxW = max(shapeSize, function (d) {
      return d.width;
    });

    var cellTrans = void 0,
        textTrans = void 0,
        textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1;

    //positions cells and text
    if (orient === "vertical") {
      (function () {
        var cellSize = textSize.map(function (d, i) {
          return Math.max(maxH, d.height);
        });

        cellTrans = function cellTrans(d, i) {
          var height = sum(cellSize.slice(0, i));
          return "translate(0, " + (height + i * shapePadding) + " )";
        };
        textTrans = function textTrans(d, i) {
          return "translate( " + (maxW + labelOffset) + ",\n              " + (shapeSize[i].y + shapeSize[i].height / 2 + 5) + ")";
        };
      })();
    } else if (orient === "horizontal") {
      cellTrans = function cellTrans(d, i) {
        return "translate( " + i * (maxW + shapePadding) + ",0)";
      };
      textTrans = function textTrans(d, i) {
        return "translate( " + (shapeSize[i].width * textAlign + shapeSize[i].x) + ",\n              " + (maxH + labelOffset) + ")";
      };
    }

    helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign);
    helper.d3_title(svg, title, classPrefix, titleWidth);
    cell.transition().style("opacity", 1);
  }

  legend.scale = function (_) {
    if (!arguments.length) return scale;
    scale = _;
    return legend;
  };

  legend.cells = function (_) {
    if (!arguments.length) return cells;
    if (_.length > 1 || _ >= 2) {
      cells = _;
    }
    return legend;
  };

  legend.cellFilter = function (_) {
    if (!arguments.length) return cellFilter;
    cellFilter = _;
    return legend;
  };

  legend.shapePadding = function (_) {
    if (!arguments.length) return shapePadding;
    shapePadding = +_;
    return legend;
  };

  legend.labels = function (_) {
    if (!arguments.length) return labels;
    labels = _;
    return legend;
  };

  legend.labelAlign = function (_) {
    if (!arguments.length) return labelAlign;
    if (_ == "start" || _ == "end" || _ == "middle") {
      labelAlign = _;
    }
    return legend;
  };

  legend.locale = function (_) {
    if (!arguments.length) return locale;
    locale = formatLocale(_);
    return legend;
  };

  legend.labelFormat = function (_) {
    if (!arguments.length) return legend.locale().format(specifier);
    specifier = formatSpecifier(_);
    return legend;
  };

  legend.labelOffset = function (_) {
    if (!arguments.length) return labelOffset;
    labelOffset = +_;
    return legend;
  };

  legend.labelDelimiter = function (_) {
    if (!arguments.length) return labelDelimiter;
    labelDelimiter = _;
    return legend;
  };

  legend.labelWrap = function (_) {
    if (!arguments.length) return labelWrap;
    labelWrap = _;
    return legend;
  };

  legend.orient = function (_) {
    if (!arguments.length) return orient;
    _ = _.toLowerCase();
    if (_ == "horizontal" || _ == "vertical") {
      orient = _;
    }
    return legend;
  };

  legend.ascending = function (_) {
    if (!arguments.length) return ascending;
    ascending = !!_;
    return legend;
  };

  legend.classPrefix = function (_) {
    if (!arguments.length) return classPrefix;
    classPrefix = _;
    return legend;
  };

  legend.title = function (_) {
    if (!arguments.length) return title;
    title = _;
    return legend;
  };

  legend.titleWidth = function (_) {
    if (!arguments.length) return titleWidth;
    titleWidth = _;
    return legend;
  };

  legend.on = function () {
    var value = legendDispatcher.on.apply(legendDispatcher, arguments);
    return value === legendDispatcher ? legend : value;
  };

  return legend;
}
Example #27
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 #28
Source File: test.legendcolor.js    From t-viSNE with MIT License 4 votes vote down vote up
// describe('d3-legend', function () {
//     var d3Legend

//     beforeEach(function () {
//         d3Legend = require('../no-extend')
//     })

//     it('should export an object', function () {
//         expect(d3Legend).to.be.an('object')
//     })

//     it('should have color, size & symbol functions', function () {
//         ['color','size','symbol'].forEach(function (fieldName) {
//             expect(d3Legend[fieldName]).to.be.a('function')
//         })
//     })
// })
describe('d3-legend #legendColor', function() {
	it('exports a function', function() {
		expect(color).to.be.a('function');
	});
	it('invoking exported function does not throw an error and returns a legend function', function() {
		let result;
		expect(color).to.be.a('function');
		expect(function() {
			result = color();
		}).to.not.throw();
		expect(result).to.be.a('function');
		expect(result.name).to.equal('legend');
	});
	it('errors when not passed a SVG', function() {
		let result;
		expect(color).to.be.a('function');
		expect(function() {
			result = color();
		}).to.not.throw();
		expect(result).to.be.a('function');
		expect(result.name).to.equal('legend');
		// TODO add formal error handling and assert on error message
		// }).to.throw('need to provide SVG');
		expect(function() {
			result();
		}).to.throw();
	});
	// TODO renable to create failing assertion to verify shapes.data is rebound
	it.skip('properly rebinds the updated range data for the legend shapes', function() {
		let result, aLegend;
		let mockSvg = {
			attr(key, val) {
				this._attrs[key] = val;
				return this;
			},
			select() { return this; },
			append() { return this; },
			enter() { return this; },
			data() { return this; },
			selectAll() {
				return this;
			}
		};
		mockSvg._attrs = {};
		this._copied = helper.d3_calcType;
		helper.d3_calcType = null;
		helper.d3_calcType = function() {
			expect(arguments.length).to.equal(6);
			return {};
		};


		expect(color).to.be.a('function');
		expect(function() {
			result = color();
		}).to.not.throw();
		expect(result).to.be.a('function');
		expect(result.name).to.equal('legend');
		// TODO add formal error handling and assert on error message
		// }).to.throw('need to provide SVG');
		expect(function() {
			aLegend = result(mockSvg);
		}).to.not.throw();
		expect(aLegend).to.be.an('Object');
	});

  it('should have a locale', function () {
    let result = color();
    expect(result.locale).to.be.a('function');
  });

  it('should redefine label\'s format with a string', function () {
    let result = color();
    let testValue = 1.00;
    let initial = result.labelFormat();

    result.labelFormat('.2f');

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine label\'s format with a format function', function () {
    let result = color();
    let testValue = 1.00;
    let initial = result.labelFormat();
    result.labelFormat(format('.2f'));

    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1.00');
  });

  it('should redefine the locale with a new locale definition', function () {
    let result = color();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,0')
  })

  it('should keep the format specifier after a locale update', function () {
    let result = color();
    let testValue = 1.00;

    let initial = result.labelFormat();
    let frFr = {
      decimal: ',',
      thousands: '.',
      grouping: [3],
      currency: ['', '\u00a0€'],
      percent: "\u202f%"
    };

    result.labelFormat(format('.2f'));
    result.locale(frFr)
    expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue));
    expect(result.labelFormat()(testValue)).to.be.equal('1,00')
  })
});
Example #29
Source File: Viz.js    From likelihood with MIT License 4 votes vote down vote up
Content = ({ openSettings, vizState, toggleDrawer }) => {
  const classes = useStyles();
  const [highlight, setHighlight] = useState();
  const theme = useTheme();
  const matchesBreak = useMediaQuery(theme.breakpoints.up("sm"));

  const {
    mu,
    muHat,
    muNull,
    muTheta,
    sigma2Theta,
    sigma2,
    sigma2Hat,
    sigma2MleNull,
    sample,
    n
  } = vizState;

  // Data sets
  const dataMu = genLogLikCurve(sample, mu, sigma2, "mu", muTheta, sigma2Theta);
  const dataSigma = genLogLikCurve(
    sample,
    mu,
    sigma2,
    "sigma",
    muTheta,
    sigma2Theta
  );
  const derivMu = dMu(10, mu, muHat, sigma2);
  const derivMuN = dMu(n, muNull, muHat, sigma2Hat);
  const derivMuNull = dMu(n, muNull, muHat, sigma2MleNull);
  const deriv2MuNull = d2Mu(n, sigma2MleNull);
  const estllThetaMLE = estimatedLogLik(n, mu, mu, sigma2Hat);
  const estllThetaNull = estimatedLogLik(n, muNull, muHat, sigma2Hat);
  const derivSigma2 = dSigma2(sample, mu, sigma2);
  const y = vizState.sample.map(y => format(".1f")(y)).join(", ");
  const f2n = format(".2n");
  const eqDeriv1 = katex.renderToString(
    `U(\\mu_0, \\hat\\sigma_0^2) = \\frac{\\partial}{\\partial \\mu_0}\\ell(\\mu_0, \\hat\\sigma_0^2) = ${f2n(
      derivMuNull
    )} `,
    {
      displayMode: true,
      throwOnError: false
    }
  );
  const eqDeriv2 = katex.renderToString(
    `I(\\mu_0, \\hat\\sigma_0^2) = \\frac{\\partial^2}{\\partial \\mu_0^2}\\ell(\\mu_0, \\hat\\sigma_0^2) = ${-f2n(
      deriv2MuNull
    )}`,
    {
      displayMode: true,
      throwOnError: false
    }
  );
  const eqModel = katex.renderToString("y \\sim \\mathcal N(\\mu, \\sigma^2)", {
    displayMode: false,
    throwOnError: false
  });
  return (
    <div>
      <Container maxWidth="lg">
        <Typography variant="h2" align="center" gutterBottom>
          Likelihood Calculation
        </Typography>
        <Container className={classes.textContent}>
          <Typography variant="body1" gutterBottom>
            Before we do any calculations, we need some data. So, {"here's"} 10
            random observations from a normal distribution with unknown mean (μ)
            and variance (σ²).
          </Typography>
          <Typography
            variant="body1"
            align="center"
            gutterBottom
          >{`Y = [${y}]`}</Typography>
          <Typography variant="body1" gutterBottom>
            We also need to assume a model, we're gonna go with the model
            that we know generated this data:{" "}
            <span dangerouslySetInnerHTML={{ __html: eqModel }} />. The
            challenge now is to find what combination of values for μ and σ²
            maximize the likelihood of observing this data (given our
            assumed model). Try moving the sliders around to see what happens.
          </Typography>
        </Container>
        <div className={classes.stickySlider}>
          <Grid
            container
            direction="column"
            justify="center"
            alignItems="center"
            className={classes.blur}
          >
            <Slider
              name="mu"
              label="Mean (μ)"
              thetaHat={vizState.muHat}
              value={vizState.mu}
              max={vizState.sliderMax}
              step={vizState.sliderStep}
              openSettings={openSettings}
              handleDrawer={toggleDrawer}
            />

            <Slider
              name="sigma2"
              label="Variance (σ²)"
              thetaHat={vizState.sigma2Hat}
              value={vizState.sigma2}
              min={1}
              max={vizState.sigma2Max}
              step={vizState.sliderStep}
              openSettings={openSettings}
              handleDrawer={toggleDrawer}
            />
          </Grid>
          <Grid
            container
            alignItems="flex-start"
            justify="flex-end"
            direction="row"
          >
            <ButtonSample
              M={vizState.muTheta}
              sigma2={vizState.sigma2Theta}
            />
          </Grid>
        </div>

        <Grid
          container
          spacing={3}
          alignItems="center"
          direction="row"
          justify="center"
          className={classes.gridContainer}
        >
          <Grid item md={6} xs={12}>
            <Paper className={classes.sampleDist}>
              <ResponsiveChart
                chart={SampleDist}
                {...vizState}
                highlight={highlight}
                setHighlight={setHighlight}
              />
            </Paper>
          </Grid>
          <Grid item md={6} xs={12}>
            <Paper className={classes.paper}>
              <Grid align="bottom" className={classes.logLikSum}>
                <Typography variant="body1" gutterBottom>
                  We can calculate the joint likelihood by multiplying the
                  densities for all observations. However, often we calculate
                  the log-likelihood instead, which is
                </Typography>
                <CalcLogLik
                  sample={vizState.sample}
                  mu={vizState.mu}
                  sigma={vizState.sigma2}
                  highlight={highlight}
                  setHighlight={setHighlight}
                />
                <Typography variant="body1" gutterBottom>
                  The combination of parameter values that give the largest
                  log-likelihood is the maximum likelihood estimates (MLEs).
                </Typography>
              </Grid>
            </Paper>
          </Grid>
        </Grid>

        <Typography variant="h2" align="center" gutterBottom>
          Finding the Maximum Likelihood Estimates
        </Typography>
        <Container className={classes.textContent}>
          <MleFirst />
        </Container>

        <Grid
          container
          alignItems="flex-end"
          direction="row"
          justify="center"
          spacing={0}
        >
          <Grid item xs={12} sm={6}>
            <Paper className={classes.paper}>
              <Typography
                variant="h4"
                component="h3"
                align="center"
                style={{
                  paddingBottom: "0em",
                  paddingTop: "0.5em",
                  paddingLeft: "0em"
                }}
              >
                Mean
              </Typography>
              <ResponsiveChart
                chart={LogLikPlot}
                {...vizState}
                data={dataMu}
                theta={mu}
                thetaLab="mu"
                deriv={derivMu}
              />
              <ResponsiveChart
                chart={ContourLogLik}
                {...vizState}
                data={dataSigma}
                theta={sigma2}
                thetaLab="sigma"
                deriv={derivSigma2}
              />
              <Typography align="right" variant="caption" component="p">Tip: You can move the values around by dragging them.</Typography>
            </Paper>
          </Grid>
          <Grid item xs={12} sm={6}>
            <Paper className={classes.paper}>
             <GradientAscent {...vizState} />
              <Typography
                variant="h4"
                component="h3"
                align="left"
                style={{
                  paddingBottom: "0.5em",
                  paddingTop: "1em",
                  paddingLeft: "3em"
                }}
              >
                Variance
              </Typography>
              <ResponsiveChart
                chart={LogLikPlotSigma}
                {...vizState}
                data={dataSigma}
                theta={sigma2}
                thetaLab="sigma"
                deriv={derivSigma2}
              />
            </Paper>
          </Grid>
        </Grid>

        <Typography
          variant="h2"
          align="center"
          gutterBottom
          style={{ paddingTop: "1em" }}
        >
          Inference
        </Typography>
        <Container className={classes.textContent}>
          <Typography gutterBottom>
            After {"we've"} found the MLEs we usually want to make some
            inferences, so {"let's"} focus on three common hypothesis tests. Use
            the sliders below to change the null hypothesis and the sample size.
          </Typography>
        </Container>
      </Container>
      <Container maxWidth="lg">
        <Grid container direction="row" justify="center" spacing={3}>
          <Grid item md={6} xs={12}>
            <Typography variant="h4" component="h2" align="center" gutterBottom>
              Illustration
            </Typography>
            <Slider
              name="n"
              label="Sample Size (n)"
              value={vizState.n}
              max={100}
              step={1}
              openSettings={openSettings}
              handleDrawer={toggleDrawer}
            />
            <Slider
              name="muNull"
              label="Null (μ0)"
              value={vizState.muNull}
              min={70}
              max={160}
              step={1}
              openSettings={openSettings}
              handleDrawer={toggleDrawer}
            />

            <div>
              <p>The score function evaluated at the null is, </p>
              <p dangerouslySetInnerHTML={{ __html: eqDeriv1 }} />
              <Typography variant="body1">
                The observed <b>Fisher information</b> is the negative of the
                second derivative. This is related to the curvature of the
                likelihood function -- try increasing the sample size and note
                that the peak gets narrower around the MLE and that the{" "}
                <em>information</em> increases. The inverse of I is also the
                variance of the MLE.
              </Typography>
              <p dangerouslySetInnerHTML={{ __html: eqDeriv2 }} />
            </div>
            <Paper className={classes.paper}>
              <ResponsiveChart
                chart={CurvaturePlot}
                {...vizState}
                theta={mu}
                thetaLab="mu"
                llThetaMLE={estllThetaMLE}
                llThetaNull={estllThetaNull}
                deriv={derivMuN}
              />
            </Paper>
          </Grid>
          <Grid item md={6} xs={12}>
            <Typography variant="h4" component="h2" align="center" gutterBottom>
              Hypothesis Tests
            </Typography>
            <TestTabs
              muNull={muNull}
              muHat={muHat}
              sigma2={sigma2Hat}
              sigma2Null={sigma2MleNull}
              derivMuNull={derivMuNull}
              deriv2MuNull={deriv2MuNull}
              n={n}
            />
          </Grid>
        </Grid>
      </Container>
    </div>
  );
}