1 /**
  2  * Returns a histogram operator for the specified data, with an optional
  3  * accessor function. If the data specified is not an array of numbers, an
  4  * accessor function must be specified to map the data to numeric values.
  5  *
  6  * @class Represents a histogram operator.
  7  *
  8  * @param {array} data an array of numbers or objects.
  9  * @param {function} [f] an optional accessor function.
 10  */
 11 pv.histogram = function(data, f) {
 12   var frequency = true;
 13   return {
 14 
 15     /**
 16      * Returns the computed histogram bins. An optional array of numbers,
 17      * <tt>ticks</tt>, may be specified as the break points. If the ticks are
 18      * not specified, default ticks will be computed using a linear scale on the
 19      * data domain.
 20      *
 21      * <p>The returned array contains {@link pv.histogram.Bin}s. The <tt>x</tt>
 22      * attribute corresponds to the bin's start value (inclusive), while the
 23      * <tt>dx</tt> attribute stores the bin size (end - start). The <tt>y</tt>
 24      * attribute stores either the frequency count or probability, depending on
 25      * how the histogram operator has been configured.
 26      *
 27      * <p>The {@link pv.histogram.Bin} objects are themselves arrays, containing
 28      * the data elements present in each bin, i.e., the elements in the
 29      * <tt>data</tt> array (prior to invoking the accessor function, if any).
 30      * For example, if the data represented countries, and the accessor function
 31      * returned the GDP of each country, the returned bins would be arrays of
 32      * countries (not GDPs).
 33      *
 34      * @function
 35      * @name pv.histogram.prototype.bins
 36      * @param {array} [ticks]
 37      * @returns {array}
 38      */ /** @private */
 39     bins: function(ticks) {
 40       var x = pv.map(data, f), bins = [];
 41 
 42       /* Initialize default ticks. */
 43       if (!arguments.length) ticks = pv.Scale.linear(x).ticks();
 44 
 45       /* Initialize the bins. */
 46       for (var i = 0; i < ticks.length - 1; i++) {
 47         var bin = bins[i] = [];
 48         bin.x = ticks[i];
 49         bin.dx = ticks[i + 1] - ticks[i];
 50         bin.y = 0;
 51       }
 52 
 53       /* Count the number of samples per bin. */
 54       for (var i = 0; i < x.length; i++) {
 55         var j = pv.search.index(ticks, x[i]) - 1,
 56             bin = bins[Math.max(0, Math.min(bins.length - 1, j))];
 57         bin.y++;
 58         bin.push(data[i]);
 59       }
 60 
 61       /* Convert frequencies to probabilities. */
 62       if (!frequency) for (var i = 0; i < bins.length; i++) {
 63         bins[i].y /= x.length;
 64       }
 65 
 66       return bins;
 67     },
 68 
 69     /**
 70      * Sets or gets whether this histogram operator returns frequencies or
 71      * probabilities.
 72      *
 73      * @function
 74      * @name pv.histogram.prototype.frequency
 75      * @param {boolean} [x]
 76      * @returns {pv.histogram} this.
 77      */ /** @private */
 78     frequency: function(x) {
 79       if (arguments.length) {
 80         frequency = Boolean(x);
 81         return this;
 82       }
 83       return frequency;
 84     }
 85   };
 86 };
 87 
 88 /**
 89  * @class Represents a bin returned by the {@link pv.histogram} operator. Bins
 90  * are themselves arrays containing the data elements present in the given bin
 91  * (prior to the accessor function being invoked to convert the data object to a
 92  * numeric value). These bin arrays have additional attributes with meta
 93  * information about the bin.
 94  *
 95  * @name pv.histogram.Bin
 96  * @extends array
 97  * @see pv.histogram
 98  */
 99 
100 /**
101  * The start value of the bin's range.
102  *
103  * @type number
104  * @name pv.histogram.Bin.prototype.x
105  */
106 
107 /**
108  * The magnitude value of the bin's range; end - start.
109  *
110  * @type number
111  * @name pv.histogram.Bin.prototype.dx
112  */
113 
114 /**
115  * The frequency or probability of the bin, depending on how the histogram
116  * operator was configured.
117  *
118  * @type number
119  * @name pv.histogram.Bin.prototype.y
120  */
121