function Sieve(traces, opts) {
    this.traces = traces;
    this.sepNegVal = opts.sepNegVal;
    this.overlapNoMerge = opts.overlapNoMerge;

    // for single-bin histograms - see histogram/calc
    var width1 = Infinity;

    var axLetter = opts.posAxis._id.charAt(0);

    var positions = [];
    for(var i = 0; i < traces.length; i++) {
        var trace = traces[i];
        for(var j = 0; j < trace.length; j++) {
            var bar = trace[j];
            var pos = bar.p;
            if(pos === undefined) {
                pos = bar[axLetter];
            }
            if(pos !== undefined) positions.push(pos);
        }
        if(trace[0] && trace[0].width1) {
            width1 = Math.min(trace[0].width1, width1);
        }
    }
    this.positions = positions;

    var dv = distinctVals(positions);

    this.distinctPositions = dv.vals;
    if(dv.vals.length === 1 && width1 !== Infinity) this.minDiff = width1;
    else this.minDiff = Math.min(dv.minDiff, width1);

    var type = (opts.posAxis || {}).type;
    if(type === 'category' || type === 'multicategory') {
        this.minDiff = 1;
    }

    this.binWidth = this.minDiff;

    this.bins = {};
}
Helper class to sieve data from traces into bins

@class

@param {Array} traces
  Array of calculated traces
@param {object} opts
 - @param {boolean} [sepNegVal]
     If true, then split data at the same position into a bar
     for positive values and another for negative values
 - @param {boolean} [overlapNoMerge]
    If true, then don't merge overlapping bars into a single bar