Skip to content

Histograms

Histogram counts samples into bins and returns one bar per bin for a BarSeries.

Count samples

QAccelPlot.BarSeries {
    xAxis: plot.xAxis
    yAxis: plot.yAxis

    Component.onCompleted: setData(QAccelPlot.Histogram.fromSamples(samples, 40).bars())
}

fromSamples(samples, 40) spreads 40 bins over the samples. fromSamples(samples, 40, -3, 3) uses a fixed range instead.

Choose the bin edges

Pass bin edges instead of a bin count:

const edges = QAccelPlot.Histogram.logEdges(1, 10000, 40);
setData(QAccelPlot.Histogram.fromSamples(samples, edges).bars());
Edges Result
[0, 1, 2, 5, 10] Any list of finite, strictly increasing numbers
Histogram.linearEdges(0, 10, 20) 20 equal bins from 0 to 10
Histogram.logEdges(1, 10000, 40) 40 bins of equal width on a logarithmic axis
Histogram.decadeEdges(1, 10000) One bin between each pair of logarithmic axis ticks: 1, 2, …, 9, 10, 20, …

The bars are ranged: each one spans its bin, whatever its width. orientation: Qt.Horizontal on the series puts the bins on the Y axis.

Density

density() divides each count by the sample count and the bin width, so the bin areas sum to 1:

setData(QAccelPlot.Histogram.fromSamples(samples, edges).density().bars());

Use it when bins differ in width, or to compare data sets of different sizes. A wide bin collects more samples than a narrow one, so raw counts of uneven bins misrepresent the distribution.

On a logarithmic axis, logEdges() bins have equal drawn widths, so their raw counts show the shape of the distribution. decadeEdges() bins widen tenfold at each power of ten, so draw them as density.

Counting rules

Sample Counted in
On an edge The bin above it; the last bin includes its upper edge
NaN, or outside the edges No bin

Invalid edges or a bin count below 1 give an empty histogram (binCount 0) and a logged warning. A histogram exposes binCount, edges, values, total, uniform, and binWidth, which is NaN for uneven bins.

C++

#include <QAccelPlot/data/Histogram.hpp>

using QAccelPlot::Histogram;

const auto histogram = Histogram::fromSamples(samples.data(), samples.size(), 40);
bars->setRangedData(histogram.barData(), histogram.binCount());

const auto density = Histogram::fromSamples(samples.data(), samples.size(), Histogram::logEdges(1.0, 10000.0, 40)).density();
bars->setRangedData(density.barData(), density.binCount());

samples is an array of double or float. The functions keep no state, so a worker thread can build the histogram and pass its data to postRangedData(). Histogram::fromCounts(edges, counts) wraps data that is already binned.

Use a histogram as a color bar

A histogram of a heatmap's values can key its colors: color the bins with the heatmap's colormap through colorSource: BarSeries.Position, and let the histogram's bin axis set the colormap range. With horizontal bars, that is yAxis, the bars' position axis:

QAccelPlot.Colormap {
    id: amplitudeColors
    min: histogramPlot.yAxis.viewportMin
    max: histogramPlot.yAxis.viewportMax
}

QAccelPlot.HeatmapSeries {
    colormap: amplitudeColors
}

QAccelPlot.Plot {
    id: histogramPlot
    xAxis: QAccelPlot.Axis { autoRescale: true }
    yAxis: QAccelPlot.Axis {}

    QAccelPlot.BarSeries {
        xAxis: histogramPlot.xAxis
        yAxis: histogramPlot.yAxis
        orientation: Qt.Horizontal
        colorSource: QAccelPlot.BarSeries.Position
        colormap: amplitudeColors
    }
}
  • Panning or zooming the bin axis recolors the heatmap and the bins.
  • Fill the bars with setRangedData(), and call rescaleToData() on the bin axis once to fit it to the bin edges.
  • Keep the bin edges fixed when recounting, for example over the cells in view, so the bin axis is never refitted under the user.

The Interference page of examples/plot_types/heatmap recounts the cells in view as the heatmap pans and zooms.

Complete source: examples/plot_types/histogram