diff --git a/gh-pages/distributions.js b/gh-pages/distributions.js new file mode 100644 index 0000000..969b31f --- /dev/null +++ b/gh-pages/distributions.js @@ -0,0 +1,140 @@ +/** List of distributions, arguments, and defaults **/ + +var distributions = { + "arcsine": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "beta": { + "argDefaults": [1, 1, 0, 1], + "argNames": ["v", "w", "min", "max"] + }, + "cauchy": { + "argDefaults": [1, 1], + "argNames": ["a", "b"] + }, + "chiSquare": { + "argDefaults": [1], + "argNames": ["df"] + }, + "cosine": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "doubleLog": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "erlang": { + "argDefaults": [1, 1], + "argNames": ["b", "c"] + }, + "exponential": { + "argDefaults": [1, 1], + "argNames": ["a", "b"] + }, + "extremeValue": { + "argDefaults": [0.5, 5, 0, 1], + "argNames": ["a", "b"] + }, + "fRatio": { + "argDefaults": [1, 1], + "argNames": ["v", "w"] + }, + "gamma": { + "argDefaults": [1, 1, 1], + "argNames": ["a", "b", "c"] + }, + "laplace": { + "argDefaults": [1, 1], + "argNames": ["a", "b"] + }, + "logarithmic": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "logistic": { + "argDefaults": [1, 1], + "argNames": ["a", "b"] + }, + "lognormal": { + "argDefaults": [1, 1, 1], + "argNames": ["a", "mu", "sigma"] + }, + "normal": { + "argDefaults": [1, 1], + "argNames": ["mu", "sigma"] + }, + "parabolic": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "pareto": { + "argDefaults": [1], + "argNames": ["c"] + }, + "pearson5": { + "argDefaults": [1, 1], + "argNames": ["b", "c"] + }, + "pearson6": { + "argDefaults": [1, 1, 1], + "argNames": ["b", "v", "w"] + }, + "power": { + "argDefaults": [1], + "argNames": ["c"] + }, + "rayleigh": { + "argDefaults": [1, 1], + "argNames": ["a", "b"] + }, + "studentT": { + "argDefaults": [1], + "argNames": ["df"] + }, + "triangular": { + "argDefaults": [0, 1, 1], + "argNames": ["min", "max", "c"] + }, + "uniform": { + "argDefaults": [0, 1], + "argNames": ["min", "max"] + }, + "weibull": { + "argDefaults": [1, 1, 1], + "argNames": ["a", "b", "c"] + }, + "bernoulli": { + "argDefaults": [0.5], + "argNames": ["p"] + }, + "binomial": { + "argDefaults": [10, 0.5], + "argNames": ["n", "p"] + }, + "geometric": { + "argDefaults": [0.5], + "argNames": ["p"] + }, + "hypergeometric": { + "argDefaults": [6, 10, 4], + "argNames": ["n", "N", "K"] + }, + "negativeBinomial": { + "argDefaults": [5, 0.5], + "argNames": ["s", "p"] + }, + "pascal": { + "argDefaults": [5, 0.5], + "argNames": ["s", "p"] + }, + "poisson": { + "argDefaults": [5], + "argNames": ["mu"] + }, + "uniformDiscrete": { + "argDefaults": [1, 10], + "argNames": ["i", "j"] + } +} diff --git a/gh-pages/graphs.js b/gh-pages/graphs.js new file mode 100644 index 0000000..43b21fb --- /dev/null +++ b/gh-pages/graphs.js @@ -0,0 +1,42 @@ +/** Graph to visualize normal dists **/ + +/** bin and normalise data so it can be plotted on a line graph **/ +function bin_data(values, nbins) { + nbins=nbins||100 + + var flatVals = _(values).values().flatten().value() + var max = _.max(flatVals) + var min = _.min(flatVals) + var steps = (max - min) / nbins + var bins = d3.range(min, max, steps) + var binner = d3.layout.histogram() + .bins(bins) + .frequency(false) // use probability + + // I want to remove start and end bins with few values in to improve display + var cuttofProb = 0.002 + var allBinned = binner(flatVals).map(v=>v.y/v.dx).map(v=>vv!=0) + i1=_.findLastIndex(allBinned,v=>v!=0) + bins2=bins.slice(i0,i1-i0) + + var binner = d3.layout.histogram() + .bins(bins2) + .frequency(false) // use probability + + // format for c3 + c3data = {x:'x'} + c3data.columns=[ + _.concat(['x'],bins) + ] + + // bin and adjust for bin width + for (var name in values) { + var vals = values[name] + normalisedData = binner(vals).map(v=>v.y/v.dx) + + var column = _.concat([name],normalisedData) + c3data.columns.push(column) + } + return c3data +} diff --git a/gh-pages/main.js b/gh-pages/main.js new file mode 100644 index 0000000..830ab70 --- /dev/null +++ b/gh-pages/main.js @@ -0,0 +1,93 @@ +var gui = new dat.GUI(); +var distGuiConfig = {}; +var chart; + +$(window).ready(function () { + + function genVals(sd, total) { + var intval = $('#intval').val() + + var f = random[sd] + var argDefaults = distributions[sd].argDefaults + var vals = [] + for (var i = 0; i < total; i++) { + vals.push(f.apply(random, argDefaults)) + } + return vals + } + + /** make/update chart for selected values **/ + function genSelected() { + var allVals = {} + for (var name in distGuiConfig) { + if (distributions.hasOwnProperty(name) && (distGuiConfig[name].on)) { + allVals[name] = genVals(name, distGuiConfig.npoints) + } + } + + var c3data = bin_data(allVals, distGuiConfig.bins) + + chart.load({ + columns: c3data.columns, + unload: true + }) + } + + + function loadDistGui() { + + // make config + initialOn = ['gamma', 'normal', 'cosine'] + distGuiConfig = { + npoints: 50000, + bins: 80 + } + + var npoints = gui.add(distGuiConfig, 'npoints').onChange(genSelected.bind(this)) + var bins = gui.add(distGuiConfig, 'bins').onChange(genSelected.bind(this)) + for (var name in distributions) { + if (distributions.hasOwnProperty(name)) { + var folder = gui.addFolder(name); + distGuiConfig[name] = { + on: initialOn.indexOf(name) > -1 + } + var button = folder.add(distGuiConfig[name], 'on'); + var args = distributions[name].argNames + var argDefaults = distributions[name].argDefaults + for (var i = 0; i < args.length; i++) { + var arg = args[i] + var defV = argDefaults[i] + distGuiConfig[name][arg] = defV + var controller = folder.add(distGuiConfig[name], arg, defV) + controller.onChange(genSelected.bind(this)); + } + button.onChange(genSelected.bind(this)); + if (distGuiConfig[name].on) folder.open() + } + } + + // init chart + chart = c3.generate({ + axis: { + x: { + tick: { + format: d3.format(".2g") + }, + label: 'outputs' + }, + y:{ + label: 'probability' + } + }, + data: { + x: 'x', + columns: [], + type: 'spline', + } + }); + } + + loadDistGui() + genSelected() + +}); diff --git a/gh-pages/style.css b/gh-pages/style.css new file mode 100644 index 0000000..e69de29 diff --git a/index.html b/index.html index 248cb40..f2e9223 100644 --- a/index.html +++ b/index.html @@ -7,52 +7,9 @@ Statistical Distributions - - - - - - - - - @@ -61,487 +18,36 @@

-

Density Histogram

- -

Distribution Histogram

+ +

Distribution

-
-
- Parameters -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- -
-
-
-
- + - function line(values, name) { - // http://bl.ocks.org/phil-pedruco/88cb8a51cdce45f13c7e - // line chart based on http://bl.ocks.org/mbostock/3883245 - var margin = { - top: 20, - right: 20, - bottom: 30, - left: 50 - }, - width = 960 - margin.left - margin.right, - height = 500 - margin.top - margin.bottom; - var flatVals = _(values).values().flatten().value() - var max = _.max(flatVals) - var min = _.min(flatVals) - max=_.clamp(max,0,40) - min=_.clamp(min,-40,0) + + - - - var x = d3.scale.linear() - .domain([min, max]) - .range([0, width]); - - var y = d3.scale.linear() - .range([height, 0]); - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); - - var svg = d3.select("body").append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - x.domain(d3.extent([min,max])); - y.domain([0, 1]); - - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - - // legend - var colors = d3.scale.category10() - var names = Object.keys(values) - var ordinal = d3.scale.category10() - .domain(names) - - svg.append("g") - .attr("class", "legendOrdinal") - .attr("transform", "translate(" + width * 0.8 + ",20)"); - - var legendOrdinal = d3.legend.color() - .shape("path", d3.svg.symbol().type("triangle-up").size(150)()) - .shapePadding(10) - .scale(ordinal); - - svg.select(".legendOrdinal") - .call(legendOrdinal); - - var allData = {} - for (var name in values) { - var nameInd = Object.keys(values).indexOf(name) - var vals = values[name] - var dmin = _.min(vals) - var dmax = _.max(vals) - dmax=_.clamp(dmax,min,max) - dmin=_.clamp(dmin,min,max) - var nbins = vals.length / 100 - var dsteps = (dmax - dmin) / nbins - var dbins = d3.range(dmin, dmax, dsteps) - allData[name] = d3.layout.histogram() - .bins(dbins) - (vals); - - // normalise counts - - // scale by bin width and total count - allData[name] = allData[name] - .map(v => { - v.y = v.y / values[name].length * ((dmax - dmin) / v.dx); - return v; - }) - - // scale by max y - var maxy = _(allData[name]).map(v => v.y).max() - allData[name] = allData[name] - .map(v => { - v.y = v.y / maxy; - return v; - }) - - var line = d3.svg.line() - .x(function(d) { - return x(d.x); - }) - .y(function(d) { - return y(d.y); - }) - .interpolate('basis') - - svg.append("path") - .datum(allData[name]) - .attr("class", "line") - .attr("d", line) - .style("stroke", colors(nameInd)); - - console.log( - name, - _(allData[name]).map(r => r.x).min(), - _(allData[name]).map(r => r.x).max(), - _(allData[name]).map(r => r.y).min(), - _(allData[name]).map(r => r.y).max() - ) - } - - } - - - /* graph from http://bl.ocks.org/mbostock/3048450*/ - function hist(values, nbins, name) { - if (!nbins) nbins = bins || 20 - - // A formatter for counts. - var formatCount = d3.format(",.0f"); - var min = Math.min.apply(null, values); - var max = Math.max.apply(null, values); - - var margin = { - top: 10, - right: 30, - bottom: 30, - left: 30 - }, - width = 960 - margin.left - margin.right, - height = 500 - margin.top - margin.bottom; - - var x = d3.scale.linear() - .domain([min, max]) - .range([0, width]); - - // Generate a histogram using N uniformly-spaced bins. - var data = d3.layout.histogram() - .bins(x.ticks(bins)) - (values); - - var y = d3.scale.linear() - .domain([d3.min(data, function(d) { - return d.y; - }), d3.max(data, function(d) { - return d.y; - })]) - .range([height, 0]); - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); - - var svg = d3.select("body").append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - var bar = svg.selectAll(".bar") - .data(data) - .enter().append("g") - .attr("class", "bar") - .attr("transform", function(d) { - return "translate(" + x(d.x) + "," + y(d.y) + ")"; - }); - - bar.append("rect") - .attr("x", 1) - .attr("width", x(data[0].dx) - 1) - .attr("height", function(d) { - return height - y(d.y); - }); - - // bind labels - bar.append("text") - .attr("dy", ".75em") - .attr("y", 6) - .attr("x", x(data[0].dx) / 2) - .attr("text-anchor", "middle") - .text(function(d) { - return formatCount(d.y); - }); - - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - var g = svg.append("g") - //.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - var gridX = g.append("g") - .attr("class", "grid") - .attr("transform", "translate(0," + height + ")") - .call(xAxis - .tickSize(-height, 0, 0) - .tickFormat("") - ); - - var gridY = g.append("g") - .attr("class", "grid") - .call(yAxis - .tickSize(-width, 0, 0) - .tickFormat("") - ); - - var label = g.append("svg:text") - .attr("class", "plotLab") - .attr("text-anchor", "middle") - .attr("x", width / 2) - .attr("y", height / 20) - .text(name); - } - - $(function() { - - - - /** generate random numbers **/ - function gen() { - - // get values from buttons - var sd = $('#sd').val() - var total = $('#total').val() - // var intval = $('#intval').val() - - var f = random[sd] - var argDefaults = distributions[sd].argDefaults - var vals = genVals(sd,total) - - hist(vals,20,sd) - - // var o={} - // o[sd]=vals - // line(o) - } - - function genVals(sd,total){ - var intval = $('#intval').val() - - var f = random[sd] - var argDefaults = distributions[sd].argDefaults - var vals = [] - for (var i = 0; i < total; i++) { - vals.push(f.apply(random, argDefaults)) - } - return vals - } - - var total = $('#total').val() - var allVals={} - for (var sd in distributions) { - if (distributions.hasOwnProperty(sd)) { - allVals[sd]=genVals(sd,total) - } - } - line(allVals) - - /** change Distribution **/ - function changeDi(event) { - var dist = $('#sd').val() - } - - var diMeta = Object.keys(random) - $.each(diMeta, function(i, e) { - $('#sd').append(''); - }); - $('#sd').on('change', changeDi); - $('#gen').on('click', gen); - - changeDi(); - }); - + + + + + +