Public
Edited
Sep 1, 2023
Importers
Insert cell
md`# Histogram1D
use: import {viewof Histogram1D} from "@ahojsenn/histogram1d"
<div id="testhisto"></div>`
Insert cell
histogram = {
let h = new Histogram1D ( 0, 10 , 30)
h.margin = ({ top: 25, right: 50, bottom: 20, left: 20 });
h.title = "test 1D histogram";
let Zwölferregel = () => {let z = 0; for (let i=0; i<12; i++) {z += Math.random()} return z}
h.testfill(500, Zwölferregel);
//h.testfill(5000);
return h
}
Insert cell
histogram.plot(300,200)
Insert cell
Insert cell
/*
20151025: Johannes Mainusch
1D Histogram
*/
function Histogram1D(xMin, xMax, nBins) {
this.ID = new Date().getTime();
this.xMin = xMin || 0;
this.xMax = xMax || 1;
this.nBins = nBins || 100;
this.bins = new Array(nBins);
this.title = "1D histogram";
this.plottextboxstats = true;
this.plotbinentries = true;
this.bin
//
this.fill = function (d, weight) {
this.nEntries += (weight || 1);
this.sum += d * (weight || 1);
this.sum2 += d * (weight * weight || 1)
if (d > this.max) this.max = d;
if (d < this.min) this.min = d;
if (d < xMin) this.underflow += weight || 1;
else
if (d >= xMax) this.overflow += weight || 1;
else {
var bin = Math.trunc(this.nBins * (d - this.xMin) / (this.xMax - this.xMin));
this.bins[bin] += weight || 1;
this.average = this.sum / this.nEntries;
this.rms = Math.sqrt(this.sum2 / this.nEntries);
}
return this;
};
this.reset = function () {
console.log ("in reset...", this.ID);
this.underflow = 0.0;
this.overflow = 0.0;
this.sum = 0.0;
this.sum2 = 0.0;
this.average = 0.0;
this.rms = 0.0;
this.nEntries = 0.0;
this.min = 0.0;
this.max = 0.0;
for (let i = 0; i < this.bins.length; i++) {
this.bins[i] = 0;
}
return this;
};
this.print = function () {
let output = "";
output += "underflow: " + this.underflow + "\n"
output += "overflow: " + this.overflow + "\n"
output += "nEntries: " + this.nEntries + "\n"
output += "average: " + this.average + "\n"
output += "rms: " + this.rms + "\n"
for (let i in this.bins) {
let binwidth = (this.xMax-this.xMin) / this.nBins;
output += "bin[" + i + "] ["+(this.xMin + i * binwidth)+" : "+(this.xMin + binwidth + i*binwidth) +"] = " + this.bins[i] + "\n";
}
return output;
};
this.testfill = function (nEntries, distributionFunction) {
console.log ("in testfill...", this.ID)
let entries = nEntries || 100;
let self = this;
// d = [0..1] --> [this.xMin...this.xMax]
function gleichverteilung () {
let scale = (self.xMax - self.xMin);
return (Math.random() * scale + self.xMin);
}
let df = distributionFunction || gleichverteilung ;
for (let i = 0; i < entries; i++) {
this.fill( df() );
}
return this;
}
this.plot = function (w, h, domElemId) {
console.log ("in plot...", this)
//
// plot a Histogram with d3
//
let width = w || 400;
let height = h || 200;
let margin = this.margin || ({ top: 25, right: 30, bottom: 20, left: 20 });
var svg = this.svg
|| d3.select(DOM.svg(width + margin.left + margin.right,
height + margin.top + margin.bottom));
if (domElemId) {
d3.select(domElemId).append(svg);
}
if (this.svg) {
this.svg.selectAll("rect").remove();
this.svg.selectAll("text").remove();
this.svg.selectAll("g").remove();
}
this.svg = svg;
// background
svg.append("rect")
.attr("class", "bar")
.attr("fill", "#ccf")
.attr("fill-opacity", "0.2")
.attr("x", 0)
.attr("y", 0)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// x-scale
let x = d3.scaleLinear()
.domain([this.xMin, this.xMax])
.range([margin.left, width+margin.left])
// y-scale
let y = d3.scaleLinear()
.domain([0, d3.max(this.bins)*1.2])
.range([height,0])
// x-Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height +margin.top) + ")")
.call(d3.axisBottom(x))
.call(g => g.append("text")
.text(function (d,i){return i}));
// y-Axis
let maxval = d3.max(this.bins);
svg.append("g")
//.attr("class", "y axis")
.attr("transform", "translate("+margin.left+","+margin.top+")")
.call(d3.axisRight(y).tickSize(width))
.call(g => g.selectAll(".tick:not(:first-of-type) line").attr("stroke", "#ddd"))
.call(g => g.append("text")
.text(function (d,i){return y(d) }));
// the frame
svg.append("rect")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "1")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("width", width)
.attr("height", height);
// the histogram
let barWidth = width/this.nBins;
let bar = svg.selectAll("bar").data(this.bins).enter();
let barFunction = (d,i) => x( (i/ this.nBins)*(this.xMax - this.xMin) + this.xMin);
let textxPosition = (d,i) => x( ( (i+0.5)/ this.nBins)*(this.xMax - this.xMin) + this.xMin);
bar.append("rect")
.attr("fill", "steelblue")
//.attr("x", (d,i) => x( (i/ this.nBins)*(this.xMax - this.xMin) + this.xMin) )
.attr("x", barFunction )
.attr("y", d => y(d) + margin.top)
.attr("height", d => height - y(d) )
.attr("width", barWidth-1);
// text in the histogram box
if (this.plotbinentries) {
bar.append("text")
//.attr("x", (d,i) => x((i+0.5) / this.nBins ))
.attr("x", textxPosition)
.attr("y", d => y(d) + 10)
.attr("dy", "1.5em")
.attr("fill", "white")
.attr("writing-mode", "tb")
.attr("text-anchor", "left")
.text( d => d )
.attr("font-size", "10px")
.attr("f0nt-family","sans-serif");
}
// textbox stats
if (this.plottextboxstats) {
svg.append("text")
.attr("transform", "translate("+margin.left+","+margin.top+")")
.attr("font-size", "10px")
.attr("f0nt-family","sans-serif")
.attr("y", 10)
.attr("x", 10)
.append("tspan")
.text("N: " + this.nEntries)
.append("tspan")
.text("underflow: " + this.underflow)
.attr("x", 10)
.attr("dy", 10)
.append("tspan")
.text("overflow: " + this.overflow)
.attr("x", 10)
.attr("dy", 10)
.append("tspan")
.text("average: " + Math.round(this.average * 100) / 100)
.attr("x", 10)
.attr("dy", 10)
.append("tspan")
.text("rms: " + Math.round(this.rms * 100) / 100)
.attr("x", 10)
.attr("dy", 10);
}
// the title
if (this.title) {
svg.append ("text")
.attr("transform", "translate("+margin.left+",20)")
.attr("font-size", "20px")
.attr("f0nt-family","sans-serif")
.attr("y", 0)
.attr("x", 0)
.text(this.title);
}
return svg.node();
}
//
this.reset();
return this;
}
Insert cell
d3 = require("d3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more