changeset 89:18f8c214169f

add gtc
author paulo
date Sun, 19 Feb 2017 19:45:31 -0800
parents 583400dc28a0
children 302eebbf025f
files gtc/d3.js gtc/d3.zip gtc/gtc.js gtc/index.html gtc/nv.d3.css gtc/nv.d3.js gtc/simple-statistics.js
diffstat 7 files changed, 27164 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gtc/d3.js	Sun Feb 19 19:45:31 2017 -0800
     1.3 @@ -0,0 +1,9554 @@
     1.4 +!function() {
     1.5 +  var d3 = {
     1.6 +    version: "3.5.17"
     1.7 +  };
     1.8 +  var d3_arraySlice = [].slice, d3_array = function(list) {
     1.9 +    return d3_arraySlice.call(list);
    1.10 +  };
    1.11 +  var d3_document = this.document;
    1.12 +  function d3_documentElement(node) {
    1.13 +    return node && (node.ownerDocument || node.document || node).documentElement;
    1.14 +  }
    1.15 +  function d3_window(node) {
    1.16 +    return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
    1.17 +  }
    1.18 +  if (d3_document) {
    1.19 +    try {
    1.20 +      d3_array(d3_document.documentElement.childNodes)[0].nodeType;
    1.21 +    } catch (e) {
    1.22 +      d3_array = function(list) {
    1.23 +        var i = list.length, array = new Array(i);
    1.24 +        while (i--) array[i] = list[i];
    1.25 +        return array;
    1.26 +      };
    1.27 +    }
    1.28 +  }
    1.29 +  if (!Date.now) Date.now = function() {
    1.30 +    return +new Date();
    1.31 +  };
    1.32 +  if (d3_document) {
    1.33 +    try {
    1.34 +      d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
    1.35 +    } catch (error) {
    1.36 +      var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
    1.37 +      d3_element_prototype.setAttribute = function(name, value) {
    1.38 +        d3_element_setAttribute.call(this, name, value + "");
    1.39 +      };
    1.40 +      d3_element_prototype.setAttributeNS = function(space, local, value) {
    1.41 +        d3_element_setAttributeNS.call(this, space, local, value + "");
    1.42 +      };
    1.43 +      d3_style_prototype.setProperty = function(name, value, priority) {
    1.44 +        d3_style_setProperty.call(this, name, value + "", priority);
    1.45 +      };
    1.46 +    }
    1.47 +  }
    1.48 +  d3.ascending = d3_ascending;
    1.49 +  function d3_ascending(a, b) {
    1.50 +    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
    1.51 +  }
    1.52 +  d3.descending = function(a, b) {
    1.53 +    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
    1.54 +  };
    1.55 +  d3.min = function(array, f) {
    1.56 +    var i = -1, n = array.length, a, b;
    1.57 +    if (arguments.length === 1) {
    1.58 +      while (++i < n) if ((b = array[i]) != null && b >= b) {
    1.59 +        a = b;
    1.60 +        break;
    1.61 +      }
    1.62 +      while (++i < n) if ((b = array[i]) != null && a > b) a = b;
    1.63 +    } else {
    1.64 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
    1.65 +        a = b;
    1.66 +        break;
    1.67 +      }
    1.68 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
    1.69 +    }
    1.70 +    return a;
    1.71 +  };
    1.72 +  d3.max = function(array, f) {
    1.73 +    var i = -1, n = array.length, a, b;
    1.74 +    if (arguments.length === 1) {
    1.75 +      while (++i < n) if ((b = array[i]) != null && b >= b) {
    1.76 +        a = b;
    1.77 +        break;
    1.78 +      }
    1.79 +      while (++i < n) if ((b = array[i]) != null && b > a) a = b;
    1.80 +    } else {
    1.81 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
    1.82 +        a = b;
    1.83 +        break;
    1.84 +      }
    1.85 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
    1.86 +    }
    1.87 +    return a;
    1.88 +  };
    1.89 +  d3.extent = function(array, f) {
    1.90 +    var i = -1, n = array.length, a, b, c;
    1.91 +    if (arguments.length === 1) {
    1.92 +      while (++i < n) if ((b = array[i]) != null && b >= b) {
    1.93 +        a = c = b;
    1.94 +        break;
    1.95 +      }
    1.96 +      while (++i < n) if ((b = array[i]) != null) {
    1.97 +        if (a > b) a = b;
    1.98 +        if (c < b) c = b;
    1.99 +      }
   1.100 +    } else {
   1.101 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
   1.102 +        a = c = b;
   1.103 +        break;
   1.104 +      }
   1.105 +      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
   1.106 +        if (a > b) a = b;
   1.107 +        if (c < b) c = b;
   1.108 +      }
   1.109 +    }
   1.110 +    return [ a, c ];
   1.111 +  };
   1.112 +  function d3_number(x) {
   1.113 +    return x === null ? NaN : +x;
   1.114 +  }
   1.115 +  function d3_numeric(x) {
   1.116 +    return !isNaN(x);
   1.117 +  }
   1.118 +  d3.sum = function(array, f) {
   1.119 +    var s = 0, n = array.length, a, i = -1;
   1.120 +    if (arguments.length === 1) {
   1.121 +      while (++i < n) if (d3_numeric(a = +array[i])) s += a;
   1.122 +    } else {
   1.123 +      while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
   1.124 +    }
   1.125 +    return s;
   1.126 +  };
   1.127 +  d3.mean = function(array, f) {
   1.128 +    var s = 0, n = array.length, a, i = -1, j = n;
   1.129 +    if (arguments.length === 1) {
   1.130 +      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
   1.131 +    } else {
   1.132 +      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
   1.133 +    }
   1.134 +    if (j) return s / j;
   1.135 +  };
   1.136 +  d3.quantile = function(values, p) {
   1.137 +    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
   1.138 +    return e ? v + e * (values[h] - v) : v;
   1.139 +  };
   1.140 +  d3.median = function(array, f) {
   1.141 +    var numbers = [], n = array.length, a, i = -1;
   1.142 +    if (arguments.length === 1) {
   1.143 +      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
   1.144 +    } else {
   1.145 +      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
   1.146 +    }
   1.147 +    if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
   1.148 +  };
   1.149 +  d3.variance = function(array, f) {
   1.150 +    var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
   1.151 +    if (arguments.length === 1) {
   1.152 +      while (++i < n) {
   1.153 +        if (d3_numeric(a = d3_number(array[i]))) {
   1.154 +          d = a - m;
   1.155 +          m += d / ++j;
   1.156 +          s += d * (a - m);
   1.157 +        }
   1.158 +      }
   1.159 +    } else {
   1.160 +      while (++i < n) {
   1.161 +        if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
   1.162 +          d = a - m;
   1.163 +          m += d / ++j;
   1.164 +          s += d * (a - m);
   1.165 +        }
   1.166 +      }
   1.167 +    }
   1.168 +    if (j > 1) return s / (j - 1);
   1.169 +  };
   1.170 +  d3.deviation = function() {
   1.171 +    var v = d3.variance.apply(this, arguments);
   1.172 +    return v ? Math.sqrt(v) : v;
   1.173 +  };
   1.174 +  function d3_bisector(compare) {
   1.175 +    return {
   1.176 +      left: function(a, x, lo, hi) {
   1.177 +        if (arguments.length < 3) lo = 0;
   1.178 +        if (arguments.length < 4) hi = a.length;
   1.179 +        while (lo < hi) {
   1.180 +          var mid = lo + hi >>> 1;
   1.181 +          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
   1.182 +        }
   1.183 +        return lo;
   1.184 +      },
   1.185 +      right: function(a, x, lo, hi) {
   1.186 +        if (arguments.length < 3) lo = 0;
   1.187 +        if (arguments.length < 4) hi = a.length;
   1.188 +        while (lo < hi) {
   1.189 +          var mid = lo + hi >>> 1;
   1.190 +          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
   1.191 +        }
   1.192 +        return lo;
   1.193 +      }
   1.194 +    };
   1.195 +  }
   1.196 +  var d3_bisect = d3_bisector(d3_ascending);
   1.197 +  d3.bisectLeft = d3_bisect.left;
   1.198 +  d3.bisect = d3.bisectRight = d3_bisect.right;
   1.199 +  d3.bisector = function(f) {
   1.200 +    return d3_bisector(f.length === 1 ? function(d, x) {
   1.201 +      return d3_ascending(f(d), x);
   1.202 +    } : f);
   1.203 +  };
   1.204 +  d3.shuffle = function(array, i0, i1) {
   1.205 +    if ((m = arguments.length) < 3) {
   1.206 +      i1 = array.length;
   1.207 +      if (m < 2) i0 = 0;
   1.208 +    }
   1.209 +    var m = i1 - i0, t, i;
   1.210 +    while (m) {
   1.211 +      i = Math.random() * m-- | 0;
   1.212 +      t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
   1.213 +    }
   1.214 +    return array;
   1.215 +  };
   1.216 +  d3.permute = function(array, indexes) {
   1.217 +    var i = indexes.length, permutes = new Array(i);
   1.218 +    while (i--) permutes[i] = array[indexes[i]];
   1.219 +    return permutes;
   1.220 +  };
   1.221 +  d3.pairs = function(array) {
   1.222 +    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
   1.223 +    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
   1.224 +    return pairs;
   1.225 +  };
   1.226 +  d3.transpose = function(matrix) {
   1.227 +    if (!(n = matrix.length)) return [];
   1.228 +    for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) {
   1.229 +      for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) {
   1.230 +        row[j] = matrix[j][i];
   1.231 +      }
   1.232 +    }
   1.233 +    return transpose;
   1.234 +  };
   1.235 +  function d3_transposeLength(d) {
   1.236 +    return d.length;
   1.237 +  }
   1.238 +  d3.zip = function() {
   1.239 +    return d3.transpose(arguments);
   1.240 +  };
   1.241 +  d3.keys = function(map) {
   1.242 +    var keys = [];
   1.243 +    for (var key in map) keys.push(key);
   1.244 +    return keys;
   1.245 +  };
   1.246 +  d3.values = function(map) {
   1.247 +    var values = [];
   1.248 +    for (var key in map) values.push(map[key]);
   1.249 +    return values;
   1.250 +  };
   1.251 +  d3.entries = function(map) {
   1.252 +    var entries = [];
   1.253 +    for (var key in map) entries.push({
   1.254 +      key: key,
   1.255 +      value: map[key]
   1.256 +    });
   1.257 +    return entries;
   1.258 +  };
   1.259 +  d3.merge = function(arrays) {
   1.260 +    var n = arrays.length, m, i = -1, j = 0, merged, array;
   1.261 +    while (++i < n) j += arrays[i].length;
   1.262 +    merged = new Array(j);
   1.263 +    while (--n >= 0) {
   1.264 +      array = arrays[n];
   1.265 +      m = array.length;
   1.266 +      while (--m >= 0) {
   1.267 +        merged[--j] = array[m];
   1.268 +      }
   1.269 +    }
   1.270 +    return merged;
   1.271 +  };
   1.272 +  var abs = Math.abs;
   1.273 +  d3.range = function(start, stop, step) {
   1.274 +    if (arguments.length < 3) {
   1.275 +      step = 1;
   1.276 +      if (arguments.length < 2) {
   1.277 +        stop = start;
   1.278 +        start = 0;
   1.279 +      }
   1.280 +    }
   1.281 +    if ((stop - start) / step === Infinity) throw new Error("infinite range");
   1.282 +    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
   1.283 +    start *= k, stop *= k, step *= k;
   1.284 +    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
   1.285 +    return range;
   1.286 +  };
   1.287 +  function d3_range_integerScale(x) {
   1.288 +    var k = 1;
   1.289 +    while (x * k % 1) k *= 10;
   1.290 +    return k;
   1.291 +  }
   1.292 +  function d3_class(ctor, properties) {
   1.293 +    for (var key in properties) {
   1.294 +      Object.defineProperty(ctor.prototype, key, {
   1.295 +        value: properties[key],
   1.296 +        enumerable: false
   1.297 +      });
   1.298 +    }
   1.299 +  }
   1.300 +  d3.map = function(object, f) {
   1.301 +    var map = new d3_Map();
   1.302 +    if (object instanceof d3_Map) {
   1.303 +      object.forEach(function(key, value) {
   1.304 +        map.set(key, value);
   1.305 +      });
   1.306 +    } else if (Array.isArray(object)) {
   1.307 +      var i = -1, n = object.length, o;
   1.308 +      if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
   1.309 +    } else {
   1.310 +      for (var key in object) map.set(key, object[key]);
   1.311 +    }
   1.312 +    return map;
   1.313 +  };
   1.314 +  function d3_Map() {
   1.315 +    this._ = Object.create(null);
   1.316 +  }
   1.317 +  var d3_map_proto = "__proto__", d3_map_zero = "\x00";
   1.318 +  d3_class(d3_Map, {
   1.319 +    has: d3_map_has,
   1.320 +    get: function(key) {
   1.321 +      return this._[d3_map_escape(key)];
   1.322 +    },
   1.323 +    set: function(key, value) {
   1.324 +      return this._[d3_map_escape(key)] = value;
   1.325 +    },
   1.326 +    remove: d3_map_remove,
   1.327 +    keys: d3_map_keys,
   1.328 +    values: function() {
   1.329 +      var values = [];
   1.330 +      for (var key in this._) values.push(this._[key]);
   1.331 +      return values;
   1.332 +    },
   1.333 +    entries: function() {
   1.334 +      var entries = [];
   1.335 +      for (var key in this._) entries.push({
   1.336 +        key: d3_map_unescape(key),
   1.337 +        value: this._[key]
   1.338 +      });
   1.339 +      return entries;
   1.340 +    },
   1.341 +    size: d3_map_size,
   1.342 +    empty: d3_map_empty,
   1.343 +    forEach: function(f) {
   1.344 +      for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
   1.345 +    }
   1.346 +  });
   1.347 +  function d3_map_escape(key) {
   1.348 +    return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
   1.349 +  }
   1.350 +  function d3_map_unescape(key) {
   1.351 +    return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
   1.352 +  }
   1.353 +  function d3_map_has(key) {
   1.354 +    return d3_map_escape(key) in this._;
   1.355 +  }
   1.356 +  function d3_map_remove(key) {
   1.357 +    return (key = d3_map_escape(key)) in this._ && delete this._[key];
   1.358 +  }
   1.359 +  function d3_map_keys() {
   1.360 +    var keys = [];
   1.361 +    for (var key in this._) keys.push(d3_map_unescape(key));
   1.362 +    return keys;
   1.363 +  }
   1.364 +  function d3_map_size() {
   1.365 +    var size = 0;
   1.366 +    for (var key in this._) ++size;
   1.367 +    return size;
   1.368 +  }
   1.369 +  function d3_map_empty() {
   1.370 +    for (var key in this._) return false;
   1.371 +    return true;
   1.372 +  }
   1.373 +  d3.nest = function() {
   1.374 +    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
   1.375 +    function map(mapType, array, depth) {
   1.376 +      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
   1.377 +      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
   1.378 +      while (++i < n) {
   1.379 +        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
   1.380 +          values.push(object);
   1.381 +        } else {
   1.382 +          valuesByKey.set(keyValue, [ object ]);
   1.383 +        }
   1.384 +      }
   1.385 +      if (mapType) {
   1.386 +        object = mapType();
   1.387 +        setter = function(keyValue, values) {
   1.388 +          object.set(keyValue, map(mapType, values, depth));
   1.389 +        };
   1.390 +      } else {
   1.391 +        object = {};
   1.392 +        setter = function(keyValue, values) {
   1.393 +          object[keyValue] = map(mapType, values, depth);
   1.394 +        };
   1.395 +      }
   1.396 +      valuesByKey.forEach(setter);
   1.397 +      return object;
   1.398 +    }
   1.399 +    function entries(map, depth) {
   1.400 +      if (depth >= keys.length) return map;
   1.401 +      var array = [], sortKey = sortKeys[depth++];
   1.402 +      map.forEach(function(key, keyMap) {
   1.403 +        array.push({
   1.404 +          key: key,
   1.405 +          values: entries(keyMap, depth)
   1.406 +        });
   1.407 +      });
   1.408 +      return sortKey ? array.sort(function(a, b) {
   1.409 +        return sortKey(a.key, b.key);
   1.410 +      }) : array;
   1.411 +    }
   1.412 +    nest.map = function(array, mapType) {
   1.413 +      return map(mapType, array, 0);
   1.414 +    };
   1.415 +    nest.entries = function(array) {
   1.416 +      return entries(map(d3.map, array, 0), 0);
   1.417 +    };
   1.418 +    nest.key = function(d) {
   1.419 +      keys.push(d);
   1.420 +      return nest;
   1.421 +    };
   1.422 +    nest.sortKeys = function(order) {
   1.423 +      sortKeys[keys.length - 1] = order;
   1.424 +      return nest;
   1.425 +    };
   1.426 +    nest.sortValues = function(order) {
   1.427 +      sortValues = order;
   1.428 +      return nest;
   1.429 +    };
   1.430 +    nest.rollup = function(f) {
   1.431 +      rollup = f;
   1.432 +      return nest;
   1.433 +    };
   1.434 +    return nest;
   1.435 +  };
   1.436 +  d3.set = function(array) {
   1.437 +    var set = new d3_Set();
   1.438 +    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
   1.439 +    return set;
   1.440 +  };
   1.441 +  function d3_Set() {
   1.442 +    this._ = Object.create(null);
   1.443 +  }
   1.444 +  d3_class(d3_Set, {
   1.445 +    has: d3_map_has,
   1.446 +    add: function(key) {
   1.447 +      this._[d3_map_escape(key += "")] = true;
   1.448 +      return key;
   1.449 +    },
   1.450 +    remove: d3_map_remove,
   1.451 +    values: d3_map_keys,
   1.452 +    size: d3_map_size,
   1.453 +    empty: d3_map_empty,
   1.454 +    forEach: function(f) {
   1.455 +      for (var key in this._) f.call(this, d3_map_unescape(key));
   1.456 +    }
   1.457 +  });
   1.458 +  d3.behavior = {};
   1.459 +  function d3_identity(d) {
   1.460 +    return d;
   1.461 +  }
   1.462 +  d3.rebind = function(target, source) {
   1.463 +    var i = 1, n = arguments.length, method;
   1.464 +    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
   1.465 +    return target;
   1.466 +  };
   1.467 +  function d3_rebind(target, source, method) {
   1.468 +    return function() {
   1.469 +      var value = method.apply(source, arguments);
   1.470 +      return value === source ? target : value;
   1.471 +    };
   1.472 +  }
   1.473 +  function d3_vendorSymbol(object, name) {
   1.474 +    if (name in object) return name;
   1.475 +    name = name.charAt(0).toUpperCase() + name.slice(1);
   1.476 +    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
   1.477 +      var prefixName = d3_vendorPrefixes[i] + name;
   1.478 +      if (prefixName in object) return prefixName;
   1.479 +    }
   1.480 +  }
   1.481 +  var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
   1.482 +  function d3_noop() {}
   1.483 +  d3.dispatch = function() {
   1.484 +    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
   1.485 +    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
   1.486 +    return dispatch;
   1.487 +  };
   1.488 +  function d3_dispatch() {}
   1.489 +  d3_dispatch.prototype.on = function(type, listener) {
   1.490 +    var i = type.indexOf("."), name = "";
   1.491 +    if (i >= 0) {
   1.492 +      name = type.slice(i + 1);
   1.493 +      type = type.slice(0, i);
   1.494 +    }
   1.495 +    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
   1.496 +    if (arguments.length === 2) {
   1.497 +      if (listener == null) for (type in this) {
   1.498 +        if (this.hasOwnProperty(type)) this[type].on(name, null);
   1.499 +      }
   1.500 +      return this;
   1.501 +    }
   1.502 +  };
   1.503 +  function d3_dispatch_event(dispatch) {
   1.504 +    var listeners = [], listenerByName = new d3_Map();
   1.505 +    function event() {
   1.506 +      var z = listeners, i = -1, n = z.length, l;
   1.507 +      while (++i < n) if (l = z[i].on) l.apply(this, arguments);
   1.508 +      return dispatch;
   1.509 +    }
   1.510 +    event.on = function(name, listener) {
   1.511 +      var l = listenerByName.get(name), i;
   1.512 +      if (arguments.length < 2) return l && l.on;
   1.513 +      if (l) {
   1.514 +        l.on = null;
   1.515 +        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
   1.516 +        listenerByName.remove(name);
   1.517 +      }
   1.518 +      if (listener) listeners.push(listenerByName.set(name, {
   1.519 +        on: listener
   1.520 +      }));
   1.521 +      return dispatch;
   1.522 +    };
   1.523 +    return event;
   1.524 +  }
   1.525 +  d3.event = null;
   1.526 +  function d3_eventPreventDefault() {
   1.527 +    d3.event.preventDefault();
   1.528 +  }
   1.529 +  function d3_eventSource() {
   1.530 +    var e = d3.event, s;
   1.531 +    while (s = e.sourceEvent) e = s;
   1.532 +    return e;
   1.533 +  }
   1.534 +  function d3_eventDispatch(target) {
   1.535 +    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
   1.536 +    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
   1.537 +    dispatch.of = function(thiz, argumentz) {
   1.538 +      return function(e1) {
   1.539 +        try {
   1.540 +          var e0 = e1.sourceEvent = d3.event;
   1.541 +          e1.target = target;
   1.542 +          d3.event = e1;
   1.543 +          dispatch[e1.type].apply(thiz, argumentz);
   1.544 +        } finally {
   1.545 +          d3.event = e0;
   1.546 +        }
   1.547 +      };
   1.548 +    };
   1.549 +    return dispatch;
   1.550 +  }
   1.551 +  d3.requote = function(s) {
   1.552 +    return s.replace(d3_requote_re, "\\$&");
   1.553 +  };
   1.554 +  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
   1.555 +  var d3_subclass = {}.__proto__ ? function(object, prototype) {
   1.556 +    object.__proto__ = prototype;
   1.557 +  } : function(object, prototype) {
   1.558 +    for (var property in prototype) object[property] = prototype[property];
   1.559 +  };
   1.560 +  function d3_selection(groups) {
   1.561 +    d3_subclass(groups, d3_selectionPrototype);
   1.562 +    return groups;
   1.563 +  }
   1.564 +  var d3_select = function(s, n) {
   1.565 +    return n.querySelector(s);
   1.566 +  }, d3_selectAll = function(s, n) {
   1.567 +    return n.querySelectorAll(s);
   1.568 +  }, d3_selectMatches = function(n, s) {
   1.569 +    var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
   1.570 +    d3_selectMatches = function(n, s) {
   1.571 +      return d3_selectMatcher.call(n, s);
   1.572 +    };
   1.573 +    return d3_selectMatches(n, s);
   1.574 +  };
   1.575 +  if (typeof Sizzle === "function") {
   1.576 +    d3_select = function(s, n) {
   1.577 +      return Sizzle(s, n)[0] || null;
   1.578 +    };
   1.579 +    d3_selectAll = Sizzle;
   1.580 +    d3_selectMatches = Sizzle.matchesSelector;
   1.581 +  }
   1.582 +  d3.selection = function() {
   1.583 +    return d3.select(d3_document.documentElement);
   1.584 +  };
   1.585 +  var d3_selectionPrototype = d3.selection.prototype = [];
   1.586 +  d3_selectionPrototype.select = function(selector) {
   1.587 +    var subgroups = [], subgroup, subnode, group, node;
   1.588 +    selector = d3_selection_selector(selector);
   1.589 +    for (var j = -1, m = this.length; ++j < m; ) {
   1.590 +      subgroups.push(subgroup = []);
   1.591 +      subgroup.parentNode = (group = this[j]).parentNode;
   1.592 +      for (var i = -1, n = group.length; ++i < n; ) {
   1.593 +        if (node = group[i]) {
   1.594 +          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
   1.595 +          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
   1.596 +        } else {
   1.597 +          subgroup.push(null);
   1.598 +        }
   1.599 +      }
   1.600 +    }
   1.601 +    return d3_selection(subgroups);
   1.602 +  };
   1.603 +  function d3_selection_selector(selector) {
   1.604 +    return typeof selector === "function" ? selector : function() {
   1.605 +      return d3_select(selector, this);
   1.606 +    };
   1.607 +  }
   1.608 +  d3_selectionPrototype.selectAll = function(selector) {
   1.609 +    var subgroups = [], subgroup, node;
   1.610 +    selector = d3_selection_selectorAll(selector);
   1.611 +    for (var j = -1, m = this.length; ++j < m; ) {
   1.612 +      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
   1.613 +        if (node = group[i]) {
   1.614 +          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
   1.615 +          subgroup.parentNode = node;
   1.616 +        }
   1.617 +      }
   1.618 +    }
   1.619 +    return d3_selection(subgroups);
   1.620 +  };
   1.621 +  function d3_selection_selectorAll(selector) {
   1.622 +    return typeof selector === "function" ? selector : function() {
   1.623 +      return d3_selectAll(selector, this);
   1.624 +    };
   1.625 +  }
   1.626 +  var d3_nsXhtml = "http://www.w3.org/1999/xhtml";
   1.627 +  var d3_nsPrefix = {
   1.628 +    svg: "http://www.w3.org/2000/svg",
   1.629 +    xhtml: d3_nsXhtml,
   1.630 +    xlink: "http://www.w3.org/1999/xlink",
   1.631 +    xml: "http://www.w3.org/XML/1998/namespace",
   1.632 +    xmlns: "http://www.w3.org/2000/xmlns/"
   1.633 +  };
   1.634 +  d3.ns = {
   1.635 +    prefix: d3_nsPrefix,
   1.636 +    qualify: function(name) {
   1.637 +      var i = name.indexOf(":"), prefix = name;
   1.638 +      if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
   1.639 +      return d3_nsPrefix.hasOwnProperty(prefix) ? {
   1.640 +        space: d3_nsPrefix[prefix],
   1.641 +        local: name
   1.642 +      } : name;
   1.643 +    }
   1.644 +  };
   1.645 +  d3_selectionPrototype.attr = function(name, value) {
   1.646 +    if (arguments.length < 2) {
   1.647 +      if (typeof name === "string") {
   1.648 +        var node = this.node();
   1.649 +        name = d3.ns.qualify(name);
   1.650 +        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
   1.651 +      }
   1.652 +      for (value in name) this.each(d3_selection_attr(value, name[value]));
   1.653 +      return this;
   1.654 +    }
   1.655 +    return this.each(d3_selection_attr(name, value));
   1.656 +  };
   1.657 +  function d3_selection_attr(name, value) {
   1.658 +    name = d3.ns.qualify(name);
   1.659 +    function attrNull() {
   1.660 +      this.removeAttribute(name);
   1.661 +    }
   1.662 +    function attrNullNS() {
   1.663 +      this.removeAttributeNS(name.space, name.local);
   1.664 +    }
   1.665 +    function attrConstant() {
   1.666 +      this.setAttribute(name, value);
   1.667 +    }
   1.668 +    function attrConstantNS() {
   1.669 +      this.setAttributeNS(name.space, name.local, value);
   1.670 +    }
   1.671 +    function attrFunction() {
   1.672 +      var x = value.apply(this, arguments);
   1.673 +      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
   1.674 +    }
   1.675 +    function attrFunctionNS() {
   1.676 +      var x = value.apply(this, arguments);
   1.677 +      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
   1.678 +    }
   1.679 +    return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
   1.680 +  }
   1.681 +  function d3_collapse(s) {
   1.682 +    return s.trim().replace(/\s+/g, " ");
   1.683 +  }
   1.684 +  d3_selectionPrototype.classed = function(name, value) {
   1.685 +    if (arguments.length < 2) {
   1.686 +      if (typeof name === "string") {
   1.687 +        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
   1.688 +        if (value = node.classList) {
   1.689 +          while (++i < n) if (!value.contains(name[i])) return false;
   1.690 +        } else {
   1.691 +          value = node.getAttribute("class");
   1.692 +          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
   1.693 +        }
   1.694 +        return true;
   1.695 +      }
   1.696 +      for (value in name) this.each(d3_selection_classed(value, name[value]));
   1.697 +      return this;
   1.698 +    }
   1.699 +    return this.each(d3_selection_classed(name, value));
   1.700 +  };
   1.701 +  function d3_selection_classedRe(name) {
   1.702 +    return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
   1.703 +  }
   1.704 +  function d3_selection_classes(name) {
   1.705 +    return (name + "").trim().split(/^|\s+/);
   1.706 +  }
   1.707 +  function d3_selection_classed(name, value) {
   1.708 +    name = d3_selection_classes(name).map(d3_selection_classedName);
   1.709 +    var n = name.length;
   1.710 +    function classedConstant() {
   1.711 +      var i = -1;
   1.712 +      while (++i < n) name[i](this, value);
   1.713 +    }
   1.714 +    function classedFunction() {
   1.715 +      var i = -1, x = value.apply(this, arguments);
   1.716 +      while (++i < n) name[i](this, x);
   1.717 +    }
   1.718 +    return typeof value === "function" ? classedFunction : classedConstant;
   1.719 +  }
   1.720 +  function d3_selection_classedName(name) {
   1.721 +    var re = d3_selection_classedRe(name);
   1.722 +    return function(node, value) {
   1.723 +      if (c = node.classList) return value ? c.add(name) : c.remove(name);
   1.724 +      var c = node.getAttribute("class") || "";
   1.725 +      if (value) {
   1.726 +        re.lastIndex = 0;
   1.727 +        if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
   1.728 +      } else {
   1.729 +        node.setAttribute("class", d3_collapse(c.replace(re, " ")));
   1.730 +      }
   1.731 +    };
   1.732 +  }
   1.733 +  d3_selectionPrototype.style = function(name, value, priority) {
   1.734 +    var n = arguments.length;
   1.735 +    if (n < 3) {
   1.736 +      if (typeof name !== "string") {
   1.737 +        if (n < 2) value = "";
   1.738 +        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
   1.739 +        return this;
   1.740 +      }
   1.741 +      if (n < 2) {
   1.742 +        var node = this.node();
   1.743 +        return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
   1.744 +      }
   1.745 +      priority = "";
   1.746 +    }
   1.747 +    return this.each(d3_selection_style(name, value, priority));
   1.748 +  };
   1.749 +  function d3_selection_style(name, value, priority) {
   1.750 +    function styleNull() {
   1.751 +      this.style.removeProperty(name);
   1.752 +    }
   1.753 +    function styleConstant() {
   1.754 +      this.style.setProperty(name, value, priority);
   1.755 +    }
   1.756 +    function styleFunction() {
   1.757 +      var x = value.apply(this, arguments);
   1.758 +      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
   1.759 +    }
   1.760 +    return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
   1.761 +  }
   1.762 +  d3_selectionPrototype.property = function(name, value) {
   1.763 +    if (arguments.length < 2) {
   1.764 +      if (typeof name === "string") return this.node()[name];
   1.765 +      for (value in name) this.each(d3_selection_property(value, name[value]));
   1.766 +      return this;
   1.767 +    }
   1.768 +    return this.each(d3_selection_property(name, value));
   1.769 +  };
   1.770 +  function d3_selection_property(name, value) {
   1.771 +    function propertyNull() {
   1.772 +      delete this[name];
   1.773 +    }
   1.774 +    function propertyConstant() {
   1.775 +      this[name] = value;
   1.776 +    }
   1.777 +    function propertyFunction() {
   1.778 +      var x = value.apply(this, arguments);
   1.779 +      if (x == null) delete this[name]; else this[name] = x;
   1.780 +    }
   1.781 +    return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
   1.782 +  }
   1.783 +  d3_selectionPrototype.text = function(value) {
   1.784 +    return arguments.length ? this.each(typeof value === "function" ? function() {
   1.785 +      var v = value.apply(this, arguments);
   1.786 +      this.textContent = v == null ? "" : v;
   1.787 +    } : value == null ? function() {
   1.788 +      this.textContent = "";
   1.789 +    } : function() {
   1.790 +      this.textContent = value;
   1.791 +    }) : this.node().textContent;
   1.792 +  };
   1.793 +  d3_selectionPrototype.html = function(value) {
   1.794 +    return arguments.length ? this.each(typeof value === "function" ? function() {
   1.795 +      var v = value.apply(this, arguments);
   1.796 +      this.innerHTML = v == null ? "" : v;
   1.797 +    } : value == null ? function() {
   1.798 +      this.innerHTML = "";
   1.799 +    } : function() {
   1.800 +      this.innerHTML = value;
   1.801 +    }) : this.node().innerHTML;
   1.802 +  };
   1.803 +  d3_selectionPrototype.append = function(name) {
   1.804 +    name = d3_selection_creator(name);
   1.805 +    return this.select(function() {
   1.806 +      return this.appendChild(name.apply(this, arguments));
   1.807 +    });
   1.808 +  };
   1.809 +  function d3_selection_creator(name) {
   1.810 +    function create() {
   1.811 +      var document = this.ownerDocument, namespace = this.namespaceURI;
   1.812 +      return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name);
   1.813 +    }
   1.814 +    function createNS() {
   1.815 +      return this.ownerDocument.createElementNS(name.space, name.local);
   1.816 +    }
   1.817 +    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
   1.818 +  }
   1.819 +  d3_selectionPrototype.insert = function(name, before) {
   1.820 +    name = d3_selection_creator(name);
   1.821 +    before = d3_selection_selector(before);
   1.822 +    return this.select(function() {
   1.823 +      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
   1.824 +    });
   1.825 +  };
   1.826 +  d3_selectionPrototype.remove = function() {
   1.827 +    return this.each(d3_selectionRemove);
   1.828 +  };
   1.829 +  function d3_selectionRemove() {
   1.830 +    var parent = this.parentNode;
   1.831 +    if (parent) parent.removeChild(this);
   1.832 +  }
   1.833 +  d3_selectionPrototype.data = function(value, key) {
   1.834 +    var i = -1, n = this.length, group, node;
   1.835 +    if (!arguments.length) {
   1.836 +      value = new Array(n = (group = this[0]).length);
   1.837 +      while (++i < n) {
   1.838 +        if (node = group[i]) {
   1.839 +          value[i] = node.__data__;
   1.840 +        }
   1.841 +      }
   1.842 +      return value;
   1.843 +    }
   1.844 +    function bind(group, groupData) {
   1.845 +      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
   1.846 +      if (key) {
   1.847 +        var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
   1.848 +        for (i = -1; ++i < n; ) {
   1.849 +          if (node = group[i]) {
   1.850 +            if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) {
   1.851 +              exitNodes[i] = node;
   1.852 +            } else {
   1.853 +              nodeByKeyValue.set(keyValue, node);
   1.854 +            }
   1.855 +            keyValues[i] = keyValue;
   1.856 +          }
   1.857 +        }
   1.858 +        for (i = -1; ++i < m; ) {
   1.859 +          if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
   1.860 +            enterNodes[i] = d3_selection_dataNode(nodeData);
   1.861 +          } else if (node !== true) {
   1.862 +            updateNodes[i] = node;
   1.863 +            node.__data__ = nodeData;
   1.864 +          }
   1.865 +          nodeByKeyValue.set(keyValue, true);
   1.866 +        }
   1.867 +        for (i = -1; ++i < n; ) {
   1.868 +          if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) {
   1.869 +            exitNodes[i] = group[i];
   1.870 +          }
   1.871 +        }
   1.872 +      } else {
   1.873 +        for (i = -1; ++i < n0; ) {
   1.874 +          node = group[i];
   1.875 +          nodeData = groupData[i];
   1.876 +          if (node) {
   1.877 +            node.__data__ = nodeData;
   1.878 +            updateNodes[i] = node;
   1.879 +          } else {
   1.880 +            enterNodes[i] = d3_selection_dataNode(nodeData);
   1.881 +          }
   1.882 +        }
   1.883 +        for (;i < m; ++i) {
   1.884 +          enterNodes[i] = d3_selection_dataNode(groupData[i]);
   1.885 +        }
   1.886 +        for (;i < n; ++i) {
   1.887 +          exitNodes[i] = group[i];
   1.888 +        }
   1.889 +      }
   1.890 +      enterNodes.update = updateNodes;
   1.891 +      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
   1.892 +      enter.push(enterNodes);
   1.893 +      update.push(updateNodes);
   1.894 +      exit.push(exitNodes);
   1.895 +    }
   1.896 +    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
   1.897 +    if (typeof value === "function") {
   1.898 +      while (++i < n) {
   1.899 +        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
   1.900 +      }
   1.901 +    } else {
   1.902 +      while (++i < n) {
   1.903 +        bind(group = this[i], value);
   1.904 +      }
   1.905 +    }
   1.906 +    update.enter = function() {
   1.907 +      return enter;
   1.908 +    };
   1.909 +    update.exit = function() {
   1.910 +      return exit;
   1.911 +    };
   1.912 +    return update;
   1.913 +  };
   1.914 +  function d3_selection_dataNode(data) {
   1.915 +    return {
   1.916 +      __data__: data
   1.917 +    };
   1.918 +  }
   1.919 +  d3_selectionPrototype.datum = function(value) {
   1.920 +    return arguments.length ? this.property("__data__", value) : this.property("__data__");
   1.921 +  };
   1.922 +  d3_selectionPrototype.filter = function(filter) {
   1.923 +    var subgroups = [], subgroup, group, node;
   1.924 +    if (typeof filter !== "function") filter = d3_selection_filter(filter);
   1.925 +    for (var j = 0, m = this.length; j < m; j++) {
   1.926 +      subgroups.push(subgroup = []);
   1.927 +      subgroup.parentNode = (group = this[j]).parentNode;
   1.928 +      for (var i = 0, n = group.length; i < n; i++) {
   1.929 +        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
   1.930 +          subgroup.push(node);
   1.931 +        }
   1.932 +      }
   1.933 +    }
   1.934 +    return d3_selection(subgroups);
   1.935 +  };
   1.936 +  function d3_selection_filter(selector) {
   1.937 +    return function() {
   1.938 +      return d3_selectMatches(this, selector);
   1.939 +    };
   1.940 +  }
   1.941 +  d3_selectionPrototype.order = function() {
   1.942 +    for (var j = -1, m = this.length; ++j < m; ) {
   1.943 +      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
   1.944 +        if (node = group[i]) {
   1.945 +          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
   1.946 +          next = node;
   1.947 +        }
   1.948 +      }
   1.949 +    }
   1.950 +    return this;
   1.951 +  };
   1.952 +  d3_selectionPrototype.sort = function(comparator) {
   1.953 +    comparator = d3_selection_sortComparator.apply(this, arguments);
   1.954 +    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
   1.955 +    return this.order();
   1.956 +  };
   1.957 +  function d3_selection_sortComparator(comparator) {
   1.958 +    if (!arguments.length) comparator = d3_ascending;
   1.959 +    return function(a, b) {
   1.960 +      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
   1.961 +    };
   1.962 +  }
   1.963 +  d3_selectionPrototype.each = function(callback) {
   1.964 +    return d3_selection_each(this, function(node, i, j) {
   1.965 +      callback.call(node, node.__data__, i, j);
   1.966 +    });
   1.967 +  };
   1.968 +  function d3_selection_each(groups, callback) {
   1.969 +    for (var j = 0, m = groups.length; j < m; j++) {
   1.970 +      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
   1.971 +        if (node = group[i]) callback(node, i, j);
   1.972 +      }
   1.973 +    }
   1.974 +    return groups;
   1.975 +  }
   1.976 +  d3_selectionPrototype.call = function(callback) {
   1.977 +    var args = d3_array(arguments);
   1.978 +    callback.apply(args[0] = this, args);
   1.979 +    return this;
   1.980 +  };
   1.981 +  d3_selectionPrototype.empty = function() {
   1.982 +    return !this.node();
   1.983 +  };
   1.984 +  d3_selectionPrototype.node = function() {
   1.985 +    for (var j = 0, m = this.length; j < m; j++) {
   1.986 +      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
   1.987 +        var node = group[i];
   1.988 +        if (node) return node;
   1.989 +      }
   1.990 +    }
   1.991 +    return null;
   1.992 +  };
   1.993 +  d3_selectionPrototype.size = function() {
   1.994 +    var n = 0;
   1.995 +    d3_selection_each(this, function() {
   1.996 +      ++n;
   1.997 +    });
   1.998 +    return n;
   1.999 +  };
  1.1000 +  function d3_selection_enter(selection) {
  1.1001 +    d3_subclass(selection, d3_selection_enterPrototype);
  1.1002 +    return selection;
  1.1003 +  }
  1.1004 +  var d3_selection_enterPrototype = [];
  1.1005 +  d3.selection.enter = d3_selection_enter;
  1.1006 +  d3.selection.enter.prototype = d3_selection_enterPrototype;
  1.1007 +  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
  1.1008 +  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
  1.1009 +  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
  1.1010 +  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
  1.1011 +  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
  1.1012 +  d3_selection_enterPrototype.select = function(selector) {
  1.1013 +    var subgroups = [], subgroup, subnode, upgroup, group, node;
  1.1014 +    for (var j = -1, m = this.length; ++j < m; ) {
  1.1015 +      upgroup = (group = this[j]).update;
  1.1016 +      subgroups.push(subgroup = []);
  1.1017 +      subgroup.parentNode = group.parentNode;
  1.1018 +      for (var i = -1, n = group.length; ++i < n; ) {
  1.1019 +        if (node = group[i]) {
  1.1020 +          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
  1.1021 +          subnode.__data__ = node.__data__;
  1.1022 +        } else {
  1.1023 +          subgroup.push(null);
  1.1024 +        }
  1.1025 +      }
  1.1026 +    }
  1.1027 +    return d3_selection(subgroups);
  1.1028 +  };
  1.1029 +  d3_selection_enterPrototype.insert = function(name, before) {
  1.1030 +    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
  1.1031 +    return d3_selectionPrototype.insert.call(this, name, before);
  1.1032 +  };
  1.1033 +  function d3_selection_enterInsertBefore(enter) {
  1.1034 +    var i0, j0;
  1.1035 +    return function(d, i, j) {
  1.1036 +      var group = enter[j].update, n = group.length, node;
  1.1037 +      if (j != j0) j0 = j, i0 = 0;
  1.1038 +      if (i >= i0) i0 = i + 1;
  1.1039 +      while (!(node = group[i0]) && ++i0 < n) ;
  1.1040 +      return node;
  1.1041 +    };
  1.1042 +  }
  1.1043 +  d3.select = function(node) {
  1.1044 +    var group;
  1.1045 +    if (typeof node === "string") {
  1.1046 +      group = [ d3_select(node, d3_document) ];
  1.1047 +      group.parentNode = d3_document.documentElement;
  1.1048 +    } else {
  1.1049 +      group = [ node ];
  1.1050 +      group.parentNode = d3_documentElement(node);
  1.1051 +    }
  1.1052 +    return d3_selection([ group ]);
  1.1053 +  };
  1.1054 +  d3.selectAll = function(nodes) {
  1.1055 +    var group;
  1.1056 +    if (typeof nodes === "string") {
  1.1057 +      group = d3_array(d3_selectAll(nodes, d3_document));
  1.1058 +      group.parentNode = d3_document.documentElement;
  1.1059 +    } else {
  1.1060 +      group = d3_array(nodes);
  1.1061 +      group.parentNode = null;
  1.1062 +    }
  1.1063 +    return d3_selection([ group ]);
  1.1064 +  };
  1.1065 +  d3_selectionPrototype.on = function(type, listener, capture) {
  1.1066 +    var n = arguments.length;
  1.1067 +    if (n < 3) {
  1.1068 +      if (typeof type !== "string") {
  1.1069 +        if (n < 2) listener = false;
  1.1070 +        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
  1.1071 +        return this;
  1.1072 +      }
  1.1073 +      if (n < 2) return (n = this.node()["__on" + type]) && n._;
  1.1074 +      capture = false;
  1.1075 +    }
  1.1076 +    return this.each(d3_selection_on(type, listener, capture));
  1.1077 +  };
  1.1078 +  function d3_selection_on(type, listener, capture) {
  1.1079 +    var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
  1.1080 +    if (i > 0) type = type.slice(0, i);
  1.1081 +    var filter = d3_selection_onFilters.get(type);
  1.1082 +    if (filter) type = filter, wrap = d3_selection_onFilter;
  1.1083 +    function onRemove() {
  1.1084 +      var l = this[name];
  1.1085 +      if (l) {
  1.1086 +        this.removeEventListener(type, l, l.$);
  1.1087 +        delete this[name];
  1.1088 +      }
  1.1089 +    }
  1.1090 +    function onAdd() {
  1.1091 +      var l = wrap(listener, d3_array(arguments));
  1.1092 +      onRemove.call(this);
  1.1093 +      this.addEventListener(type, this[name] = l, l.$ = capture);
  1.1094 +      l._ = listener;
  1.1095 +    }
  1.1096 +    function removeAll() {
  1.1097 +      var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
  1.1098 +      for (var name in this) {
  1.1099 +        if (match = name.match(re)) {
  1.1100 +          var l = this[name];
  1.1101 +          this.removeEventListener(match[1], l, l.$);
  1.1102 +          delete this[name];
  1.1103 +        }
  1.1104 +      }
  1.1105 +    }
  1.1106 +    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
  1.1107 +  }
  1.1108 +  var d3_selection_onFilters = d3.map({
  1.1109 +    mouseenter: "mouseover",
  1.1110 +    mouseleave: "mouseout"
  1.1111 +  });
  1.1112 +  if (d3_document) {
  1.1113 +    d3_selection_onFilters.forEach(function(k) {
  1.1114 +      if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
  1.1115 +    });
  1.1116 +  }
  1.1117 +  function d3_selection_onListener(listener, argumentz) {
  1.1118 +    return function(e) {
  1.1119 +      var o = d3.event;
  1.1120 +      d3.event = e;
  1.1121 +      argumentz[0] = this.__data__;
  1.1122 +      try {
  1.1123 +        listener.apply(this, argumentz);
  1.1124 +      } finally {
  1.1125 +        d3.event = o;
  1.1126 +      }
  1.1127 +    };
  1.1128 +  }
  1.1129 +  function d3_selection_onFilter(listener, argumentz) {
  1.1130 +    var l = d3_selection_onListener(listener, argumentz);
  1.1131 +    return function(e) {
  1.1132 +      var target = this, related = e.relatedTarget;
  1.1133 +      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
  1.1134 +        l.call(target, e);
  1.1135 +      }
  1.1136 +    };
  1.1137 +  }
  1.1138 +  var d3_event_dragSelect, d3_event_dragId = 0;
  1.1139 +  function d3_event_dragSuppress(node) {
  1.1140 +    var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
  1.1141 +    if (d3_event_dragSelect == null) {
  1.1142 +      d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
  1.1143 +    }
  1.1144 +    if (d3_event_dragSelect) {
  1.1145 +      var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
  1.1146 +      style[d3_event_dragSelect] = "none";
  1.1147 +    }
  1.1148 +    return function(suppressClick) {
  1.1149 +      w.on(name, null);
  1.1150 +      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
  1.1151 +      if (suppressClick) {
  1.1152 +        var off = function() {
  1.1153 +          w.on(click, null);
  1.1154 +        };
  1.1155 +        w.on(click, function() {
  1.1156 +          d3_eventPreventDefault();
  1.1157 +          off();
  1.1158 +        }, true);
  1.1159 +        setTimeout(off, 0);
  1.1160 +      }
  1.1161 +    };
  1.1162 +  }
  1.1163 +  d3.mouse = function(container) {
  1.1164 +    return d3_mousePoint(container, d3_eventSource());
  1.1165 +  };
  1.1166 +  var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
  1.1167 +  function d3_mousePoint(container, e) {
  1.1168 +    if (e.changedTouches) e = e.changedTouches[0];
  1.1169 +    var svg = container.ownerSVGElement || container;
  1.1170 +    if (svg.createSVGPoint) {
  1.1171 +      var point = svg.createSVGPoint();
  1.1172 +      if (d3_mouse_bug44083 < 0) {
  1.1173 +        var window = d3_window(container);
  1.1174 +        if (window.scrollX || window.scrollY) {
  1.1175 +          svg = d3.select("body").append("svg").style({
  1.1176 +            position: "absolute",
  1.1177 +            top: 0,
  1.1178 +            left: 0,
  1.1179 +            margin: 0,
  1.1180 +            padding: 0,
  1.1181 +            border: "none"
  1.1182 +          }, "important");
  1.1183 +          var ctm = svg[0][0].getScreenCTM();
  1.1184 +          d3_mouse_bug44083 = !(ctm.f || ctm.e);
  1.1185 +          svg.remove();
  1.1186 +        }
  1.1187 +      }
  1.1188 +      if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 
  1.1189 +      point.y = e.clientY;
  1.1190 +      point = point.matrixTransform(container.getScreenCTM().inverse());
  1.1191 +      return [ point.x, point.y ];
  1.1192 +    }
  1.1193 +    var rect = container.getBoundingClientRect();
  1.1194 +    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
  1.1195 +  }
  1.1196 +  d3.touch = function(container, touches, identifier) {
  1.1197 +    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
  1.1198 +    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
  1.1199 +      if ((touch = touches[i]).identifier === identifier) {
  1.1200 +        return d3_mousePoint(container, touch);
  1.1201 +      }
  1.1202 +    }
  1.1203 +  };
  1.1204 +  d3.behavior.drag = function() {
  1.1205 +    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
  1.1206 +    function drag() {
  1.1207 +      this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
  1.1208 +    }
  1.1209 +    function dragstart(id, position, subject, move, end) {
  1.1210 +      return function() {
  1.1211 +        var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
  1.1212 +        if (origin) {
  1.1213 +          dragOffset = origin.apply(that, arguments);
  1.1214 +          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
  1.1215 +        } else {
  1.1216 +          dragOffset = [ 0, 0 ];
  1.1217 +        }
  1.1218 +        dispatch({
  1.1219 +          type: "dragstart"
  1.1220 +        });
  1.1221 +        function moved() {
  1.1222 +          var position1 = position(parent, dragId), dx, dy;
  1.1223 +          if (!position1) return;
  1.1224 +          dx = position1[0] - position0[0];
  1.1225 +          dy = position1[1] - position0[1];
  1.1226 +          dragged |= dx | dy;
  1.1227 +          position0 = position1;
  1.1228 +          dispatch({
  1.1229 +            type: "drag",
  1.1230 +            x: position1[0] + dragOffset[0],
  1.1231 +            y: position1[1] + dragOffset[1],
  1.1232 +            dx: dx,
  1.1233 +            dy: dy
  1.1234 +          });
  1.1235 +        }
  1.1236 +        function ended() {
  1.1237 +          if (!position(parent, dragId)) return;
  1.1238 +          dragSubject.on(move + dragName, null).on(end + dragName, null);
  1.1239 +          dragRestore(dragged);
  1.1240 +          dispatch({
  1.1241 +            type: "dragend"
  1.1242 +          });
  1.1243 +        }
  1.1244 +      };
  1.1245 +    }
  1.1246 +    drag.origin = function(x) {
  1.1247 +      if (!arguments.length) return origin;
  1.1248 +      origin = x;
  1.1249 +      return drag;
  1.1250 +    };
  1.1251 +    return d3.rebind(drag, event, "on");
  1.1252 +  };
  1.1253 +  function d3_behavior_dragTouchId() {
  1.1254 +    return d3.event.changedTouches[0].identifier;
  1.1255 +  }
  1.1256 +  d3.touches = function(container, touches) {
  1.1257 +    if (arguments.length < 2) touches = d3_eventSource().touches;
  1.1258 +    return touches ? d3_array(touches).map(function(touch) {
  1.1259 +      var point = d3_mousePoint(container, touch);
  1.1260 +      point.identifier = touch.identifier;
  1.1261 +      return point;
  1.1262 +    }) : [];
  1.1263 +  };
  1.1264 +  var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
  1.1265 +  function d3_sgn(x) {
  1.1266 +    return x > 0 ? 1 : x < 0 ? -1 : 0;
  1.1267 +  }
  1.1268 +  function d3_cross2d(a, b, c) {
  1.1269 +    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
  1.1270 +  }
  1.1271 +  function d3_acos(x) {
  1.1272 +    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
  1.1273 +  }
  1.1274 +  function d3_asin(x) {
  1.1275 +    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
  1.1276 +  }
  1.1277 +  function d3_sinh(x) {
  1.1278 +    return ((x = Math.exp(x)) - 1 / x) / 2;
  1.1279 +  }
  1.1280 +  function d3_cosh(x) {
  1.1281 +    return ((x = Math.exp(x)) + 1 / x) / 2;
  1.1282 +  }
  1.1283 +  function d3_tanh(x) {
  1.1284 +    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
  1.1285 +  }
  1.1286 +  function d3_haversin(x) {
  1.1287 +    return (x = Math.sin(x / 2)) * x;
  1.1288 +  }
  1.1289 +  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
  1.1290 +  d3.interpolateZoom = function(p0, p1) {
  1.1291 +    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S;
  1.1292 +    if (d2 < ε2) {
  1.1293 +      S = Math.log(w1 / w0) / ρ;
  1.1294 +      i = function(t) {
  1.1295 +        return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ];
  1.1296 +      };
  1.1297 +    } else {
  1.1298 +      var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
  1.1299 +      S = (r1 - r0) / ρ;
  1.1300 +      i = function(t) {
  1.1301 +        var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
  1.1302 +        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
  1.1303 +      };
  1.1304 +    }
  1.1305 +    i.duration = S * 1e3;
  1.1306 +    return i;
  1.1307 +  };
  1.1308 +  d3.behavior.zoom = function() {
  1.1309 +    var view = {
  1.1310 +      x: 0,
  1.1311 +      y: 0,
  1.1312 +      k: 1
  1.1313 +    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
  1.1314 +    if (!d3_behavior_zoomWheel) {
  1.1315 +      d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
  1.1316 +        return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
  1.1317 +      }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
  1.1318 +        return d3.event.wheelDelta;
  1.1319 +      }, "mousewheel") : (d3_behavior_zoomDelta = function() {
  1.1320 +        return -d3.event.detail;
  1.1321 +      }, "MozMousePixelScroll");
  1.1322 +    }
  1.1323 +    function zoom(g) {
  1.1324 +      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
  1.1325 +    }
  1.1326 +    zoom.event = function(g) {
  1.1327 +      g.each(function() {
  1.1328 +        var dispatch = event.of(this, arguments), view1 = view;
  1.1329 +        if (d3_transitionInheritId) {
  1.1330 +          d3.select(this).transition().each("start.zoom", function() {
  1.1331 +            view = this.__chart__ || {
  1.1332 +              x: 0,
  1.1333 +              y: 0,
  1.1334 +              k: 1
  1.1335 +            };
  1.1336 +            zoomstarted(dispatch);
  1.1337 +          }).tween("zoom:zoom", function() {
  1.1338 +            var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
  1.1339 +            return function(t) {
  1.1340 +              var l = i(t), k = dx / l[2];
  1.1341 +              this.__chart__ = view = {
  1.1342 +                x: cx - l[0] * k,
  1.1343 +                y: cy - l[1] * k,
  1.1344 +                k: k
  1.1345 +              };
  1.1346 +              zoomed(dispatch);
  1.1347 +            };
  1.1348 +          }).each("interrupt.zoom", function() {
  1.1349 +            zoomended(dispatch);
  1.1350 +          }).each("end.zoom", function() {
  1.1351 +            zoomended(dispatch);
  1.1352 +          });
  1.1353 +        } else {
  1.1354 +          this.__chart__ = view;
  1.1355 +          zoomstarted(dispatch);
  1.1356 +          zoomed(dispatch);
  1.1357 +          zoomended(dispatch);
  1.1358 +        }
  1.1359 +      });
  1.1360 +    };
  1.1361 +    zoom.translate = function(_) {
  1.1362 +      if (!arguments.length) return [ view.x, view.y ];
  1.1363 +      view = {
  1.1364 +        x: +_[0],
  1.1365 +        y: +_[1],
  1.1366 +        k: view.k
  1.1367 +      };
  1.1368 +      rescale();
  1.1369 +      return zoom;
  1.1370 +    };
  1.1371 +    zoom.scale = function(_) {
  1.1372 +      if (!arguments.length) return view.k;
  1.1373 +      view = {
  1.1374 +        x: view.x,
  1.1375 +        y: view.y,
  1.1376 +        k: null
  1.1377 +      };
  1.1378 +      scaleTo(+_);
  1.1379 +      rescale();
  1.1380 +      return zoom;
  1.1381 +    };
  1.1382 +    zoom.scaleExtent = function(_) {
  1.1383 +      if (!arguments.length) return scaleExtent;
  1.1384 +      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
  1.1385 +      return zoom;
  1.1386 +    };
  1.1387 +    zoom.center = function(_) {
  1.1388 +      if (!arguments.length) return center;
  1.1389 +      center = _ && [ +_[0], +_[1] ];
  1.1390 +      return zoom;
  1.1391 +    };
  1.1392 +    zoom.size = function(_) {
  1.1393 +      if (!arguments.length) return size;
  1.1394 +      size = _ && [ +_[0], +_[1] ];
  1.1395 +      return zoom;
  1.1396 +    };
  1.1397 +    zoom.duration = function(_) {
  1.1398 +      if (!arguments.length) return duration;
  1.1399 +      duration = +_;
  1.1400 +      return zoom;
  1.1401 +    };
  1.1402 +    zoom.x = function(z) {
  1.1403 +      if (!arguments.length) return x1;
  1.1404 +      x1 = z;
  1.1405 +      x0 = z.copy();
  1.1406 +      view = {
  1.1407 +        x: 0,
  1.1408 +        y: 0,
  1.1409 +        k: 1
  1.1410 +      };
  1.1411 +      return zoom;
  1.1412 +    };
  1.1413 +    zoom.y = function(z) {
  1.1414 +      if (!arguments.length) return y1;
  1.1415 +      y1 = z;
  1.1416 +      y0 = z.copy();
  1.1417 +      view = {
  1.1418 +        x: 0,
  1.1419 +        y: 0,
  1.1420 +        k: 1
  1.1421 +      };
  1.1422 +      return zoom;
  1.1423 +    };
  1.1424 +    function location(p) {
  1.1425 +      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
  1.1426 +    }
  1.1427 +    function point(l) {
  1.1428 +      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
  1.1429 +    }
  1.1430 +    function scaleTo(s) {
  1.1431 +      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
  1.1432 +    }
  1.1433 +    function translateTo(p, l) {
  1.1434 +      l = point(l);
  1.1435 +      view.x += p[0] - l[0];
  1.1436 +      view.y += p[1] - l[1];
  1.1437 +    }
  1.1438 +    function zoomTo(that, p, l, k) {
  1.1439 +      that.__chart__ = {
  1.1440 +        x: view.x,
  1.1441 +        y: view.y,
  1.1442 +        k: view.k
  1.1443 +      };
  1.1444 +      scaleTo(Math.pow(2, k));
  1.1445 +      translateTo(center0 = p, l);
  1.1446 +      that = d3.select(that);
  1.1447 +      if (duration > 0) that = that.transition().duration(duration);
  1.1448 +      that.call(zoom.event);
  1.1449 +    }
  1.1450 +    function rescale() {
  1.1451 +      if (x1) x1.domain(x0.range().map(function(x) {
  1.1452 +        return (x - view.x) / view.k;
  1.1453 +      }).map(x0.invert));
  1.1454 +      if (y1) y1.domain(y0.range().map(function(y) {
  1.1455 +        return (y - view.y) / view.k;
  1.1456 +      }).map(y0.invert));
  1.1457 +    }
  1.1458 +    function zoomstarted(dispatch) {
  1.1459 +      if (!zooming++) dispatch({
  1.1460 +        type: "zoomstart"
  1.1461 +      });
  1.1462 +    }
  1.1463 +    function zoomed(dispatch) {
  1.1464 +      rescale();
  1.1465 +      dispatch({
  1.1466 +        type: "zoom",
  1.1467 +        scale: view.k,
  1.1468 +        translate: [ view.x, view.y ]
  1.1469 +      });
  1.1470 +    }
  1.1471 +    function zoomended(dispatch) {
  1.1472 +      if (!--zooming) dispatch({
  1.1473 +        type: "zoomend"
  1.1474 +      }), center0 = null;
  1.1475 +    }
  1.1476 +    function mousedowned() {
  1.1477 +      var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
  1.1478 +      d3_selection_interrupt.call(that);
  1.1479 +      zoomstarted(dispatch);
  1.1480 +      function moved() {
  1.1481 +        dragged = 1;
  1.1482 +        translateTo(d3.mouse(that), location0);
  1.1483 +        zoomed(dispatch);
  1.1484 +      }
  1.1485 +      function ended() {
  1.1486 +        subject.on(mousemove, null).on(mouseup, null);
  1.1487 +        dragRestore(dragged);
  1.1488 +        zoomended(dispatch);
  1.1489 +      }
  1.1490 +    }
  1.1491 +    function touchstarted() {
  1.1492 +      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
  1.1493 +      started();
  1.1494 +      zoomstarted(dispatch);
  1.1495 +      subject.on(mousedown, null).on(touchstart, started);
  1.1496 +      function relocate() {
  1.1497 +        var touches = d3.touches(that);
  1.1498 +        scale0 = view.k;
  1.1499 +        touches.forEach(function(t) {
  1.1500 +          if (t.identifier in locations0) locations0[t.identifier] = location(t);
  1.1501 +        });
  1.1502 +        return touches;
  1.1503 +      }
  1.1504 +      function started() {
  1.1505 +        var target = d3.event.target;
  1.1506 +        d3.select(target).on(touchmove, moved).on(touchend, ended);
  1.1507 +        targets.push(target);
  1.1508 +        var changed = d3.event.changedTouches;
  1.1509 +        for (var i = 0, n = changed.length; i < n; ++i) {
  1.1510 +          locations0[changed[i].identifier] = null;
  1.1511 +        }
  1.1512 +        var touches = relocate(), now = Date.now();
  1.1513 +        if (touches.length === 1) {
  1.1514 +          if (now - touchtime < 500) {
  1.1515 +            var p = touches[0];
  1.1516 +            zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
  1.1517 +            d3_eventPreventDefault();
  1.1518 +          }
  1.1519 +          touchtime = now;
  1.1520 +        } else if (touches.length > 1) {
  1.1521 +          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
  1.1522 +          distance0 = dx * dx + dy * dy;
  1.1523 +        }
  1.1524 +      }
  1.1525 +      function moved() {
  1.1526 +        var touches = d3.touches(that), p0, l0, p1, l1;
  1.1527 +        d3_selection_interrupt.call(that);
  1.1528 +        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
  1.1529 +          p1 = touches[i];
  1.1530 +          if (l1 = locations0[p1.identifier]) {
  1.1531 +            if (l0) break;
  1.1532 +            p0 = p1, l0 = l1;
  1.1533 +          }
  1.1534 +        }
  1.1535 +        if (l1) {
  1.1536 +          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
  1.1537 +          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
  1.1538 +          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
  1.1539 +          scaleTo(scale1 * scale0);
  1.1540 +        }
  1.1541 +        touchtime = null;
  1.1542 +        translateTo(p0, l0);
  1.1543 +        zoomed(dispatch);
  1.1544 +      }
  1.1545 +      function ended() {
  1.1546 +        if (d3.event.touches.length) {
  1.1547 +          var changed = d3.event.changedTouches;
  1.1548 +          for (var i = 0, n = changed.length; i < n; ++i) {
  1.1549 +            delete locations0[changed[i].identifier];
  1.1550 +          }
  1.1551 +          for (var identifier in locations0) {
  1.1552 +            return void relocate();
  1.1553 +          }
  1.1554 +        }
  1.1555 +        d3.selectAll(targets).on(zoomName, null);
  1.1556 +        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
  1.1557 +        dragRestore();
  1.1558 +        zoomended(dispatch);
  1.1559 +      }
  1.1560 +    }
  1.1561 +    function mousewheeled() {
  1.1562 +      var dispatch = event.of(this, arguments);
  1.1563 +      if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), 
  1.1564 +      translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch);
  1.1565 +      mousewheelTimer = setTimeout(function() {
  1.1566 +        mousewheelTimer = null;
  1.1567 +        zoomended(dispatch);
  1.1568 +      }, 50);
  1.1569 +      d3_eventPreventDefault();
  1.1570 +      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
  1.1571 +      translateTo(center0, translate0);
  1.1572 +      zoomed(dispatch);
  1.1573 +    }
  1.1574 +    function dblclicked() {
  1.1575 +      var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
  1.1576 +      zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
  1.1577 +    }
  1.1578 +    return d3.rebind(zoom, event, "on");
  1.1579 +  };
  1.1580 +  var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
  1.1581 +  d3.color = d3_color;
  1.1582 +  function d3_color() {}
  1.1583 +  d3_color.prototype.toString = function() {
  1.1584 +    return this.rgb() + "";
  1.1585 +  };
  1.1586 +  d3.hsl = d3_hsl;
  1.1587 +  function d3_hsl(h, s, l) {
  1.1588 +    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
  1.1589 +  }
  1.1590 +  var d3_hslPrototype = d3_hsl.prototype = new d3_color();
  1.1591 +  d3_hslPrototype.brighter = function(k) {
  1.1592 +    k = Math.pow(.7, arguments.length ? k : 1);
  1.1593 +    return new d3_hsl(this.h, this.s, this.l / k);
  1.1594 +  };
  1.1595 +  d3_hslPrototype.darker = function(k) {
  1.1596 +    k = Math.pow(.7, arguments.length ? k : 1);
  1.1597 +    return new d3_hsl(this.h, this.s, k * this.l);
  1.1598 +  };
  1.1599 +  d3_hslPrototype.rgb = function() {
  1.1600 +    return d3_hsl_rgb(this.h, this.s, this.l);
  1.1601 +  };
  1.1602 +  function d3_hsl_rgb(h, s, l) {
  1.1603 +    var m1, m2;
  1.1604 +    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
  1.1605 +    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
  1.1606 +    l = l < 0 ? 0 : l > 1 ? 1 : l;
  1.1607 +    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
  1.1608 +    m1 = 2 * l - m2;
  1.1609 +    function v(h) {
  1.1610 +      if (h > 360) h -= 360; else if (h < 0) h += 360;
  1.1611 +      if (h < 60) return m1 + (m2 - m1) * h / 60;
  1.1612 +      if (h < 180) return m2;
  1.1613 +      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
  1.1614 +      return m1;
  1.1615 +    }
  1.1616 +    function vv(h) {
  1.1617 +      return Math.round(v(h) * 255);
  1.1618 +    }
  1.1619 +    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
  1.1620 +  }
  1.1621 +  d3.hcl = d3_hcl;
  1.1622 +  function d3_hcl(h, c, l) {
  1.1623 +    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
  1.1624 +  }
  1.1625 +  var d3_hclPrototype = d3_hcl.prototype = new d3_color();
  1.1626 +  d3_hclPrototype.brighter = function(k) {
  1.1627 +    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
  1.1628 +  };
  1.1629 +  d3_hclPrototype.darker = function(k) {
  1.1630 +    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
  1.1631 +  };
  1.1632 +  d3_hclPrototype.rgb = function() {
  1.1633 +    return d3_hcl_lab(this.h, this.c, this.l).rgb();
  1.1634 +  };
  1.1635 +  function d3_hcl_lab(h, c, l) {
  1.1636 +    if (isNaN(h)) h = 0;
  1.1637 +    if (isNaN(c)) c = 0;
  1.1638 +    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
  1.1639 +  }
  1.1640 +  d3.lab = d3_lab;
  1.1641 +  function d3_lab(l, a, b) {
  1.1642 +    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
  1.1643 +  }
  1.1644 +  var d3_lab_K = 18;
  1.1645 +  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
  1.1646 +  var d3_labPrototype = d3_lab.prototype = new d3_color();
  1.1647 +  d3_labPrototype.brighter = function(k) {
  1.1648 +    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
  1.1649 +  };
  1.1650 +  d3_labPrototype.darker = function(k) {
  1.1651 +    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
  1.1652 +  };
  1.1653 +  d3_labPrototype.rgb = function() {
  1.1654 +    return d3_lab_rgb(this.l, this.a, this.b);
  1.1655 +  };
  1.1656 +  function d3_lab_rgb(l, a, b) {
  1.1657 +    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
  1.1658 +    x = d3_lab_xyz(x) * d3_lab_X;
  1.1659 +    y = d3_lab_xyz(y) * d3_lab_Y;
  1.1660 +    z = d3_lab_xyz(z) * d3_lab_Z;
  1.1661 +    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
  1.1662 +  }
  1.1663 +  function d3_lab_hcl(l, a, b) {
  1.1664 +    return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
  1.1665 +  }
  1.1666 +  function d3_lab_xyz(x) {
  1.1667 +    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
  1.1668 +  }
  1.1669 +  function d3_xyz_lab(x) {
  1.1670 +    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
  1.1671 +  }
  1.1672 +  function d3_xyz_rgb(r) {
  1.1673 +    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
  1.1674 +  }
  1.1675 +  d3.rgb = d3_rgb;
  1.1676 +  function d3_rgb(r, g, b) {
  1.1677 +    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
  1.1678 +  }
  1.1679 +  function d3_rgbNumber(value) {
  1.1680 +    return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
  1.1681 +  }
  1.1682 +  function d3_rgbString(value) {
  1.1683 +    return d3_rgbNumber(value) + "";
  1.1684 +  }
  1.1685 +  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
  1.1686 +  d3_rgbPrototype.brighter = function(k) {
  1.1687 +    k = Math.pow(.7, arguments.length ? k : 1);
  1.1688 +    var r = this.r, g = this.g, b = this.b, i = 30;
  1.1689 +    if (!r && !g && !b) return new d3_rgb(i, i, i);
  1.1690 +    if (r && r < i) r = i;
  1.1691 +    if (g && g < i) g = i;
  1.1692 +    if (b && b < i) b = i;
  1.1693 +    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
  1.1694 +  };
  1.1695 +  d3_rgbPrototype.darker = function(k) {
  1.1696 +    k = Math.pow(.7, arguments.length ? k : 1);
  1.1697 +    return new d3_rgb(k * this.r, k * this.g, k * this.b);
  1.1698 +  };
  1.1699 +  d3_rgbPrototype.hsl = function() {
  1.1700 +    return d3_rgb_hsl(this.r, this.g, this.b);
  1.1701 +  };
  1.1702 +  d3_rgbPrototype.toString = function() {
  1.1703 +    return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
  1.1704 +  };
  1.1705 +  function d3_rgb_hex(v) {
  1.1706 +    return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
  1.1707 +  }
  1.1708 +  function d3_rgb_parse(format, rgb, hsl) {
  1.1709 +    var r = 0, g = 0, b = 0, m1, m2, color;
  1.1710 +    m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase());
  1.1711 +    if (m1) {
  1.1712 +      m2 = m1[2].split(",");
  1.1713 +      switch (m1[1]) {
  1.1714 +       case "hsl":
  1.1715 +        {
  1.1716 +          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
  1.1717 +        }
  1.1718 +
  1.1719 +       case "rgb":
  1.1720 +        {
  1.1721 +          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
  1.1722 +        }
  1.1723 +      }
  1.1724 +    }
  1.1725 +    if (color = d3_rgb_names.get(format)) {
  1.1726 +      return rgb(color.r, color.g, color.b);
  1.1727 +    }
  1.1728 +    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
  1.1729 +      if (format.length === 4) {
  1.1730 +        r = (color & 3840) >> 4;
  1.1731 +        r = r >> 4 | r;
  1.1732 +        g = color & 240;
  1.1733 +        g = g >> 4 | g;
  1.1734 +        b = color & 15;
  1.1735 +        b = b << 4 | b;
  1.1736 +      } else if (format.length === 7) {
  1.1737 +        r = (color & 16711680) >> 16;
  1.1738 +        g = (color & 65280) >> 8;
  1.1739 +        b = color & 255;
  1.1740 +      }
  1.1741 +    }
  1.1742 +    return rgb(r, g, b);
  1.1743 +  }
  1.1744 +  function d3_rgb_hsl(r, g, b) {
  1.1745 +    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
  1.1746 +    if (d) {
  1.1747 +      s = l < .5 ? d / (max + min) : d / (2 - max - min);
  1.1748 +      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
  1.1749 +      h *= 60;
  1.1750 +    } else {
  1.1751 +      h = NaN;
  1.1752 +      s = l > 0 && l < 1 ? 0 : h;
  1.1753 +    }
  1.1754 +    return new d3_hsl(h, s, l);
  1.1755 +  }
  1.1756 +  function d3_rgb_lab(r, g, b) {
  1.1757 +    r = d3_rgb_xyz(r);
  1.1758 +    g = d3_rgb_xyz(g);
  1.1759 +    b = d3_rgb_xyz(b);
  1.1760 +    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
  1.1761 +    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
  1.1762 +  }
  1.1763 +  function d3_rgb_xyz(r) {
  1.1764 +    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
  1.1765 +  }
  1.1766 +  function d3_rgb_parseNumber(c) {
  1.1767 +    var f = parseFloat(c);
  1.1768 +    return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
  1.1769 +  }
  1.1770 +  var d3_rgb_names = d3.map({
  1.1771 +    aliceblue: 15792383,
  1.1772 +    antiquewhite: 16444375,
  1.1773 +    aqua: 65535,
  1.1774 +    aquamarine: 8388564,
  1.1775 +    azure: 15794175,
  1.1776 +    beige: 16119260,
  1.1777 +    bisque: 16770244,
  1.1778 +    black: 0,
  1.1779 +    blanchedalmond: 16772045,
  1.1780 +    blue: 255,
  1.1781 +    blueviolet: 9055202,
  1.1782 +    brown: 10824234,
  1.1783 +    burlywood: 14596231,
  1.1784 +    cadetblue: 6266528,
  1.1785 +    chartreuse: 8388352,
  1.1786 +    chocolate: 13789470,
  1.1787 +    coral: 16744272,
  1.1788 +    cornflowerblue: 6591981,
  1.1789 +    cornsilk: 16775388,
  1.1790 +    crimson: 14423100,
  1.1791 +    cyan: 65535,
  1.1792 +    darkblue: 139,
  1.1793 +    darkcyan: 35723,
  1.1794 +    darkgoldenrod: 12092939,
  1.1795 +    darkgray: 11119017,
  1.1796 +    darkgreen: 25600,
  1.1797 +    darkgrey: 11119017,
  1.1798 +    darkkhaki: 12433259,
  1.1799 +    darkmagenta: 9109643,
  1.1800 +    darkolivegreen: 5597999,
  1.1801 +    darkorange: 16747520,
  1.1802 +    darkorchid: 10040012,
  1.1803 +    darkred: 9109504,
  1.1804 +    darksalmon: 15308410,
  1.1805 +    darkseagreen: 9419919,
  1.1806 +    darkslateblue: 4734347,
  1.1807 +    darkslategray: 3100495,
  1.1808 +    darkslategrey: 3100495,
  1.1809 +    darkturquoise: 52945,
  1.1810 +    darkviolet: 9699539,
  1.1811 +    deeppink: 16716947,
  1.1812 +    deepskyblue: 49151,
  1.1813 +    dimgray: 6908265,
  1.1814 +    dimgrey: 6908265,
  1.1815 +    dodgerblue: 2003199,
  1.1816 +    firebrick: 11674146,
  1.1817 +    floralwhite: 16775920,
  1.1818 +    forestgreen: 2263842,
  1.1819 +    fuchsia: 16711935,
  1.1820 +    gainsboro: 14474460,
  1.1821 +    ghostwhite: 16316671,
  1.1822 +    gold: 16766720,
  1.1823 +    goldenrod: 14329120,
  1.1824 +    gray: 8421504,
  1.1825 +    green: 32768,
  1.1826 +    greenyellow: 11403055,
  1.1827 +    grey: 8421504,
  1.1828 +    honeydew: 15794160,
  1.1829 +    hotpink: 16738740,
  1.1830 +    indianred: 13458524,
  1.1831 +    indigo: 4915330,
  1.1832 +    ivory: 16777200,
  1.1833 +    khaki: 15787660,
  1.1834 +    lavender: 15132410,
  1.1835 +    lavenderblush: 16773365,
  1.1836 +    lawngreen: 8190976,
  1.1837 +    lemonchiffon: 16775885,
  1.1838 +    lightblue: 11393254,
  1.1839 +    lightcoral: 15761536,
  1.1840 +    lightcyan: 14745599,
  1.1841 +    lightgoldenrodyellow: 16448210,
  1.1842 +    lightgray: 13882323,
  1.1843 +    lightgreen: 9498256,
  1.1844 +    lightgrey: 13882323,
  1.1845 +    lightpink: 16758465,
  1.1846 +    lightsalmon: 16752762,
  1.1847 +    lightseagreen: 2142890,
  1.1848 +    lightskyblue: 8900346,
  1.1849 +    lightslategray: 7833753,
  1.1850 +    lightslategrey: 7833753,
  1.1851 +    lightsteelblue: 11584734,
  1.1852 +    lightyellow: 16777184,
  1.1853 +    lime: 65280,
  1.1854 +    limegreen: 3329330,
  1.1855 +    linen: 16445670,
  1.1856 +    magenta: 16711935,
  1.1857 +    maroon: 8388608,
  1.1858 +    mediumaquamarine: 6737322,
  1.1859 +    mediumblue: 205,
  1.1860 +    mediumorchid: 12211667,
  1.1861 +    mediumpurple: 9662683,
  1.1862 +    mediumseagreen: 3978097,
  1.1863 +    mediumslateblue: 8087790,
  1.1864 +    mediumspringgreen: 64154,
  1.1865 +    mediumturquoise: 4772300,
  1.1866 +    mediumvioletred: 13047173,
  1.1867 +    midnightblue: 1644912,
  1.1868 +    mintcream: 16121850,
  1.1869 +    mistyrose: 16770273,
  1.1870 +    moccasin: 16770229,
  1.1871 +    navajowhite: 16768685,
  1.1872 +    navy: 128,
  1.1873 +    oldlace: 16643558,
  1.1874 +    olive: 8421376,
  1.1875 +    olivedrab: 7048739,
  1.1876 +    orange: 16753920,
  1.1877 +    orangered: 16729344,
  1.1878 +    orchid: 14315734,
  1.1879 +    palegoldenrod: 15657130,
  1.1880 +    palegreen: 10025880,
  1.1881 +    paleturquoise: 11529966,
  1.1882 +    palevioletred: 14381203,
  1.1883 +    papayawhip: 16773077,
  1.1884 +    peachpuff: 16767673,
  1.1885 +    peru: 13468991,
  1.1886 +    pink: 16761035,
  1.1887 +    plum: 14524637,
  1.1888 +    powderblue: 11591910,
  1.1889 +    purple: 8388736,
  1.1890 +    rebeccapurple: 6697881,
  1.1891 +    red: 16711680,
  1.1892 +    rosybrown: 12357519,
  1.1893 +    royalblue: 4286945,
  1.1894 +    saddlebrown: 9127187,
  1.1895 +    salmon: 16416882,
  1.1896 +    sandybrown: 16032864,
  1.1897 +    seagreen: 3050327,
  1.1898 +    seashell: 16774638,
  1.1899 +    sienna: 10506797,
  1.1900 +    silver: 12632256,
  1.1901 +    skyblue: 8900331,
  1.1902 +    slateblue: 6970061,
  1.1903 +    slategray: 7372944,
  1.1904 +    slategrey: 7372944,
  1.1905 +    snow: 16775930,
  1.1906 +    springgreen: 65407,
  1.1907 +    steelblue: 4620980,
  1.1908 +    tan: 13808780,
  1.1909 +    teal: 32896,
  1.1910 +    thistle: 14204888,
  1.1911 +    tomato: 16737095,
  1.1912 +    turquoise: 4251856,
  1.1913 +    violet: 15631086,
  1.1914 +    wheat: 16113331,
  1.1915 +    white: 16777215,
  1.1916 +    whitesmoke: 16119285,
  1.1917 +    yellow: 16776960,
  1.1918 +    yellowgreen: 10145074
  1.1919 +  });
  1.1920 +  d3_rgb_names.forEach(function(key, value) {
  1.1921 +    d3_rgb_names.set(key, d3_rgbNumber(value));
  1.1922 +  });
  1.1923 +  function d3_functor(v) {
  1.1924 +    return typeof v === "function" ? v : function() {
  1.1925 +      return v;
  1.1926 +    };
  1.1927 +  }
  1.1928 +  d3.functor = d3_functor;
  1.1929 +  d3.xhr = d3_xhrType(d3_identity);
  1.1930 +  function d3_xhrType(response) {
  1.1931 +    return function(url, mimeType, callback) {
  1.1932 +      if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
  1.1933 +      mimeType = null;
  1.1934 +      return d3_xhr(url, mimeType, response, callback);
  1.1935 +    };
  1.1936 +  }
  1.1937 +  function d3_xhr(url, mimeType, response, callback) {
  1.1938 +    var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
  1.1939 +    if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
  1.1940 +    "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
  1.1941 +      request.readyState > 3 && respond();
  1.1942 +    };
  1.1943 +    function respond() {
  1.1944 +      var status = request.status, result;
  1.1945 +      if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
  1.1946 +        try {
  1.1947 +          result = response.call(xhr, request);
  1.1948 +        } catch (e) {
  1.1949 +          dispatch.error.call(xhr, e);
  1.1950 +          return;
  1.1951 +        }
  1.1952 +        dispatch.load.call(xhr, result);
  1.1953 +      } else {
  1.1954 +        dispatch.error.call(xhr, request);
  1.1955 +      }
  1.1956 +    }
  1.1957 +    request.onprogress = function(event) {
  1.1958 +      var o = d3.event;
  1.1959 +      d3.event = event;
  1.1960 +      try {
  1.1961 +        dispatch.progress.call(xhr, request);
  1.1962 +      } finally {
  1.1963 +        d3.event = o;
  1.1964 +      }
  1.1965 +    };
  1.1966 +    xhr.header = function(name, value) {
  1.1967 +      name = (name + "").toLowerCase();
  1.1968 +      if (arguments.length < 2) return headers[name];
  1.1969 +      if (value == null) delete headers[name]; else headers[name] = value + "";
  1.1970 +      return xhr;
  1.1971 +    };
  1.1972 +    xhr.mimeType = function(value) {
  1.1973 +      if (!arguments.length) return mimeType;
  1.1974 +      mimeType = value == null ? null : value + "";
  1.1975 +      return xhr;
  1.1976 +    };
  1.1977 +    xhr.responseType = function(value) {
  1.1978 +      if (!arguments.length) return responseType;
  1.1979 +      responseType = value;
  1.1980 +      return xhr;
  1.1981 +    };
  1.1982 +    xhr.response = function(value) {
  1.1983 +      response = value;
  1.1984 +      return xhr;
  1.1985 +    };
  1.1986 +    [ "get", "post" ].forEach(function(method) {
  1.1987 +      xhr[method] = function() {
  1.1988 +        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
  1.1989 +      };
  1.1990 +    });
  1.1991 +    xhr.send = function(method, data, callback) {
  1.1992 +      if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
  1.1993 +      request.open(method, url, true);
  1.1994 +      if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
  1.1995 +      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
  1.1996 +      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
  1.1997 +      if (responseType != null) request.responseType = responseType;
  1.1998 +      if (callback != null) xhr.on("error", callback).on("load", function(request) {
  1.1999 +        callback(null, request);
  1.2000 +      });
  1.2001 +      dispatch.beforesend.call(xhr, request);
  1.2002 +      request.send(data == null ? null : data);
  1.2003 +      return xhr;
  1.2004 +    };
  1.2005 +    xhr.abort = function() {
  1.2006 +      request.abort();
  1.2007 +      return xhr;
  1.2008 +    };
  1.2009 +    d3.rebind(xhr, dispatch, "on");
  1.2010 +    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
  1.2011 +  }
  1.2012 +  function d3_xhr_fixCallback(callback) {
  1.2013 +    return callback.length === 1 ? function(error, request) {
  1.2014 +      callback(error == null ? request : null);
  1.2015 +    } : callback;
  1.2016 +  }
  1.2017 +  function d3_xhrHasResponse(request) {
  1.2018 +    var type = request.responseType;
  1.2019 +    return type && type !== "text" ? request.response : request.responseText;
  1.2020 +  }
  1.2021 +  d3.dsv = function(delimiter, mimeType) {
  1.2022 +    var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
  1.2023 +    function dsv(url, row, callback) {
  1.2024 +      if (arguments.length < 3) callback = row, row = null;
  1.2025 +      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
  1.2026 +      xhr.row = function(_) {
  1.2027 +        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
  1.2028 +      };
  1.2029 +      return xhr;
  1.2030 +    }
  1.2031 +    function response(request) {
  1.2032 +      return dsv.parse(request.responseText);
  1.2033 +    }
  1.2034 +    function typedResponse(f) {
  1.2035 +      return function(request) {
  1.2036 +        return dsv.parse(request.responseText, f);
  1.2037 +      };
  1.2038 +    }
  1.2039 +    dsv.parse = function(text, f) {
  1.2040 +      var o;
  1.2041 +      return dsv.parseRows(text, function(row, i) {
  1.2042 +        if (o) return o(row, i - 1);
  1.2043 +        var a = new Function("d", "return {" + row.map(function(name, i) {
  1.2044 +          return JSON.stringify(name) + ": d[" + i + "]";
  1.2045 +        }).join(",") + "}");
  1.2046 +        o = f ? function(row, i) {
  1.2047 +          return f(a(row), i);
  1.2048 +        } : a;
  1.2049 +      });
  1.2050 +    };
  1.2051 +    dsv.parseRows = function(text, f) {
  1.2052 +      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
  1.2053 +      function token() {
  1.2054 +        if (I >= N) return EOF;
  1.2055 +        if (eol) return eol = false, EOL;
  1.2056 +        var j = I;
  1.2057 +        if (text.charCodeAt(j) === 34) {
  1.2058 +          var i = j;
  1.2059 +          while (i++ < N) {
  1.2060 +            if (text.charCodeAt(i) === 34) {
  1.2061 +              if (text.charCodeAt(i + 1) !== 34) break;
  1.2062 +              ++i;
  1.2063 +            }
  1.2064 +          }
  1.2065 +          I = i + 2;
  1.2066 +          var c = text.charCodeAt(i + 1);
  1.2067 +          if (c === 13) {
  1.2068 +            eol = true;
  1.2069 +            if (text.charCodeAt(i + 2) === 10) ++I;
  1.2070 +          } else if (c === 10) {
  1.2071 +            eol = true;
  1.2072 +          }
  1.2073 +          return text.slice(j + 1, i).replace(/""/g, '"');
  1.2074 +        }
  1.2075 +        while (I < N) {
  1.2076 +          var c = text.charCodeAt(I++), k = 1;
  1.2077 +          if (c === 10) eol = true; else if (c === 13) {
  1.2078 +            eol = true;
  1.2079 +            if (text.charCodeAt(I) === 10) ++I, ++k;
  1.2080 +          } else if (c !== delimiterCode) continue;
  1.2081 +          return text.slice(j, I - k);
  1.2082 +        }
  1.2083 +        return text.slice(j);
  1.2084 +      }
  1.2085 +      while ((t = token()) !== EOF) {
  1.2086 +        var a = [];
  1.2087 +        while (t !== EOL && t !== EOF) {
  1.2088 +          a.push(t);
  1.2089 +          t = token();
  1.2090 +        }
  1.2091 +        if (f && (a = f(a, n++)) == null) continue;
  1.2092 +        rows.push(a);
  1.2093 +      }
  1.2094 +      return rows;
  1.2095 +    };
  1.2096 +    dsv.format = function(rows) {
  1.2097 +      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
  1.2098 +      var fieldSet = new d3_Set(), fields = [];
  1.2099 +      rows.forEach(function(row) {
  1.2100 +        for (var field in row) {
  1.2101 +          if (!fieldSet.has(field)) {
  1.2102 +            fields.push(fieldSet.add(field));
  1.2103 +          }
  1.2104 +        }
  1.2105 +      });
  1.2106 +      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
  1.2107 +        return fields.map(function(field) {
  1.2108 +          return formatValue(row[field]);
  1.2109 +        }).join(delimiter);
  1.2110 +      })).join("\n");
  1.2111 +    };
  1.2112 +    dsv.formatRows = function(rows) {
  1.2113 +      return rows.map(formatRow).join("\n");
  1.2114 +    };
  1.2115 +    function formatRow(row) {
  1.2116 +      return row.map(formatValue).join(delimiter);
  1.2117 +    }
  1.2118 +    function formatValue(text) {
  1.2119 +      return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
  1.2120 +    }
  1.2121 +    return dsv;
  1.2122 +  };
  1.2123 +  d3.csv = d3.dsv(",", "text/csv");
  1.2124 +  d3.tsv = d3.dsv("	", "text/tab-separated-values");
  1.2125 +  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
  1.2126 +    setTimeout(callback, 17);
  1.2127 +  };
  1.2128 +  d3.timer = function() {
  1.2129 +    d3_timer.apply(this, arguments);
  1.2130 +  };
  1.2131 +  function d3_timer(callback, delay, then) {
  1.2132 +    var n = arguments.length;
  1.2133 +    if (n < 2) delay = 0;
  1.2134 +    if (n < 3) then = Date.now();
  1.2135 +    var time = then + delay, timer = {
  1.2136 +      c: callback,
  1.2137 +      t: time,
  1.2138 +      n: null
  1.2139 +    };
  1.2140 +    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
  1.2141 +    d3_timer_queueTail = timer;
  1.2142 +    if (!d3_timer_interval) {
  1.2143 +      d3_timer_timeout = clearTimeout(d3_timer_timeout);
  1.2144 +      d3_timer_interval = 1;
  1.2145 +      d3_timer_frame(d3_timer_step);
  1.2146 +    }
  1.2147 +    return timer;
  1.2148 +  }
  1.2149 +  function d3_timer_step() {
  1.2150 +    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
  1.2151 +    if (delay > 24) {
  1.2152 +      if (isFinite(delay)) {
  1.2153 +        clearTimeout(d3_timer_timeout);
  1.2154 +        d3_timer_timeout = setTimeout(d3_timer_step, delay);
  1.2155 +      }
  1.2156 +      d3_timer_interval = 0;
  1.2157 +    } else {
  1.2158 +      d3_timer_interval = 1;
  1.2159 +      d3_timer_frame(d3_timer_step);
  1.2160 +    }
  1.2161 +  }
  1.2162 +  d3.timer.flush = function() {
  1.2163 +    d3_timer_mark();
  1.2164 +    d3_timer_sweep();
  1.2165 +  };
  1.2166 +  function d3_timer_mark() {
  1.2167 +    var now = Date.now(), timer = d3_timer_queueHead;
  1.2168 +    while (timer) {
  1.2169 +      if (now >= timer.t && timer.c(now - timer.t)) timer.c = null;
  1.2170 +      timer = timer.n;
  1.2171 +    }
  1.2172 +    return now;
  1.2173 +  }
  1.2174 +  function d3_timer_sweep() {
  1.2175 +    var t0, t1 = d3_timer_queueHead, time = Infinity;
  1.2176 +    while (t1) {
  1.2177 +      if (t1.c) {
  1.2178 +        if (t1.t < time) time = t1.t;
  1.2179 +        t1 = (t0 = t1).n;
  1.2180 +      } else {
  1.2181 +        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
  1.2182 +      }
  1.2183 +    }
  1.2184 +    d3_timer_queueTail = t0;
  1.2185 +    return time;
  1.2186 +  }
  1.2187 +  function d3_format_precision(x, p) {
  1.2188 +    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
  1.2189 +  }
  1.2190 +  d3.round = function(x, n) {
  1.2191 +    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
  1.2192 +  };
  1.2193 +  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
  1.2194 +  d3.formatPrefix = function(value, precision) {
  1.2195 +    var i = 0;
  1.2196 +    if (value = +value) {
  1.2197 +      if (value < 0) value *= -1;
  1.2198 +      if (precision) value = d3.round(value, d3_format_precision(value, precision));
  1.2199 +      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
  1.2200 +      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
  1.2201 +    }
  1.2202 +    return d3_formatPrefixes[8 + i / 3];
  1.2203 +  };
  1.2204 +  function d3_formatPrefix(d, i) {
  1.2205 +    var k = Math.pow(10, abs(8 - i) * 3);
  1.2206 +    return {
  1.2207 +      scale: i > 8 ? function(d) {
  1.2208 +        return d / k;
  1.2209 +      } : function(d) {
  1.2210 +        return d * k;
  1.2211 +      },
  1.2212 +      symbol: d
  1.2213 +    };
  1.2214 +  }
  1.2215 +  function d3_locale_numberFormat(locale) {
  1.2216 +    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
  1.2217 +      var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
  1.2218 +      while (i > 0 && g > 0) {
  1.2219 +        if (length + g + 1 > width) g = Math.max(1, width - length);
  1.2220 +        t.push(value.substring(i -= g, i + g));
  1.2221 +        if ((length += g + 1) > width) break;
  1.2222 +        g = locale_grouping[j = (j + 1) % locale_grouping.length];
  1.2223 +      }
  1.2224 +      return t.reverse().join(locale_thousands);
  1.2225 +    } : d3_identity;
  1.2226 +    return function(specifier) {
  1.2227 +      var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
  1.2228 +      if (precision) precision = +precision.substring(1);
  1.2229 +      if (zfill || fill === "0" && align === "=") {
  1.2230 +        zfill = fill = "0";
  1.2231 +        align = "=";
  1.2232 +      }
  1.2233 +      switch (type) {
  1.2234 +       case "n":
  1.2235 +        comma = true;
  1.2236 +        type = "g";
  1.2237 +        break;
  1.2238 +
  1.2239 +       case "%":
  1.2240 +        scale = 100;
  1.2241 +        suffix = "%";
  1.2242 +        type = "f";
  1.2243 +        break;
  1.2244 +
  1.2245 +       case "p":
  1.2246 +        scale = 100;
  1.2247 +        suffix = "%";
  1.2248 +        type = "r";
  1.2249 +        break;
  1.2250 +
  1.2251 +       case "b":
  1.2252 +       case "o":
  1.2253 +       case "x":
  1.2254 +       case "X":
  1.2255 +        if (symbol === "#") prefix = "0" + type.toLowerCase();
  1.2256 +
  1.2257 +       case "c":
  1.2258 +        exponent = false;
  1.2259 +
  1.2260 +       case "d":
  1.2261 +        integer = true;
  1.2262 +        precision = 0;
  1.2263 +        break;
  1.2264 +
  1.2265 +       case "s":
  1.2266 +        scale = -1;
  1.2267 +        type = "r";
  1.2268 +        break;
  1.2269 +      }
  1.2270 +      if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
  1.2271 +      if (type == "r" && !precision) type = "g";
  1.2272 +      if (precision != null) {
  1.2273 +        if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
  1.2274 +      }
  1.2275 +      type = d3_format_types.get(type) || d3_format_typeDefault;
  1.2276 +      var zcomma = zfill && comma;
  1.2277 +      return function(value) {
  1.2278 +        var fullSuffix = suffix;
  1.2279 +        if (integer && value % 1) return "";
  1.2280 +        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
  1.2281 +        if (scale < 0) {
  1.2282 +          var unit = d3.formatPrefix(value, precision);
  1.2283 +          value = unit.scale(value);
  1.2284 +          fullSuffix = unit.symbol + suffix;
  1.2285 +        } else {
  1.2286 +          value *= scale;
  1.2287 +        }
  1.2288 +        value = type(value, precision);
  1.2289 +        var i = value.lastIndexOf("."), before, after;
  1.2290 +        if (i < 0) {
  1.2291 +          var j = exponent ? value.lastIndexOf("e") : -1;
  1.2292 +          if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
  1.2293 +        } else {
  1.2294 +          before = value.substring(0, i);
  1.2295 +          after = locale_decimal + value.substring(i + 1);
  1.2296 +        }
  1.2297 +        if (!zfill && comma) before = formatGroup(before, Infinity);
  1.2298 +        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
  1.2299 +        if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
  1.2300 +        negative += prefix;
  1.2301 +        value = before + after;
  1.2302 +        return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
  1.2303 +      };
  1.2304 +    };
  1.2305 +  }
  1.2306 +  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
  1.2307 +  var d3_format_types = d3.map({
  1.2308 +    b: function(x) {
  1.2309 +      return x.toString(2);
  1.2310 +    },
  1.2311 +    c: function(x) {
  1.2312 +      return String.fromCharCode(x);
  1.2313 +    },
  1.2314 +    o: function(x) {
  1.2315 +      return x.toString(8);
  1.2316 +    },
  1.2317 +    x: function(x) {
  1.2318 +      return x.toString(16);
  1.2319 +    },
  1.2320 +    X: function(x) {
  1.2321 +      return x.toString(16).toUpperCase();
  1.2322 +    },
  1.2323 +    g: function(x, p) {
  1.2324 +      return x.toPrecision(p);
  1.2325 +    },
  1.2326 +    e: function(x, p) {
  1.2327 +      return x.toExponential(p);
  1.2328 +    },
  1.2329 +    f: function(x, p) {
  1.2330 +      return x.toFixed(p);
  1.2331 +    },
  1.2332 +    r: function(x, p) {
  1.2333 +      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
  1.2334 +    }
  1.2335 +  });
  1.2336 +  function d3_format_typeDefault(x) {
  1.2337 +    return x + "";
  1.2338 +  }
  1.2339 +  var d3_time = d3.time = {}, d3_date = Date;
  1.2340 +  function d3_date_utc() {
  1.2341 +    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
  1.2342 +  }
  1.2343 +  d3_date_utc.prototype = {
  1.2344 +    getDate: function() {
  1.2345 +      return this._.getUTCDate();
  1.2346 +    },
  1.2347 +    getDay: function() {
  1.2348 +      return this._.getUTCDay();
  1.2349 +    },
  1.2350 +    getFullYear: function() {
  1.2351 +      return this._.getUTCFullYear();
  1.2352 +    },
  1.2353 +    getHours: function() {
  1.2354 +      return this._.getUTCHours();
  1.2355 +    },
  1.2356 +    getMilliseconds: function() {
  1.2357 +      return this._.getUTCMilliseconds();
  1.2358 +    },
  1.2359 +    getMinutes: function() {
  1.2360 +      return this._.getUTCMinutes();
  1.2361 +    },
  1.2362 +    getMonth: function() {
  1.2363 +      return this._.getUTCMonth();
  1.2364 +    },
  1.2365 +    getSeconds: function() {
  1.2366 +      return this._.getUTCSeconds();
  1.2367 +    },
  1.2368 +    getTime: function() {
  1.2369 +      return this._.getTime();
  1.2370 +    },
  1.2371 +    getTimezoneOffset: function() {
  1.2372 +      return 0;
  1.2373 +    },
  1.2374 +    valueOf: function() {
  1.2375 +      return this._.valueOf();
  1.2376 +    },
  1.2377 +    setDate: function() {
  1.2378 +      d3_time_prototype.setUTCDate.apply(this._, arguments);
  1.2379 +    },
  1.2380 +    setDay: function() {
  1.2381 +      d3_time_prototype.setUTCDay.apply(this._, arguments);
  1.2382 +    },
  1.2383 +    setFullYear: function() {
  1.2384 +      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
  1.2385 +    },
  1.2386 +    setHours: function() {
  1.2387 +      d3_time_prototype.setUTCHours.apply(this._, arguments);
  1.2388 +    },
  1.2389 +    setMilliseconds: function() {
  1.2390 +      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
  1.2391 +    },
  1.2392 +    setMinutes: function() {
  1.2393 +      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
  1.2394 +    },
  1.2395 +    setMonth: function() {
  1.2396 +      d3_time_prototype.setUTCMonth.apply(this._, arguments);
  1.2397 +    },
  1.2398 +    setSeconds: function() {
  1.2399 +      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
  1.2400 +    },
  1.2401 +    setTime: function() {
  1.2402 +      d3_time_prototype.setTime.apply(this._, arguments);
  1.2403 +    }
  1.2404 +  };
  1.2405 +  var d3_time_prototype = Date.prototype;
  1.2406 +  function d3_time_interval(local, step, number) {
  1.2407 +    function round(date) {
  1.2408 +      var d0 = local(date), d1 = offset(d0, 1);
  1.2409 +      return date - d0 < d1 - date ? d0 : d1;
  1.2410 +    }
  1.2411 +    function ceil(date) {
  1.2412 +      step(date = local(new d3_date(date - 1)), 1);
  1.2413 +      return date;
  1.2414 +    }
  1.2415 +    function offset(date, k) {
  1.2416 +      step(date = new d3_date(+date), k);
  1.2417 +      return date;
  1.2418 +    }
  1.2419 +    function range(t0, t1, dt) {
  1.2420 +      var time = ceil(t0), times = [];
  1.2421 +      if (dt > 1) {
  1.2422 +        while (time < t1) {
  1.2423 +          if (!(number(time) % dt)) times.push(new Date(+time));
  1.2424 +          step(time, 1);
  1.2425 +        }
  1.2426 +      } else {
  1.2427 +        while (time < t1) times.push(new Date(+time)), step(time, 1);
  1.2428 +      }
  1.2429 +      return times;
  1.2430 +    }
  1.2431 +    function range_utc(t0, t1, dt) {
  1.2432 +      try {
  1.2433 +        d3_date = d3_date_utc;
  1.2434 +        var utc = new d3_date_utc();
  1.2435 +        utc._ = t0;
  1.2436 +        return range(utc, t1, dt);
  1.2437 +      } finally {
  1.2438 +        d3_date = Date;
  1.2439 +      }
  1.2440 +    }
  1.2441 +    local.floor = local;
  1.2442 +    local.round = round;
  1.2443 +    local.ceil = ceil;
  1.2444 +    local.offset = offset;
  1.2445 +    local.range = range;
  1.2446 +    var utc = local.utc = d3_time_interval_utc(local);
  1.2447 +    utc.floor = utc;
  1.2448 +    utc.round = d3_time_interval_utc(round);
  1.2449 +    utc.ceil = d3_time_interval_utc(ceil);
  1.2450 +    utc.offset = d3_time_interval_utc(offset);
  1.2451 +    utc.range = range_utc;
  1.2452 +    return local;
  1.2453 +  }
  1.2454 +  function d3_time_interval_utc(method) {
  1.2455 +    return function(date, k) {
  1.2456 +      try {
  1.2457 +        d3_date = d3_date_utc;
  1.2458 +        var utc = new d3_date_utc();
  1.2459 +        utc._ = date;
  1.2460 +        return method(utc, k)._;
  1.2461 +      } finally {
  1.2462 +        d3_date = Date;
  1.2463 +      }
  1.2464 +    };
  1.2465 +  }
  1.2466 +  d3_time.year = d3_time_interval(function(date) {
  1.2467 +    date = d3_time.day(date);
  1.2468 +    date.setMonth(0, 1);
  1.2469 +    return date;
  1.2470 +  }, function(date, offset) {
  1.2471 +    date.setFullYear(date.getFullYear() + offset);
  1.2472 +  }, function(date) {
  1.2473 +    return date.getFullYear();
  1.2474 +  });
  1.2475 +  d3_time.years = d3_time.year.range;
  1.2476 +  d3_time.years.utc = d3_time.year.utc.range;
  1.2477 +  d3_time.day = d3_time_interval(function(date) {
  1.2478 +    var day = new d3_date(2e3, 0);
  1.2479 +    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
  1.2480 +    return day;
  1.2481 +  }, function(date, offset) {
  1.2482 +    date.setDate(date.getDate() + offset);
  1.2483 +  }, function(date) {
  1.2484 +    return date.getDate() - 1;
  1.2485 +  });
  1.2486 +  d3_time.days = d3_time.day.range;
  1.2487 +  d3_time.days.utc = d3_time.day.utc.range;
  1.2488 +  d3_time.dayOfYear = function(date) {
  1.2489 +    var year = d3_time.year(date);
  1.2490 +    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
  1.2491 +  };
  1.2492 +  [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
  1.2493 +    i = 7 - i;
  1.2494 +    var interval = d3_time[day] = d3_time_interval(function(date) {
  1.2495 +      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
  1.2496 +      return date;
  1.2497 +    }, function(date, offset) {
  1.2498 +      date.setDate(date.getDate() + Math.floor(offset) * 7);
  1.2499 +    }, function(date) {
  1.2500 +      var day = d3_time.year(date).getDay();
  1.2501 +      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
  1.2502 +    });
  1.2503 +    d3_time[day + "s"] = interval.range;
  1.2504 +    d3_time[day + "s"].utc = interval.utc.range;
  1.2505 +    d3_time[day + "OfYear"] = function(date) {
  1.2506 +      var day = d3_time.year(date).getDay();
  1.2507 +      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
  1.2508 +    };
  1.2509 +  });
  1.2510 +  d3_time.week = d3_time.sunday;
  1.2511 +  d3_time.weeks = d3_time.sunday.range;
  1.2512 +  d3_time.weeks.utc = d3_time.sunday.utc.range;
  1.2513 +  d3_time.weekOfYear = d3_time.sundayOfYear;
  1.2514 +  function d3_locale_timeFormat(locale) {
  1.2515 +    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
  1.2516 +    function d3_time_format(template) {
  1.2517 +      var n = template.length;
  1.2518 +      function format(date) {
  1.2519 +        var string = [], i = -1, j = 0, c, p, f;
  1.2520 +        while (++i < n) {
  1.2521 +          if (template.charCodeAt(i) === 37) {
  1.2522 +            string.push(template.slice(j, i));
  1.2523 +            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
  1.2524 +            if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
  1.2525 +            string.push(c);
  1.2526 +            j = i + 1;
  1.2527 +          }
  1.2528 +        }
  1.2529 +        string.push(template.slice(j, i));
  1.2530 +        return string.join("");
  1.2531 +      }
  1.2532 +      format.parse = function(string) {
  1.2533 +        var d = {
  1.2534 +          y: 1900,
  1.2535 +          m: 0,
  1.2536 +          d: 1,
  1.2537 +          H: 0,
  1.2538 +          M: 0,
  1.2539 +          S: 0,
  1.2540 +          L: 0,
  1.2541 +          Z: null
  1.2542 +        }, i = d3_time_parse(d, template, string, 0);
  1.2543 +        if (i != string.length) return null;
  1.2544 +        if ("p" in d) d.H = d.H % 12 + d.p * 12;
  1.2545 +        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
  1.2546 +        if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) {
  1.2547 +          if (!("w" in d)) d.w = "W" in d ? 1 : 0;
  1.2548 +          date.setFullYear(d.y, 0, 1);
  1.2549 +          date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
  1.2550 +        } else date.setFullYear(d.y, d.m, d.d);
  1.2551 +        date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
  1.2552 +        return localZ ? date._ : date;
  1.2553 +      };
  1.2554 +      format.toString = function() {
  1.2555 +        return template;
  1.2556 +      };
  1.2557 +      return format;
  1.2558 +    }
  1.2559 +    function d3_time_parse(date, template, string, j) {
  1.2560 +      var c, p, t, i = 0, n = template.length, m = string.length;
  1.2561 +      while (i < n) {
  1.2562 +        if (j >= m) return -1;
  1.2563 +        c = template.charCodeAt(i++);
  1.2564 +        if (c === 37) {
  1.2565 +          t = template.charAt(i++);
  1.2566 +          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
  1.2567 +          if (!p || (j = p(date, string, j)) < 0) return -1;
  1.2568 +        } else if (c != string.charCodeAt(j++)) {
  1.2569 +          return -1;
  1.2570 +        }
  1.2571 +      }
  1.2572 +      return j;
  1.2573 +    }
  1.2574 +    d3_time_format.utc = function(template) {
  1.2575 +      var local = d3_time_format(template);
  1.2576 +      function format(date) {
  1.2577 +        try {
  1.2578 +          d3_date = d3_date_utc;
  1.2579 +          var utc = new d3_date();
  1.2580 +          utc._ = date;
  1.2581 +          return local(utc);
  1.2582 +        } finally {
  1.2583 +          d3_date = Date;
  1.2584 +        }
  1.2585 +      }
  1.2586 +      format.parse = function(string) {
  1.2587 +        try {
  1.2588 +          d3_date = d3_date_utc;
  1.2589 +          var date = local.parse(string);
  1.2590 +          return date && date._;
  1.2591 +        } finally {
  1.2592 +          d3_date = Date;
  1.2593 +        }
  1.2594 +      };
  1.2595 +      format.toString = local.toString;
  1.2596 +      return format;
  1.2597 +    };
  1.2598 +    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
  1.2599 +    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
  1.2600 +    locale_periods.forEach(function(p, i) {
  1.2601 +      d3_time_periodLookup.set(p.toLowerCase(), i);
  1.2602 +    });
  1.2603 +    var d3_time_formats = {
  1.2604 +      a: function(d) {
  1.2605 +        return locale_shortDays[d.getDay()];
  1.2606 +      },
  1.2607 +      A: function(d) {
  1.2608 +        return locale_days[d.getDay()];
  1.2609 +      },
  1.2610 +      b: function(d) {
  1.2611 +        return locale_shortMonths[d.getMonth()];
  1.2612 +      },
  1.2613 +      B: function(d) {
  1.2614 +        return locale_months[d.getMonth()];
  1.2615 +      },
  1.2616 +      c: d3_time_format(locale_dateTime),
  1.2617 +      d: function(d, p) {
  1.2618 +        return d3_time_formatPad(d.getDate(), p, 2);
  1.2619 +      },
  1.2620 +      e: function(d, p) {
  1.2621 +        return d3_time_formatPad(d.getDate(), p, 2);
  1.2622 +      },
  1.2623 +      H: function(d, p) {
  1.2624 +        return d3_time_formatPad(d.getHours(), p, 2);
  1.2625 +      },
  1.2626 +      I: function(d, p) {
  1.2627 +        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
  1.2628 +      },
  1.2629 +      j: function(d, p) {
  1.2630 +        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
  1.2631 +      },
  1.2632 +      L: function(d, p) {
  1.2633 +        return d3_time_formatPad(d.getMilliseconds(), p, 3);
  1.2634 +      },
  1.2635 +      m: function(d, p) {
  1.2636 +        return d3_time_formatPad(d.getMonth() + 1, p, 2);
  1.2637 +      },
  1.2638 +      M: function(d, p) {
  1.2639 +        return d3_time_formatPad(d.getMinutes(), p, 2);
  1.2640 +      },
  1.2641 +      p: function(d) {
  1.2642 +        return locale_periods[+(d.getHours() >= 12)];
  1.2643 +      },
  1.2644 +      S: function(d, p) {
  1.2645 +        return d3_time_formatPad(d.getSeconds(), p, 2);
  1.2646 +      },
  1.2647 +      U: function(d, p) {
  1.2648 +        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
  1.2649 +      },
  1.2650 +      w: function(d) {
  1.2651 +        return d.getDay();
  1.2652 +      },
  1.2653 +      W: function(d, p) {
  1.2654 +        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
  1.2655 +      },
  1.2656 +      x: d3_time_format(locale_date),
  1.2657 +      X: d3_time_format(locale_time),
  1.2658 +      y: function(d, p) {
  1.2659 +        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
  1.2660 +      },
  1.2661 +      Y: function(d, p) {
  1.2662 +        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
  1.2663 +      },
  1.2664 +      Z: d3_time_zone,
  1.2665 +      "%": function() {
  1.2666 +        return "%";
  1.2667 +      }
  1.2668 +    };
  1.2669 +    var d3_time_parsers = {
  1.2670 +      a: d3_time_parseWeekdayAbbrev,
  1.2671 +      A: d3_time_parseWeekday,
  1.2672 +      b: d3_time_parseMonthAbbrev,
  1.2673 +      B: d3_time_parseMonth,
  1.2674 +      c: d3_time_parseLocaleFull,
  1.2675 +      d: d3_time_parseDay,
  1.2676 +      e: d3_time_parseDay,
  1.2677 +      H: d3_time_parseHour24,
  1.2678 +      I: d3_time_parseHour24,
  1.2679 +      j: d3_time_parseDayOfYear,
  1.2680 +      L: d3_time_parseMilliseconds,
  1.2681 +      m: d3_time_parseMonthNumber,
  1.2682 +      M: d3_time_parseMinutes,
  1.2683 +      p: d3_time_parseAmPm,
  1.2684 +      S: d3_time_parseSeconds,
  1.2685 +      U: d3_time_parseWeekNumberSunday,
  1.2686 +      w: d3_time_parseWeekdayNumber,
  1.2687 +      W: d3_time_parseWeekNumberMonday,
  1.2688 +      x: d3_time_parseLocaleDate,
  1.2689 +      X: d3_time_parseLocaleTime,
  1.2690 +      y: d3_time_parseYear,
  1.2691 +      Y: d3_time_parseFullYear,
  1.2692 +      Z: d3_time_parseZone,
  1.2693 +      "%": d3_time_parseLiteralPercent
  1.2694 +    };
  1.2695 +    function d3_time_parseWeekdayAbbrev(date, string, i) {
  1.2696 +      d3_time_dayAbbrevRe.lastIndex = 0;
  1.2697 +      var n = d3_time_dayAbbrevRe.exec(string.slice(i));
  1.2698 +      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  1.2699 +    }
  1.2700 +    function d3_time_parseWeekday(date, string, i) {
  1.2701 +      d3_time_dayRe.lastIndex = 0;
  1.2702 +      var n = d3_time_dayRe.exec(string.slice(i));
  1.2703 +      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  1.2704 +    }
  1.2705 +    function d3_time_parseMonthAbbrev(date, string, i) {
  1.2706 +      d3_time_monthAbbrevRe.lastIndex = 0;
  1.2707 +      var n = d3_time_monthAbbrevRe.exec(string.slice(i));
  1.2708 +      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  1.2709 +    }
  1.2710 +    function d3_time_parseMonth(date, string, i) {
  1.2711 +      d3_time_monthRe.lastIndex = 0;
  1.2712 +      var n = d3_time_monthRe.exec(string.slice(i));
  1.2713 +      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  1.2714 +    }
  1.2715 +    function d3_time_parseLocaleFull(date, string, i) {
  1.2716 +      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
  1.2717 +    }
  1.2718 +    function d3_time_parseLocaleDate(date, string, i) {
  1.2719 +      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
  1.2720 +    }
  1.2721 +    function d3_time_parseLocaleTime(date, string, i) {
  1.2722 +      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
  1.2723 +    }
  1.2724 +    function d3_time_parseAmPm(date, string, i) {
  1.2725 +      var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
  1.2726 +      return n == null ? -1 : (date.p = n, i);
  1.2727 +    }
  1.2728 +    return d3_time_format;
  1.2729 +  }
  1.2730 +  var d3_time_formatPads = {
  1.2731 +    "-": "",
  1.2732 +    _: " ",
  1.2733 +    "0": "0"
  1.2734 +  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
  1.2735 +  function d3_time_formatPad(value, fill, width) {
  1.2736 +    var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
  1.2737 +    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
  1.2738 +  }
  1.2739 +  function d3_time_formatRe(names) {
  1.2740 +    return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
  1.2741 +  }
  1.2742 +  function d3_time_formatLookup(names) {
  1.2743 +    var map = new d3_Map(), i = -1, n = names.length;
  1.2744 +    while (++i < n) map.set(names[i].toLowerCase(), i);
  1.2745 +    return map;
  1.2746 +  }
  1.2747 +  function d3_time_parseWeekdayNumber(date, string, i) {
  1.2748 +    d3_time_numberRe.lastIndex = 0;
  1.2749 +    var n = d3_time_numberRe.exec(string.slice(i, i + 1));
  1.2750 +    return n ? (date.w = +n[0], i + n[0].length) : -1;
  1.2751 +  }
  1.2752 +  function d3_time_parseWeekNumberSunday(date, string, i) {
  1.2753 +    d3_time_numberRe.lastIndex = 0;
  1.2754 +    var n = d3_time_numberRe.exec(string.slice(i));
  1.2755 +    return n ? (date.U = +n[0], i + n[0].length) : -1;
  1.2756 +  }
  1.2757 +  function d3_time_parseWeekNumberMonday(date, string, i) {
  1.2758 +    d3_time_numberRe.lastIndex = 0;
  1.2759 +    var n = d3_time_numberRe.exec(string.slice(i));
  1.2760 +    return n ? (date.W = +n[0], i + n[0].length) : -1;
  1.2761 +  }
  1.2762 +  function d3_time_parseFullYear(date, string, i) {
  1.2763 +    d3_time_numberRe.lastIndex = 0;
  1.2764 +    var n = d3_time_numberRe.exec(string.slice(i, i + 4));
  1.2765 +    return n ? (date.y = +n[0], i + n[0].length) : -1;
  1.2766 +  }
  1.2767 +  function d3_time_parseYear(date, string, i) {
  1.2768 +    d3_time_numberRe.lastIndex = 0;
  1.2769 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2770 +    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
  1.2771 +  }
  1.2772 +  function d3_time_parseZone(date, string, i) {
  1.2773 +    return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, 
  1.2774 +    i + 5) : -1;
  1.2775 +  }
  1.2776 +  function d3_time_expandYear(d) {
  1.2777 +    return d + (d > 68 ? 1900 : 2e3);
  1.2778 +  }
  1.2779 +  function d3_time_parseMonthNumber(date, string, i) {
  1.2780 +    d3_time_numberRe.lastIndex = 0;
  1.2781 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2782 +    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
  1.2783 +  }
  1.2784 +  function d3_time_parseDay(date, string, i) {
  1.2785 +    d3_time_numberRe.lastIndex = 0;
  1.2786 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2787 +    return n ? (date.d = +n[0], i + n[0].length) : -1;
  1.2788 +  }
  1.2789 +  function d3_time_parseDayOfYear(date, string, i) {
  1.2790 +    d3_time_numberRe.lastIndex = 0;
  1.2791 +    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
  1.2792 +    return n ? (date.j = +n[0], i + n[0].length) : -1;
  1.2793 +  }
  1.2794 +  function d3_time_parseHour24(date, string, i) {
  1.2795 +    d3_time_numberRe.lastIndex = 0;
  1.2796 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2797 +    return n ? (date.H = +n[0], i + n[0].length) : -1;
  1.2798 +  }
  1.2799 +  function d3_time_parseMinutes(date, string, i) {
  1.2800 +    d3_time_numberRe.lastIndex = 0;
  1.2801 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2802 +    return n ? (date.M = +n[0], i + n[0].length) : -1;
  1.2803 +  }
  1.2804 +  function d3_time_parseSeconds(date, string, i) {
  1.2805 +    d3_time_numberRe.lastIndex = 0;
  1.2806 +    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
  1.2807 +    return n ? (date.S = +n[0], i + n[0].length) : -1;
  1.2808 +  }
  1.2809 +  function d3_time_parseMilliseconds(date, string, i) {
  1.2810 +    d3_time_numberRe.lastIndex = 0;
  1.2811 +    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
  1.2812 +    return n ? (date.L = +n[0], i + n[0].length) : -1;
  1.2813 +  }
  1.2814 +  function d3_time_zone(d) {
  1.2815 +    var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
  1.2816 +    return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
  1.2817 +  }
  1.2818 +  function d3_time_parseLiteralPercent(date, string, i) {
  1.2819 +    d3_time_percentRe.lastIndex = 0;
  1.2820 +    var n = d3_time_percentRe.exec(string.slice(i, i + 1));
  1.2821 +    return n ? i + n[0].length : -1;
  1.2822 +  }
  1.2823 +  function d3_time_formatMulti(formats) {
  1.2824 +    var n = formats.length, i = -1;
  1.2825 +    while (++i < n) formats[i][0] = this(formats[i][0]);
  1.2826 +    return function(date) {
  1.2827 +      var i = 0, f = formats[i];
  1.2828 +      while (!f[1](date)) f = formats[++i];
  1.2829 +      return f[0](date);
  1.2830 +    };
  1.2831 +  }
  1.2832 +  d3.locale = function(locale) {
  1.2833 +    return {
  1.2834 +      numberFormat: d3_locale_numberFormat(locale),
  1.2835 +      timeFormat: d3_locale_timeFormat(locale)
  1.2836 +    };
  1.2837 +  };
  1.2838 +  var d3_locale_enUS = d3.locale({
  1.2839 +    decimal: ".",
  1.2840 +    thousands: ",",
  1.2841 +    grouping: [ 3 ],
  1.2842 +    currency: [ "$", "" ],
  1.2843 +    dateTime: "%a %b %e %X %Y",
  1.2844 +    date: "%m/%d/%Y",
  1.2845 +    time: "%H:%M:%S",
  1.2846 +    periods: [ "AM", "PM" ],
  1.2847 +    days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
  1.2848 +    shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
  1.2849 +    months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
  1.2850 +    shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
  1.2851 +  });
  1.2852 +  d3.format = d3_locale_enUS.numberFormat;
  1.2853 +  d3.geo = {};
  1.2854 +  function d3_adder() {}
  1.2855 +  d3_adder.prototype = {
  1.2856 +    s: 0,
  1.2857 +    t: 0,
  1.2858 +    add: function(y) {
  1.2859 +      d3_adderSum(y, this.t, d3_adderTemp);
  1.2860 +      d3_adderSum(d3_adderTemp.s, this.s, this);
  1.2861 +      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
  1.2862 +    },
  1.2863 +    reset: function() {
  1.2864 +      this.s = this.t = 0;
  1.2865 +    },
  1.2866 +    valueOf: function() {
  1.2867 +      return this.s;
  1.2868 +    }
  1.2869 +  };
  1.2870 +  var d3_adderTemp = new d3_adder();
  1.2871 +  function d3_adderSum(a, b, o) {
  1.2872 +    var x = o.s = a + b, bv = x - a, av = x - bv;
  1.2873 +    o.t = a - av + (b - bv);
  1.2874 +  }
  1.2875 +  d3.geo.stream = function(object, listener) {
  1.2876 +    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
  1.2877 +      d3_geo_streamObjectType[object.type](object, listener);
  1.2878 +    } else {
  1.2879 +      d3_geo_streamGeometry(object, listener);
  1.2880 +    }
  1.2881 +  };
  1.2882 +  function d3_geo_streamGeometry(geometry, listener) {
  1.2883 +    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
  1.2884 +      d3_geo_streamGeometryType[geometry.type](geometry, listener);
  1.2885 +    }
  1.2886 +  }
  1.2887 +  var d3_geo_streamObjectType = {
  1.2888 +    Feature: function(feature, listener) {
  1.2889 +      d3_geo_streamGeometry(feature.geometry, listener);
  1.2890 +    },
  1.2891 +    FeatureCollection: function(object, listener) {
  1.2892 +      var features = object.features, i = -1, n = features.length;
  1.2893 +      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
  1.2894 +    }
  1.2895 +  };
  1.2896 +  var d3_geo_streamGeometryType = {
  1.2897 +    Sphere: function(object, listener) {
  1.2898 +      listener.sphere();
  1.2899 +    },
  1.2900 +    Point: function(object, listener) {
  1.2901 +      object = object.coordinates;
  1.2902 +      listener.point(object[0], object[1], object[2]);
  1.2903 +    },
  1.2904 +    MultiPoint: function(object, listener) {
  1.2905 +      var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1.2906 +      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
  1.2907 +    },
  1.2908 +    LineString: function(object, listener) {
  1.2909 +      d3_geo_streamLine(object.coordinates, listener, 0);
  1.2910 +    },
  1.2911 +    MultiLineString: function(object, listener) {
  1.2912 +      var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1.2913 +      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
  1.2914 +    },
  1.2915 +    Polygon: function(object, listener) {
  1.2916 +      d3_geo_streamPolygon(object.coordinates, listener);
  1.2917 +    },
  1.2918 +    MultiPolygon: function(object, listener) {
  1.2919 +      var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1.2920 +      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
  1.2921 +    },
  1.2922 +    GeometryCollection: function(object, listener) {
  1.2923 +      var geometries = object.geometries, i = -1, n = geometries.length;
  1.2924 +      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
  1.2925 +    }
  1.2926 +  };
  1.2927 +  function d3_geo_streamLine(coordinates, listener, closed) {
  1.2928 +    var i = -1, n = coordinates.length - closed, coordinate;
  1.2929 +    listener.lineStart();
  1.2930 +    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
  1.2931 +    listener.lineEnd();
  1.2932 +  }
  1.2933 +  function d3_geo_streamPolygon(coordinates, listener) {
  1.2934 +    var i = -1, n = coordinates.length;
  1.2935 +    listener.polygonStart();
  1.2936 +    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
  1.2937 +    listener.polygonEnd();
  1.2938 +  }
  1.2939 +  d3.geo.area = function(object) {
  1.2940 +    d3_geo_areaSum = 0;
  1.2941 +    d3.geo.stream(object, d3_geo_area);
  1.2942 +    return d3_geo_areaSum;
  1.2943 +  };
  1.2944 +  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
  1.2945 +  var d3_geo_area = {
  1.2946 +    sphere: function() {
  1.2947 +      d3_geo_areaSum += 4 * π;
  1.2948 +    },
  1.2949 +    point: d3_noop,
  1.2950 +    lineStart: d3_noop,
  1.2951 +    lineEnd: d3_noop,
  1.2952 +    polygonStart: function() {
  1.2953 +      d3_geo_areaRingSum.reset();
  1.2954 +      d3_geo_area.lineStart = d3_geo_areaRingStart;
  1.2955 +    },
  1.2956 +    polygonEnd: function() {
  1.2957 +      var area = 2 * d3_geo_areaRingSum;
  1.2958 +      d3_geo_areaSum += area < 0 ? 4 * π + area : area;
  1.2959 +      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
  1.2960 +    }
  1.2961 +  };
  1.2962 +  function d3_geo_areaRingStart() {
  1.2963 +    var λ00, φ00, λ0, cosφ0, sinφ0;
  1.2964 +    d3_geo_area.point = function(λ, φ) {
  1.2965 +      d3_geo_area.point = nextPoint;
  1.2966 +      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
  1.2967 +      sinφ0 = Math.sin(φ);
  1.2968 +    };
  1.2969 +    function nextPoint(λ, φ) {
  1.2970 +      λ *= d3_radians;
  1.2971 +      φ = φ * d3_radians / 2 + π / 4;
  1.2972 +      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
  1.2973 +      d3_geo_areaRingSum.add(Math.atan2(v, u));
  1.2974 +      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
  1.2975 +    }
  1.2976 +    d3_geo_area.lineEnd = function() {
  1.2977 +      nextPoint(λ00, φ00);
  1.2978 +    };
  1.2979 +  }
  1.2980 +  function d3_geo_cartesian(spherical) {
  1.2981 +    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
  1.2982 +    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
  1.2983 +  }
  1.2984 +  function d3_geo_cartesianDot(a, b) {
  1.2985 +    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  1.2986 +  }
  1.2987 +  function d3_geo_cartesianCross(a, b) {
  1.2988 +    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
  1.2989 +  }
  1.2990 +  function d3_geo_cartesianAdd(a, b) {
  1.2991 +    a[0] += b[0];
  1.2992 +    a[1] += b[1];
  1.2993 +    a[2] += b[2];
  1.2994 +  }
  1.2995 +  function d3_geo_cartesianScale(vector, k) {
  1.2996 +    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
  1.2997 +  }
  1.2998 +  function d3_geo_cartesianNormalize(d) {
  1.2999 +    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
  1.3000 +    d[0] /= l;
  1.3001 +    d[1] /= l;
  1.3002 +    d[2] /= l;
  1.3003 +  }
  1.3004 +  function d3_geo_spherical(cartesian) {
  1.3005 +    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
  1.3006 +  }
  1.3007 +  function d3_geo_sphericalEqual(a, b) {
  1.3008 +    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
  1.3009 +  }
  1.3010 +  d3.geo.bounds = function() {
  1.3011 +    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
  1.3012 +    var bound = {
  1.3013 +      point: point,
  1.3014 +      lineStart: lineStart,
  1.3015 +      lineEnd: lineEnd,
  1.3016 +      polygonStart: function() {
  1.3017 +        bound.point = ringPoint;
  1.3018 +        bound.lineStart = ringStart;
  1.3019 +        bound.lineEnd = ringEnd;
  1.3020 +        dλSum = 0;
  1.3021 +        d3_geo_area.polygonStart();
  1.3022 +      },
  1.3023 +      polygonEnd: function() {
  1.3024 +        d3_geo_area.polygonEnd();
  1.3025 +        bound.point = point;
  1.3026 +        bound.lineStart = lineStart;
  1.3027 +        bound.lineEnd = lineEnd;
  1.3028 +        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
  1.3029 +        range[0] = λ0, range[1] = λ1;
  1.3030 +      }
  1.3031 +    };
  1.3032 +    function point(λ, φ) {
  1.3033 +      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
  1.3034 +      if (φ < φ0) φ0 = φ;
  1.3035 +      if (φ > φ1) φ1 = φ;
  1.3036 +    }
  1.3037 +    function linePoint(λ, φ) {
  1.3038 +      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
  1.3039 +      if (p0) {
  1.3040 +        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
  1.3041 +        d3_geo_cartesianNormalize(inflection);
  1.3042 +        inflection = d3_geo_spherical(inflection);
  1.3043 +        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
  1.3044 +        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
  1.3045 +          var φi = inflection[1] * d3_degrees;
  1.3046 +          if (φi > φ1) φ1 = φi;
  1.3047 +        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
  1.3048 +          var φi = -inflection[1] * d3_degrees;
  1.3049 +          if (φi < φ0) φ0 = φi;
  1.3050 +        } else {
  1.3051 +          if (φ < φ0) φ0 = φ;
  1.3052 +          if (φ > φ1) φ1 = φ;
  1.3053 +        }
  1.3054 +        if (antimeridian) {
  1.3055 +          if (λ < λ_) {
  1.3056 +            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
  1.3057 +          } else {
  1.3058 +            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
  1.3059 +          }
  1.3060 +        } else {
  1.3061 +          if (λ1 >= λ0) {
  1.3062 +            if (λ < λ0) λ0 = λ;
  1.3063 +            if (λ > λ1) λ1 = λ;
  1.3064 +          } else {
  1.3065 +            if (λ > λ_) {
  1.3066 +              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
  1.3067 +            } else {
  1.3068 +              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
  1.3069 +            }
  1.3070 +          }
  1.3071 +        }
  1.3072 +      } else {
  1.3073 +        point(λ, φ);
  1.3074 +      }
  1.3075 +      p0 = p, λ_ = λ;
  1.3076 +    }
  1.3077 +    function lineStart() {
  1.3078 +      bound.point = linePoint;
  1.3079 +    }
  1.3080 +    function lineEnd() {
  1.3081 +      range[0] = λ0, range[1] = λ1;
  1.3082 +      bound.point = point;
  1.3083 +      p0 = null;
  1.3084 +    }
  1.3085 +    function ringPoint(λ, φ) {
  1.3086 +      if (p0) {
  1.3087 +        var dλ = λ - λ_;
  1.3088 +        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
  1.3089 +      } else λ__ = λ, φ__ = φ;
  1.3090 +      d3_geo_area.point(λ, φ);
  1.3091 +      linePoint(λ, φ);
  1.3092 +    }
  1.3093 +    function ringStart() {
  1.3094 +      d3_geo_area.lineStart();
  1.3095 +    }
  1.3096 +    function ringEnd() {
  1.3097 +      ringPoint(λ__, φ__);
  1.3098 +      d3_geo_area.lineEnd();
  1.3099 +      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
  1.3100 +      range[0] = λ0, range[1] = λ1;
  1.3101 +      p0 = null;
  1.3102 +    }
  1.3103 +    function angle(λ0, λ1) {
  1.3104 +      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
  1.3105 +    }
  1.3106 +    function compareRanges(a, b) {
  1.3107 +      return a[0] - b[0];
  1.3108 +    }
  1.3109 +    function withinRange(x, range) {
  1.3110 +      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
  1.3111 +    }
  1.3112 +    return function(feature) {
  1.3113 +      φ1 = λ1 = -(λ0 = φ0 = Infinity);
  1.3114 +      ranges = [];
  1.3115 +      d3.geo.stream(feature, bound);
  1.3116 +      var n = ranges.length;
  1.3117 +      if (n) {
  1.3118 +        ranges.sort(compareRanges);
  1.3119 +        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
  1.3120 +          b = ranges[i];
  1.3121 +          if (withinRange(b[0], a) || withinRange(b[1], a)) {
  1.3122 +            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
  1.3123 +            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
  1.3124 +          } else {
  1.3125 +            merged.push(a = b);
  1.3126 +          }
  1.3127 +        }
  1.3128 +        var best = -Infinity, dλ;
  1.3129 +        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
  1.3130 +          b = merged[i];
  1.3131 +          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
  1.3132 +        }
  1.3133 +      }
  1.3134 +      ranges = range = null;
  1.3135 +      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
  1.3136 +    };
  1.3137 +  }();
  1.3138 +  d3.geo.centroid = function(object) {
  1.3139 +    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
  1.3140 +    d3.geo.stream(object, d3_geo_centroid);
  1.3141 +    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
  1.3142 +    if (m < ε2) {
  1.3143 +      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
  1.3144 +      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
  1.3145 +      m = x * x + y * y + z * z;
  1.3146 +      if (m < ε2) return [ NaN, NaN ];
  1.3147 +    }
  1.3148 +    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
  1.3149 +  };
  1.3150 +  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
  1.3151 +  var d3_geo_centroid = {
  1.3152 +    sphere: d3_noop,
  1.3153 +    point: d3_geo_centroidPoint,
  1.3154 +    lineStart: d3_geo_centroidLineStart,
  1.3155 +    lineEnd: d3_geo_centroidLineEnd,
  1.3156 +    polygonStart: function() {
  1.3157 +      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
  1.3158 +    },
  1.3159 +    polygonEnd: function() {
  1.3160 +      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
  1.3161 +    }
  1.3162 +  };
  1.3163 +  function d3_geo_centroidPoint(λ, φ) {
  1.3164 +    λ *= d3_radians;
  1.3165 +    var cosφ = Math.cos(φ *= d3_radians);
  1.3166 +    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
  1.3167 +  }
  1.3168 +  function d3_geo_centroidPointXYZ(x, y, z) {
  1.3169 +    ++d3_geo_centroidW0;
  1.3170 +    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
  1.3171 +    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
  1.3172 +    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
  1.3173 +  }
  1.3174 +  function d3_geo_centroidLineStart() {
  1.3175 +    var x0, y0, z0;
  1.3176 +    d3_geo_centroid.point = function(λ, φ) {
  1.3177 +      λ *= d3_radians;
  1.3178 +      var cosφ = Math.cos(φ *= d3_radians);
  1.3179 +      x0 = cosφ * Math.cos(λ);
  1.3180 +      y0 = cosφ * Math.sin(λ);
  1.3181 +      z0 = Math.sin(φ);
  1.3182 +      d3_geo_centroid.point = nextPoint;
  1.3183 +      d3_geo_centroidPointXYZ(x0, y0, z0);
  1.3184 +    };
  1.3185 +    function nextPoint(λ, φ) {
  1.3186 +      λ *= d3_radians;
  1.3187 +      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
  1.3188 +      d3_geo_centroidW1 += w;
  1.3189 +      d3_geo_centroidX1 += w * (x0 + (x0 = x));
  1.3190 +      d3_geo_centroidY1 += w * (y0 + (y0 = y));
  1.3191 +      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
  1.3192 +      d3_geo_centroidPointXYZ(x0, y0, z0);
  1.3193 +    }
  1.3194 +  }
  1.3195 +  function d3_geo_centroidLineEnd() {
  1.3196 +    d3_geo_centroid.point = d3_geo_centroidPoint;
  1.3197 +  }
  1.3198 +  function d3_geo_centroidRingStart() {
  1.3199 +    var λ00, φ00, x0, y0, z0;
  1.3200 +    d3_geo_centroid.point = function(λ, φ) {
  1.3201 +      λ00 = λ, φ00 = φ;
  1.3202 +      d3_geo_centroid.point = nextPoint;
  1.3203 +      λ *= d3_radians;
  1.3204 +      var cosφ = Math.cos(φ *= d3_radians);
  1.3205 +      x0 = cosφ * Math.cos(λ);
  1.3206 +      y0 = cosφ * Math.sin(λ);
  1.3207 +      z0 = Math.sin(φ);
  1.3208 +      d3_geo_centroidPointXYZ(x0, y0, z0);
  1.3209 +    };
  1.3210 +    d3_geo_centroid.lineEnd = function() {
  1.3211 +      nextPoint(λ00, φ00);
  1.3212 +      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
  1.3213 +      d3_geo_centroid.point = d3_geo_centroidPoint;
  1.3214 +    };
  1.3215 +    function nextPoint(λ, φ) {
  1.3216 +      λ *= d3_radians;
  1.3217 +      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
  1.3218 +      d3_geo_centroidX2 += v * cx;
  1.3219 +      d3_geo_centroidY2 += v * cy;
  1.3220 +      d3_geo_centroidZ2 += v * cz;
  1.3221 +      d3_geo_centroidW1 += w;
  1.3222 +      d3_geo_centroidX1 += w * (x0 + (x0 = x));
  1.3223 +      d3_geo_centroidY1 += w * (y0 + (y0 = y));
  1.3224 +      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
  1.3225 +      d3_geo_centroidPointXYZ(x0, y0, z0);
  1.3226 +    }
  1.3227 +  }
  1.3228 +  function d3_geo_compose(a, b) {
  1.3229 +    function compose(x, y) {
  1.3230 +      return x = a(x, y), b(x[0], x[1]);
  1.3231 +    }
  1.3232 +    if (a.invert && b.invert) compose.invert = function(x, y) {
  1.3233 +      return x = b.invert(x, y), x && a.invert(x[0], x[1]);
  1.3234 +    };
  1.3235 +    return compose;
  1.3236 +  }
  1.3237 +  function d3_true() {
  1.3238 +    return true;
  1.3239 +  }
  1.3240 +  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
  1.3241 +    var subject = [], clip = [];
  1.3242 +    segments.forEach(function(segment) {
  1.3243 +      if ((n = segment.length - 1) <= 0) return;
  1.3244 +      var n, p0 = segment[0], p1 = segment[n];
  1.3245 +      if (d3_geo_sphericalEqual(p0, p1)) {
  1.3246 +        listener.lineStart();
  1.3247 +        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
  1.3248 +        listener.lineEnd();
  1.3249 +        return;
  1.3250 +      }
  1.3251 +      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
  1.3252 +      a.o = b;
  1.3253 +      subject.push(a);
  1.3254 +      clip.push(b);
  1.3255 +      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
  1.3256 +      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
  1.3257 +      a.o = b;
  1.3258 +      subject.push(a);
  1.3259 +      clip.push(b);
  1.3260 +    });
  1.3261 +    clip.sort(compare);
  1.3262 +    d3_geo_clipPolygonLinkCircular(subject);
  1.3263 +    d3_geo_clipPolygonLinkCircular(clip);
  1.3264 +    if (!subject.length) return;
  1.3265 +    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
  1.3266 +      clip[i].e = entry = !entry;
  1.3267 +    }
  1.3268 +    var start = subject[0], points, point;
  1.3269 +    while (1) {
  1.3270 +      var current = start, isSubject = true;
  1.3271 +      while (current.v) if ((current = current.n) === start) return;
  1.3272 +      points = current.z;
  1.3273 +      listener.lineStart();
  1.3274 +      do {
  1.3275 +        current.v = current.o.v = true;
  1.3276 +        if (current.e) {
  1.3277 +          if (isSubject) {
  1.3278 +            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
  1.3279 +          } else {
  1.3280 +            interpolate(current.x, current.n.x, 1, listener);
  1.3281 +          }
  1.3282 +          current = current.n;
  1.3283 +        } else {
  1.3284 +          if (isSubject) {
  1.3285 +            points = current.p.z;
  1.3286 +            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
  1.3287 +          } else {
  1.3288 +            interpolate(current.x, current.p.x, -1, listener);
  1.3289 +          }
  1.3290 +          current = current.p;
  1.3291 +        }
  1.3292 +        current = current.o;
  1.3293 +        points = current.z;
  1.3294 +        isSubject = !isSubject;
  1.3295 +      } while (!current.v);
  1.3296 +      listener.lineEnd();
  1.3297 +    }
  1.3298 +  }
  1.3299 +  function d3_geo_clipPolygonLinkCircular(array) {
  1.3300 +    if (!(n = array.length)) return;
  1.3301 +    var n, i = 0, a = array[0], b;
  1.3302 +    while (++i < n) {
  1.3303 +      a.n = b = array[i];
  1.3304 +      b.p = a;
  1.3305 +      a = b;
  1.3306 +    }
  1.3307 +    a.n = b = array[0];
  1.3308 +    b.p = a;
  1.3309 +  }
  1.3310 +  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
  1.3311 +    this.x = point;
  1.3312 +    this.z = points;
  1.3313 +    this.o = other;
  1.3314 +    this.e = entry;
  1.3315 +    this.v = false;
  1.3316 +    this.n = this.p = null;
  1.3317 +  }
  1.3318 +  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
  1.3319 +    return function(rotate, listener) {
  1.3320 +      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
  1.3321 +      var clip = {
  1.3322 +        point: point,
  1.3323 +        lineStart: lineStart,
  1.3324 +        lineEnd: lineEnd,
  1.3325 +        polygonStart: function() {
  1.3326 +          clip.point = pointRing;
  1.3327 +          clip.lineStart = ringStart;
  1.3328 +          clip.lineEnd = ringEnd;
  1.3329 +          segments = [];
  1.3330 +          polygon = [];
  1.3331 +        },
  1.3332 +        polygonEnd: function() {
  1.3333 +          clip.point = point;
  1.3334 +          clip.lineStart = lineStart;
  1.3335 +          clip.lineEnd = lineEnd;
  1.3336 +          segments = d3.merge(segments);
  1.3337 +          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
  1.3338 +          if (segments.length) {
  1.3339 +            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
  1.3340 +            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
  1.3341 +          } else if (clipStartInside) {
  1.3342 +            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
  1.3343 +            listener.lineStart();
  1.3344 +            interpolate(null, null, 1, listener);
  1.3345 +            listener.lineEnd();
  1.3346 +          }
  1.3347 +          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
  1.3348 +          segments = polygon = null;
  1.3349 +        },
  1.3350 +        sphere: function() {
  1.3351 +          listener.polygonStart();
  1.3352 +          listener.lineStart();
  1.3353 +          interpolate(null, null, 1, listener);
  1.3354 +          listener.lineEnd();
  1.3355 +          listener.polygonEnd();
  1.3356 +        }
  1.3357 +      };
  1.3358 +      function point(λ, φ) {
  1.3359 +        var point = rotate(λ, φ);
  1.3360 +        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
  1.3361 +      }
  1.3362 +      function pointLine(λ, φ) {
  1.3363 +        var point = rotate(λ, φ);
  1.3364 +        line.point(point[0], point[1]);
  1.3365 +      }
  1.3366 +      function lineStart() {
  1.3367 +        clip.point = pointLine;
  1.3368 +        line.lineStart();
  1.3369 +      }
  1.3370 +      function lineEnd() {
  1.3371 +        clip.point = point;
  1.3372 +        line.lineEnd();
  1.3373 +      }
  1.3374 +      var segments;
  1.3375 +      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
  1.3376 +      function pointRing(λ, φ) {
  1.3377 +        ring.push([ λ, φ ]);
  1.3378 +        var point = rotate(λ, φ);
  1.3379 +        ringListener.point(point[0], point[1]);
  1.3380 +      }
  1.3381 +      function ringStart() {
  1.3382 +        ringListener.lineStart();
  1.3383 +        ring = [];
  1.3384 +      }
  1.3385 +      function ringEnd() {
  1.3386 +        pointRing(ring[0][0], ring[0][1]);
  1.3387 +        ringListener.lineEnd();
  1.3388 +        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
  1.3389 +        ring.pop();
  1.3390 +        polygon.push(ring);
  1.3391 +        ring = null;
  1.3392 +        if (!n) return;
  1.3393 +        if (clean & 1) {
  1.3394 +          segment = ringSegments[0];
  1.3395 +          var n = segment.length - 1, i = -1, point;
  1.3396 +          if (n > 0) {
  1.3397 +            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
  1.3398 +            listener.lineStart();
  1.3399 +            while (++i < n) listener.point((point = segment[i])[0], point[1]);
  1.3400 +            listener.lineEnd();
  1.3401 +          }
  1.3402 +          return;
  1.3403 +        }
  1.3404 +        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
  1.3405 +        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
  1.3406 +      }
  1.3407 +      return clip;
  1.3408 +    };
  1.3409 +  }
  1.3410 +  function d3_geo_clipSegmentLength1(segment) {
  1.3411 +    return segment.length > 1;
  1.3412 +  }
  1.3413 +  function d3_geo_clipBufferListener() {
  1.3414 +    var lines = [], line;
  1.3415 +    return {
  1.3416 +      lineStart: function() {
  1.3417 +        lines.push(line = []);
  1.3418 +      },
  1.3419 +      point: function(λ, φ) {
  1.3420 +        line.push([ λ, φ ]);
  1.3421 +      },
  1.3422 +      lineEnd: d3_noop,
  1.3423 +      buffer: function() {
  1.3424 +        var buffer = lines;
  1.3425 +        lines = [];
  1.3426 +        line = null;
  1.3427 +        return buffer;
  1.3428 +      },
  1.3429 +      rejoin: function() {
  1.3430 +        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
  1.3431 +      }
  1.3432 +    };
  1.3433 +  }
  1.3434 +  function d3_geo_clipSort(a, b) {
  1.3435 +    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
  1.3436 +  }
  1.3437 +  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
  1.3438 +  function d3_geo_clipAntimeridianLine(listener) {
  1.3439 +    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
  1.3440 +    return {
  1.3441 +      lineStart: function() {
  1.3442 +        listener.lineStart();
  1.3443 +        clean = 1;
  1.3444 +      },
  1.3445 +      point: function(λ1, φ1) {
  1.3446 +        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
  1.3447 +        if (abs(dλ - π) < ε) {
  1.3448 +          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
  1.3449 +          listener.point(sλ0, φ0);
  1.3450 +          listener.lineEnd();
  1.3451 +          listener.lineStart();
  1.3452 +          listener.point(sλ1, φ0);
  1.3453 +          listener.point(λ1, φ0);
  1.3454 +          clean = 0;
  1.3455 +        } else if (sλ0 !== sλ1 && dλ >= π) {
  1.3456 +          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
  1.3457 +          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
  1.3458 +          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
  1.3459 +          listener.point(sλ0, φ0);
  1.3460 +          listener.lineEnd();
  1.3461 +          listener.lineStart();
  1.3462 +          listener.point(sλ1, φ0);
  1.3463 +          clean = 0;
  1.3464 +        }
  1.3465 +        listener.point(λ0 = λ1, φ0 = φ1);
  1.3466 +        sλ0 = sλ1;
  1.3467 +      },
  1.3468 +      lineEnd: function() {
  1.3469 +        listener.lineEnd();
  1.3470 +        λ0 = φ0 = NaN;
  1.3471 +      },
  1.3472 +      clean: function() {
  1.3473 +        return 2 - clean;
  1.3474 +      }
  1.3475 +    };
  1.3476 +  }
  1.3477 +  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
  1.3478 +    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
  1.3479 +    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
  1.3480 +  }
  1.3481 +  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
  1.3482 +    var φ;
  1.3483 +    if (from == null) {
  1.3484 +      φ = direction * halfπ;
  1.3485 +      listener.point(-π, φ);
  1.3486 +      listener.point(0, φ);
  1.3487 +      listener.point(π, φ);
  1.3488 +      listener.point(π, 0);
  1.3489 +      listener.point(π, -φ);
  1.3490 +      listener.point(0, -φ);
  1.3491 +      listener.point(-π, -φ);
  1.3492 +      listener.point(-π, 0);
  1.3493 +      listener.point(-π, φ);
  1.3494 +    } else if (abs(from[0] - to[0]) > ε) {
  1.3495 +      var s = from[0] < to[0] ? π : -π;
  1.3496 +      φ = direction * s / 2;
  1.3497 +      listener.point(-s, φ);
  1.3498 +      listener.point(0, φ);
  1.3499 +      listener.point(s, φ);
  1.3500 +    } else {
  1.3501 +      listener.point(to[0], to[1]);
  1.3502 +    }
  1.3503 +  }
  1.3504 +  function d3_geo_pointInPolygon(point, polygon) {
  1.3505 +    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
  1.3506 +    d3_geo_areaRingSum.reset();
  1.3507 +    for (var i = 0, n = polygon.length; i < n; ++i) {
  1.3508 +      var ring = polygon[i], m = ring.length;
  1.3509 +      if (!m) continue;
  1.3510 +      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
  1.3511 +      while (true) {
  1.3512 +        if (j === m) j = 0;
  1.3513 +        point = ring[j];
  1.3514 +        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
  1.3515 +        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
  1.3516 +        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
  1.3517 +        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
  1.3518 +          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
  1.3519 +          d3_geo_cartesianNormalize(arc);
  1.3520 +          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
  1.3521 +          d3_geo_cartesianNormalize(intersection);
  1.3522 +          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
  1.3523 +          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
  1.3524 +            winding += antimeridian ^ dλ >= 0 ? 1 : -1;
  1.3525 +          }
  1.3526 +        }
  1.3527 +        if (!j++) break;
  1.3528 +        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
  1.3529 +      }
  1.3530 +    }
  1.3531 +    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1;
  1.3532 +  }
  1.3533 +  function d3_geo_clipCircle(radius) {
  1.3534 +    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
  1.3535 +    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
  1.3536 +    function visible(λ, φ) {
  1.3537 +      return Math.cos(λ) * Math.cos(φ) > cr;
  1.3538 +    }
  1.3539 +    function clipLine(listener) {
  1.3540 +      var point0, c0, v0, v00, clean;
  1.3541 +      return {
  1.3542 +        lineStart: function() {
  1.3543 +          v00 = v0 = false;
  1.3544 +          clean = 1;
  1.3545 +        },
  1.3546 +        point: function(λ, φ) {
  1.3547 +          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
  1.3548 +          if (!point0 && (v00 = v0 = v)) listener.lineStart();
  1.3549 +          if (v !== v0) {
  1.3550 +            point2 = intersect(point0, point1);
  1.3551 +            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
  1.3552 +              point1[0] += ε;
  1.3553 +              point1[1] += ε;
  1.3554 +              v = visible(point1[0], point1[1]);
  1.3555 +            }
  1.3556 +          }
  1.3557 +          if (v !== v0) {
  1.3558 +            clean = 0;
  1.3559 +            if (v) {
  1.3560 +              listener.lineStart();
  1.3561 +              point2 = intersect(point1, point0);
  1.3562 +              listener.point(point2[0], point2[1]);
  1.3563 +            } else {
  1.3564 +              point2 = intersect(point0, point1);
  1.3565 +              listener.point(point2[0], point2[1]);
  1.3566 +              listener.lineEnd();
  1.3567 +            }
  1.3568 +            point0 = point2;
  1.3569 +          } else if (notHemisphere && point0 && smallRadius ^ v) {
  1.3570 +            var t;
  1.3571 +            if (!(c & c0) && (t = intersect(point1, point0, true))) {
  1.3572 +              clean = 0;
  1.3573 +              if (smallRadius) {
  1.3574 +                listener.lineStart();
  1.3575 +                listener.point(t[0][0], t[0][1]);
  1.3576 +                listener.point(t[1][0], t[1][1]);
  1.3577 +                listener.lineEnd();
  1.3578 +              } else {
  1.3579 +                listener.point(t[1][0], t[1][1]);
  1.3580 +                listener.lineEnd();
  1.3581 +                listener.lineStart();
  1.3582 +                listener.point(t[0][0], t[0][1]);
  1.3583 +              }
  1.3584 +            }
  1.3585 +          }
  1.3586 +          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
  1.3587 +            listener.point(point1[0], point1[1]);
  1.3588 +          }
  1.3589 +          point0 = point1, v0 = v, c0 = c;
  1.3590 +        },
  1.3591 +        lineEnd: function() {
  1.3592 +          if (v0) listener.lineEnd();
  1.3593 +          point0 = null;
  1.3594 +        },
  1.3595 +        clean: function() {
  1.3596 +          return clean | (v00 && v0) << 1;
  1.3597 +        }
  1.3598 +      };
  1.3599 +    }
  1.3600 +    function intersect(a, b, two) {
  1.3601 +      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
  1.3602 +      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
  1.3603 +      if (!determinant) return !two && a;
  1.3604 +      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
  1.3605 +      d3_geo_cartesianAdd(A, B);
  1.3606 +      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
  1.3607 +      if (t2 < 0) return;
  1.3608 +      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
  1.3609 +      d3_geo_cartesianAdd(q, A);
  1.3610 +      q = d3_geo_spherical(q);
  1.3611 +      if (!two) return q;
  1.3612 +      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
  1.3613 +      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
  1.3614 +      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
  1.3615 +      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
  1.3616 +      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
  1.3617 +        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
  1.3618 +        d3_geo_cartesianAdd(q1, A);
  1.3619 +        return [ q, d3_geo_spherical(q1) ];
  1.3620 +      }
  1.3621 +    }
  1.3622 +    function code(λ, φ) {
  1.3623 +      var r = smallRadius ? radius : π - radius, code = 0;
  1.3624 +      if (λ < -r) code |= 1; else if (λ > r) code |= 2;
  1.3625 +      if (φ < -r) code |= 4; else if (φ > r) code |= 8;
  1.3626 +      return code;
  1.3627 +    }
  1.3628 +  }
  1.3629 +  function d3_geom_clipLine(x0, y0, x1, y1) {
  1.3630 +    return function(line) {
  1.3631 +      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
  1.3632 +      r = x0 - ax;
  1.3633 +      if (!dx && r > 0) return;
  1.3634 +      r /= dx;
  1.3635 +      if (dx < 0) {
  1.3636 +        if (r < t0) return;
  1.3637 +        if (r < t1) t1 = r;
  1.3638 +      } else if (dx > 0) {
  1.3639 +        if (r > t1) return;
  1.3640 +        if (r > t0) t0 = r;
  1.3641 +      }
  1.3642 +      r = x1 - ax;
  1.3643 +      if (!dx && r < 0) return;
  1.3644 +      r /= dx;
  1.3645 +      if (dx < 0) {
  1.3646 +        if (r > t1) return;
  1.3647 +        if (r > t0) t0 = r;
  1.3648 +      } else if (dx > 0) {
  1.3649 +        if (r < t0) return;
  1.3650 +        if (r < t1) t1 = r;
  1.3651 +      }
  1.3652 +      r = y0 - ay;
  1.3653 +      if (!dy && r > 0) return;
  1.3654 +      r /= dy;
  1.3655 +      if (dy < 0) {
  1.3656 +        if (r < t0) return;
  1.3657 +        if (r < t1) t1 = r;
  1.3658 +      } else if (dy > 0) {
  1.3659 +        if (r > t1) return;
  1.3660 +        if (r > t0) t0 = r;
  1.3661 +      }
  1.3662 +      r = y1 - ay;
  1.3663 +      if (!dy && r < 0) return;
  1.3664 +      r /= dy;
  1.3665 +      if (dy < 0) {
  1.3666 +        if (r > t1) return;
  1.3667 +        if (r > t0) t0 = r;
  1.3668 +      } else if (dy > 0) {
  1.3669 +        if (r < t0) return;
  1.3670 +        if (r < t1) t1 = r;
  1.3671 +      }
  1.3672 +      if (t0 > 0) line.a = {
  1.3673 +        x: ax + t0 * dx,
  1.3674 +        y: ay + t0 * dy
  1.3675 +      };
  1.3676 +      if (t1 < 1) line.b = {
  1.3677 +        x: ax + t1 * dx,
  1.3678 +        y: ay + t1 * dy
  1.3679 +      };
  1.3680 +      return line;
  1.3681 +    };
  1.3682 +  }
  1.3683 +  var d3_geo_clipExtentMAX = 1e9;
  1.3684 +  d3.geo.clipExtent = function() {
  1.3685 +    var x0, y0, x1, y1, stream, clip, clipExtent = {
  1.3686 +      stream: function(output) {
  1.3687 +        if (stream) stream.valid = false;
  1.3688 +        stream = clip(output);
  1.3689 +        stream.valid = true;
  1.3690 +        return stream;
  1.3691 +      },
  1.3692 +      extent: function(_) {
  1.3693 +        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
  1.3694 +        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
  1.3695 +        if (stream) stream.valid = false, stream = null;
  1.3696 +        return clipExtent;
  1.3697 +      }
  1.3698 +    };
  1.3699 +    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
  1.3700 +  };
  1.3701 +  function d3_geo_clipExtent(x0, y0, x1, y1) {
  1.3702 +    return function(listener) {
  1.3703 +      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
  1.3704 +      var clip = {
  1.3705 +        point: point,
  1.3706 +        lineStart: lineStart,
  1.3707 +        lineEnd: lineEnd,
  1.3708 +        polygonStart: function() {
  1.3709 +          listener = bufferListener;
  1.3710 +          segments = [];
  1.3711 +          polygon = [];
  1.3712 +          clean = true;
  1.3713 +        },
  1.3714 +        polygonEnd: function() {
  1.3715 +          listener = listener_;
  1.3716 +          segments = d3.merge(segments);
  1.3717 +          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
  1.3718 +          if (inside || visible) {
  1.3719 +            listener.polygonStart();
  1.3720 +            if (inside) {
  1.3721 +              listener.lineStart();
  1.3722 +              interpolate(null, null, 1, listener);
  1.3723 +              listener.lineEnd();
  1.3724 +            }
  1.3725 +            if (visible) {
  1.3726 +              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
  1.3727 +            }
  1.3728 +            listener.polygonEnd();
  1.3729 +          }
  1.3730 +          segments = polygon = ring = null;
  1.3731 +        }
  1.3732 +      };
  1.3733 +      function insidePolygon(p) {
  1.3734 +        var wn = 0, n = polygon.length, y = p[1];
  1.3735 +        for (var i = 0; i < n; ++i) {
  1.3736 +          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
  1.3737 +            b = v[j];
  1.3738 +            if (a[1] <= y) {
  1.3739 +              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
  1.3740 +            } else {
  1.3741 +              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
  1.3742 +            }
  1.3743 +            a = b;
  1.3744 +          }
  1.3745 +        }
  1.3746 +        return wn !== 0;
  1.3747 +      }
  1.3748 +      function interpolate(from, to, direction, listener) {
  1.3749 +        var a = 0, a1 = 0;
  1.3750 +        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
  1.3751 +          do {
  1.3752 +            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
  1.3753 +          } while ((a = (a + direction + 4) % 4) !== a1);
  1.3754 +        } else {
  1.3755 +          listener.point(to[0], to[1]);
  1.3756 +        }
  1.3757 +      }
  1.3758 +      function pointVisible(x, y) {
  1.3759 +        return x0 <= x && x <= x1 && y0 <= y && y <= y1;
  1.3760 +      }
  1.3761 +      function point(x, y) {
  1.3762 +        if (pointVisible(x, y)) listener.point(x, y);
  1.3763 +      }
  1.3764 +      var x__, y__, v__, x_, y_, v_, first, clean;
  1.3765 +      function lineStart() {
  1.3766 +        clip.point = linePoint;
  1.3767 +        if (polygon) polygon.push(ring = []);
  1.3768 +        first = true;
  1.3769 +        v_ = false;
  1.3770 +        x_ = y_ = NaN;
  1.3771 +      }
  1.3772 +      function lineEnd() {
  1.3773 +        if (segments) {
  1.3774 +          linePoint(x__, y__);
  1.3775 +          if (v__ && v_) bufferListener.rejoin();
  1.3776 +          segments.push(bufferListener.buffer());
  1.3777 +        }
  1.3778 +        clip.point = point;
  1.3779 +        if (v_) listener.lineEnd();
  1.3780 +      }
  1.3781 +      function linePoint(x, y) {
  1.3782 +        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
  1.3783 +        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
  1.3784 +        var v = pointVisible(x, y);
  1.3785 +        if (polygon) ring.push([ x, y ]);
  1.3786 +        if (first) {
  1.3787 +          x__ = x, y__ = y, v__ = v;
  1.3788 +          first = false;
  1.3789 +          if (v) {
  1.3790 +            listener.lineStart();
  1.3791 +            listener.point(x, y);
  1.3792 +          }
  1.3793 +        } else {
  1.3794 +          if (v && v_) listener.point(x, y); else {
  1.3795 +            var l = {
  1.3796 +              a: {
  1.3797 +                x: x_,
  1.3798 +                y: y_
  1.3799 +              },
  1.3800 +              b: {
  1.3801 +                x: x,
  1.3802 +                y: y
  1.3803 +              }
  1.3804 +            };
  1.3805 +            if (clipLine(l)) {
  1.3806 +              if (!v_) {
  1.3807 +                listener.lineStart();
  1.3808 +                listener.point(l.a.x, l.a.y);
  1.3809 +              }
  1.3810 +              listener.point(l.b.x, l.b.y);
  1.3811 +              if (!v) listener.lineEnd();
  1.3812 +              clean = false;
  1.3813 +            } else if (v) {
  1.3814 +              listener.lineStart();
  1.3815 +              listener.point(x, y);
  1.3816 +              clean = false;
  1.3817 +            }
  1.3818 +          }
  1.3819 +        }
  1.3820 +        x_ = x, y_ = y, v_ = v;
  1.3821 +      }
  1.3822 +      return clip;
  1.3823 +    };
  1.3824 +    function corner(p, direction) {
  1.3825 +      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
  1.3826 +    }
  1.3827 +    function compare(a, b) {
  1.3828 +      return comparePoints(a.x, b.x);
  1.3829 +    }
  1.3830 +    function comparePoints(a, b) {
  1.3831 +      var ca = corner(a, 1), cb = corner(b, 1);
  1.3832 +      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
  1.3833 +    }
  1.3834 +  }
  1.3835 +  function d3_geo_conic(projectAt) {
  1.3836 +    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
  1.3837 +    p.parallels = function(_) {
  1.3838 +      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
  1.3839 +      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
  1.3840 +    };
  1.3841 +    return p;
  1.3842 +  }
  1.3843 +  function d3_geo_conicEqualArea(φ0, φ1) {
  1.3844 +    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
  1.3845 +    function forward(λ, φ) {
  1.3846 +      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
  1.3847 +      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
  1.3848 +    }
  1.3849 +    forward.invert = function(x, y) {
  1.3850 +      var ρ0_y = ρ0 - y;
  1.3851 +      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
  1.3852 +    };
  1.3853 +    return forward;
  1.3854 +  }
  1.3855 +  (d3.geo.conicEqualArea = function() {
  1.3856 +    return d3_geo_conic(d3_geo_conicEqualArea);
  1.3857 +  }).raw = d3_geo_conicEqualArea;
  1.3858 +  d3.geo.albers = function() {
  1.3859 +    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
  1.3860 +  };
  1.3861 +  d3.geo.albersUsa = function() {
  1.3862 +    var lower48 = d3.geo.albers();
  1.3863 +    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
  1.3864 +    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
  1.3865 +    var point, pointStream = {
  1.3866 +      point: function(x, y) {
  1.3867 +        point = [ x, y ];
  1.3868 +      }
  1.3869 +    }, lower48Point, alaskaPoint, hawaiiPoint;
  1.3870 +    function albersUsa(coordinates) {
  1.3871 +      var x = coordinates[0], y = coordinates[1];
  1.3872 +      point = null;
  1.3873 +      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
  1.3874 +      return point;
  1.3875 +    }
  1.3876 +    albersUsa.invert = function(coordinates) {
  1.3877 +      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
  1.3878 +      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
  1.3879 +    };
  1.3880 +    albersUsa.stream = function(stream) {
  1.3881 +      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
  1.3882 +      return {
  1.3883 +        point: function(x, y) {
  1.3884 +          lower48Stream.point(x, y);
  1.3885 +          alaskaStream.point(x, y);
  1.3886 +          hawaiiStream.point(x, y);
  1.3887 +        },
  1.3888 +        sphere: function() {
  1.3889 +          lower48Stream.sphere();
  1.3890 +          alaskaStream.sphere();
  1.3891 +          hawaiiStream.sphere();
  1.3892 +        },
  1.3893 +        lineStart: function() {
  1.3894 +          lower48Stream.lineStart();
  1.3895 +          alaskaStream.lineStart();
  1.3896 +          hawaiiStream.lineStart();
  1.3897 +        },
  1.3898 +        lineEnd: function() {
  1.3899 +          lower48Stream.lineEnd();
  1.3900 +          alaskaStream.lineEnd();
  1.3901 +          hawaiiStream.lineEnd();
  1.3902 +        },
  1.3903 +        polygonStart: function() {
  1.3904 +          lower48Stream.polygonStart();
  1.3905 +          alaskaStream.polygonStart();
  1.3906 +          hawaiiStream.polygonStart();
  1.3907 +        },
  1.3908 +        polygonEnd: function() {
  1.3909 +          lower48Stream.polygonEnd();
  1.3910 +          alaskaStream.polygonEnd();
  1.3911 +          hawaiiStream.polygonEnd();
  1.3912 +        }
  1.3913 +      };
  1.3914 +    };
  1.3915 +    albersUsa.precision = function(_) {
  1.3916 +      if (!arguments.length) return lower48.precision();
  1.3917 +      lower48.precision(_);
  1.3918 +      alaska.precision(_);
  1.3919 +      hawaii.precision(_);
  1.3920 +      return albersUsa;
  1.3921 +    };
  1.3922 +    albersUsa.scale = function(_) {
  1.3923 +      if (!arguments.length) return lower48.scale();
  1.3924 +      lower48.scale(_);
  1.3925 +      alaska.scale(_ * .35);
  1.3926 +      hawaii.scale(_);
  1.3927 +      return albersUsa.translate(lower48.translate());
  1.3928 +    };
  1.3929 +    albersUsa.translate = function(_) {
  1.3930 +      if (!arguments.length) return lower48.translate();
  1.3931 +      var k = lower48.scale(), x = +_[0], y = +_[1];
  1.3932 +      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
  1.3933 +      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
  1.3934 +      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
  1.3935 +      return albersUsa;
  1.3936 +    };
  1.3937 +    return albersUsa.scale(1070);
  1.3938 +  };
  1.3939 +  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
  1.3940 +    point: d3_noop,
  1.3941 +    lineStart: d3_noop,
  1.3942 +    lineEnd: d3_noop,
  1.3943 +    polygonStart: function() {
  1.3944 +      d3_geo_pathAreaPolygon = 0;
  1.3945 +      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
  1.3946 +    },
  1.3947 +    polygonEnd: function() {
  1.3948 +      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
  1.3949 +      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
  1.3950 +    }
  1.3951 +  };
  1.3952 +  function d3_geo_pathAreaRingStart() {
  1.3953 +    var x00, y00, x0, y0;
  1.3954 +    d3_geo_pathArea.point = function(x, y) {
  1.3955 +      d3_geo_pathArea.point = nextPoint;
  1.3956 +      x00 = x0 = x, y00 = y0 = y;
  1.3957 +    };
  1.3958 +    function nextPoint(x, y) {
  1.3959 +      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
  1.3960 +      x0 = x, y0 = y;
  1.3961 +    }
  1.3962 +    d3_geo_pathArea.lineEnd = function() {
  1.3963 +      nextPoint(x00, y00);
  1.3964 +    };
  1.3965 +  }
  1.3966 +  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
  1.3967 +  var d3_geo_pathBounds = {
  1.3968 +    point: d3_geo_pathBoundsPoint,
  1.3969 +    lineStart: d3_noop,
  1.3970 +    lineEnd: d3_noop,
  1.3971 +    polygonStart: d3_noop,
  1.3972 +    polygonEnd: d3_noop
  1.3973 +  };
  1.3974 +  function d3_geo_pathBoundsPoint(x, y) {
  1.3975 +    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
  1.3976 +    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
  1.3977 +    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
  1.3978 +    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
  1.3979 +  }
  1.3980 +  function d3_geo_pathBuffer() {
  1.3981 +    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
  1.3982 +    var stream = {
  1.3983 +      point: point,
  1.3984 +      lineStart: function() {
  1.3985 +        stream.point = pointLineStart;
  1.3986 +      },
  1.3987 +      lineEnd: lineEnd,
  1.3988 +      polygonStart: function() {
  1.3989 +        stream.lineEnd = lineEndPolygon;
  1.3990 +      },
  1.3991 +      polygonEnd: function() {
  1.3992 +        stream.lineEnd = lineEnd;
  1.3993 +        stream.point = point;
  1.3994 +      },
  1.3995 +      pointRadius: function(_) {
  1.3996 +        pointCircle = d3_geo_pathBufferCircle(_);
  1.3997 +        return stream;
  1.3998 +      },
  1.3999 +      result: function() {
  1.4000 +        if (buffer.length) {
  1.4001 +          var result = buffer.join("");
  1.4002 +          buffer = [];
  1.4003 +          return result;
  1.4004 +        }
  1.4005 +      }
  1.4006 +    };
  1.4007 +    function point(x, y) {
  1.4008 +      buffer.push("M", x, ",", y, pointCircle);
  1.4009 +    }
  1.4010 +    function pointLineStart(x, y) {
  1.4011 +      buffer.push("M", x, ",", y);
  1.4012 +      stream.point = pointLine;
  1.4013 +    }
  1.4014 +    function pointLine(x, y) {
  1.4015 +      buffer.push("L", x, ",", y);
  1.4016 +    }
  1.4017 +    function lineEnd() {
  1.4018 +      stream.point = point;
  1.4019 +    }
  1.4020 +    function lineEndPolygon() {
  1.4021 +      buffer.push("Z");
  1.4022 +    }
  1.4023 +    return stream;
  1.4024 +  }
  1.4025 +  function d3_geo_pathBufferCircle(radius) {
  1.4026 +    return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
  1.4027 +  }
  1.4028 +  var d3_geo_pathCentroid = {
  1.4029 +    point: d3_geo_pathCentroidPoint,
  1.4030 +    lineStart: d3_geo_pathCentroidLineStart,
  1.4031 +    lineEnd: d3_geo_pathCentroidLineEnd,
  1.4032 +    polygonStart: function() {
  1.4033 +      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
  1.4034 +    },
  1.4035 +    polygonEnd: function() {
  1.4036 +      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
  1.4037 +      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
  1.4038 +      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
  1.4039 +    }
  1.4040 +  };
  1.4041 +  function d3_geo_pathCentroidPoint(x, y) {
  1.4042 +    d3_geo_centroidX0 += x;
  1.4043 +    d3_geo_centroidY0 += y;
  1.4044 +    ++d3_geo_centroidZ0;
  1.4045 +  }
  1.4046 +  function d3_geo_pathCentroidLineStart() {
  1.4047 +    var x0, y0;
  1.4048 +    d3_geo_pathCentroid.point = function(x, y) {
  1.4049 +      d3_geo_pathCentroid.point = nextPoint;
  1.4050 +      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
  1.4051 +    };
  1.4052 +    function nextPoint(x, y) {
  1.4053 +      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
  1.4054 +      d3_geo_centroidX1 += z * (x0 + x) / 2;
  1.4055 +      d3_geo_centroidY1 += z * (y0 + y) / 2;
  1.4056 +      d3_geo_centroidZ1 += z;
  1.4057 +      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
  1.4058 +    }
  1.4059 +  }
  1.4060 +  function d3_geo_pathCentroidLineEnd() {
  1.4061 +    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
  1.4062 +  }
  1.4063 +  function d3_geo_pathCentroidRingStart() {
  1.4064 +    var x00, y00, x0, y0;
  1.4065 +    d3_geo_pathCentroid.point = function(x, y) {
  1.4066 +      d3_geo_pathCentroid.point = nextPoint;
  1.4067 +      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
  1.4068 +    };
  1.4069 +    function nextPoint(x, y) {
  1.4070 +      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
  1.4071 +      d3_geo_centroidX1 += z * (x0 + x) / 2;
  1.4072 +      d3_geo_centroidY1 += z * (y0 + y) / 2;
  1.4073 +      d3_geo_centroidZ1 += z;
  1.4074 +      z = y0 * x - x0 * y;
  1.4075 +      d3_geo_centroidX2 += z * (x0 + x);
  1.4076 +      d3_geo_centroidY2 += z * (y0 + y);
  1.4077 +      d3_geo_centroidZ2 += z * 3;
  1.4078 +      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
  1.4079 +    }
  1.4080 +    d3_geo_pathCentroid.lineEnd = function() {
  1.4081 +      nextPoint(x00, y00);
  1.4082 +    };
  1.4083 +  }
  1.4084 +  function d3_geo_pathContext(context) {
  1.4085 +    var pointRadius = 4.5;
  1.4086 +    var stream = {
  1.4087 +      point: point,
  1.4088 +      lineStart: function() {
  1.4089 +        stream.point = pointLineStart;
  1.4090 +      },
  1.4091 +      lineEnd: lineEnd,
  1.4092 +      polygonStart: function() {
  1.4093 +        stream.lineEnd = lineEndPolygon;
  1.4094 +      },
  1.4095 +      polygonEnd: function() {
  1.4096 +        stream.lineEnd = lineEnd;
  1.4097 +        stream.point = point;
  1.4098 +      },
  1.4099 +      pointRadius: function(_) {
  1.4100 +        pointRadius = _;
  1.4101 +        return stream;
  1.4102 +      },
  1.4103 +      result: d3_noop
  1.4104 +    };
  1.4105 +    function point(x, y) {
  1.4106 +      context.moveTo(x + pointRadius, y);
  1.4107 +      context.arc(x, y, pointRadius, 0, τ);
  1.4108 +    }
  1.4109 +    function pointLineStart(x, y) {
  1.4110 +      context.moveTo(x, y);
  1.4111 +      stream.point = pointLine;
  1.4112 +    }
  1.4113 +    function pointLine(x, y) {
  1.4114 +      context.lineTo(x, y);
  1.4115 +    }
  1.4116 +    function lineEnd() {
  1.4117 +      stream.point = point;
  1.4118 +    }
  1.4119 +    function lineEndPolygon() {
  1.4120 +      context.closePath();
  1.4121 +    }
  1.4122 +    return stream;
  1.4123 +  }
  1.4124 +  function d3_geo_resample(project) {
  1.4125 +    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
  1.4126 +    function resample(stream) {
  1.4127 +      return (maxDepth ? resampleRecursive : resampleNone)(stream);
  1.4128 +    }
  1.4129 +    function resampleNone(stream) {
  1.4130 +      return d3_geo_transformPoint(stream, function(x, y) {
  1.4131 +        x = project(x, y);
  1.4132 +        stream.point(x[0], x[1]);
  1.4133 +      });
  1.4134 +    }
  1.4135 +    function resampleRecursive(stream) {
  1.4136 +      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
  1.4137 +      var resample = {
  1.4138 +        point: point,
  1.4139 +        lineStart: lineStart,
  1.4140 +        lineEnd: lineEnd,
  1.4141 +        polygonStart: function() {
  1.4142 +          stream.polygonStart();
  1.4143 +          resample.lineStart = ringStart;
  1.4144 +        },
  1.4145 +        polygonEnd: function() {
  1.4146 +          stream.polygonEnd();
  1.4147 +          resample.lineStart = lineStart;
  1.4148 +        }
  1.4149 +      };
  1.4150 +      function point(x, y) {
  1.4151 +        x = project(x, y);
  1.4152 +        stream.point(x[0], x[1]);
  1.4153 +      }
  1.4154 +      function lineStart() {
  1.4155 +        x0 = NaN;
  1.4156 +        resample.point = linePoint;
  1.4157 +        stream.lineStart();
  1.4158 +      }
  1.4159 +      function linePoint(λ, φ) {
  1.4160 +        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
  1.4161 +        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
  1.4162 +        stream.point(x0, y0);
  1.4163 +      }
  1.4164 +      function lineEnd() {
  1.4165 +        resample.point = point;
  1.4166 +        stream.lineEnd();
  1.4167 +      }
  1.4168 +      function ringStart() {
  1.4169 +        lineStart();
  1.4170 +        resample.point = ringPoint;
  1.4171 +        resample.lineEnd = ringEnd;
  1.4172 +      }
  1.4173 +      function ringPoint(λ, φ) {
  1.4174 +        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
  1.4175 +        resample.point = linePoint;
  1.4176 +      }
  1.4177 +      function ringEnd() {
  1.4178 +        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
  1.4179 +        resample.lineEnd = lineEnd;
  1.4180 +        lineEnd();
  1.4181 +      }
  1.4182 +      return resample;
  1.4183 +    }
  1.4184 +    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
  1.4185 +      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
  1.4186 +      if (d2 > 4 * δ2 && depth--) {
  1.4187 +        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
  1.4188 +        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
  1.4189 +          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
  1.4190 +          stream.point(x2, y2);
  1.4191 +          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
  1.4192 +        }
  1.4193 +      }
  1.4194 +    }
  1.4195 +    resample.precision = function(_) {
  1.4196 +      if (!arguments.length) return Math.sqrt(δ2);
  1.4197 +      maxDepth = (δ2 = _ * _) > 0 && 16;
  1.4198 +      return resample;
  1.4199 +    };
  1.4200 +    return resample;
  1.4201 +  }
  1.4202 +  d3.geo.path = function() {
  1.4203 +    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
  1.4204 +    function path(object) {
  1.4205 +      if (object) {
  1.4206 +        if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
  1.4207 +        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
  1.4208 +        d3.geo.stream(object, cacheStream);
  1.4209 +      }
  1.4210 +      return contextStream.result();
  1.4211 +    }
  1.4212 +    path.area = function(object) {
  1.4213 +      d3_geo_pathAreaSum = 0;
  1.4214 +      d3.geo.stream(object, projectStream(d3_geo_pathArea));
  1.4215 +      return d3_geo_pathAreaSum;
  1.4216 +    };
  1.4217 +    path.centroid = function(object) {
  1.4218 +      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
  1.4219 +      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
  1.4220 +      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
  1.4221 +    };
  1.4222 +    path.bounds = function(object) {
  1.4223 +      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
  1.4224 +      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
  1.4225 +      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
  1.4226 +    };
  1.4227 +    path.projection = function(_) {
  1.4228 +      if (!arguments.length) return projection;
  1.4229 +      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
  1.4230 +      return reset();
  1.4231 +    };
  1.4232 +    path.context = function(_) {
  1.4233 +      if (!arguments.length) return context;
  1.4234 +      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
  1.4235 +      if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
  1.4236 +      return reset();
  1.4237 +    };
  1.4238 +    path.pointRadius = function(_) {
  1.4239 +      if (!arguments.length) return pointRadius;
  1.4240 +      pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
  1.4241 +      return path;
  1.4242 +    };
  1.4243 +    function reset() {
  1.4244 +      cacheStream = null;
  1.4245 +      return path;
  1.4246 +    }
  1.4247 +    return path.projection(d3.geo.albersUsa()).context(null);
  1.4248 +  };
  1.4249 +  function d3_geo_pathProjectStream(project) {
  1.4250 +    var resample = d3_geo_resample(function(x, y) {
  1.4251 +      return project([ x * d3_degrees, y * d3_degrees ]);
  1.4252 +    });
  1.4253 +    return function(stream) {
  1.4254 +      return d3_geo_projectionRadians(resample(stream));
  1.4255 +    };
  1.4256 +  }
  1.4257 +  d3.geo.transform = function(methods) {
  1.4258 +    return {
  1.4259 +      stream: function(stream) {
  1.4260 +        var transform = new d3_geo_transform(stream);
  1.4261 +        for (var k in methods) transform[k] = methods[k];
  1.4262 +        return transform;
  1.4263 +      }
  1.4264 +    };
  1.4265 +  };
  1.4266 +  function d3_geo_transform(stream) {
  1.4267 +    this.stream = stream;
  1.4268 +  }
  1.4269 +  d3_geo_transform.prototype = {
  1.4270 +    point: function(x, y) {
  1.4271 +      this.stream.point(x, y);
  1.4272 +    },
  1.4273 +    sphere: function() {
  1.4274 +      this.stream.sphere();
  1.4275 +    },
  1.4276 +    lineStart: function() {
  1.4277 +      this.stream.lineStart();
  1.4278 +    },
  1.4279 +    lineEnd: function() {
  1.4280 +      this.stream.lineEnd();
  1.4281 +    },
  1.4282 +    polygonStart: function() {
  1.4283 +      this.stream.polygonStart();
  1.4284 +    },
  1.4285 +    polygonEnd: function() {
  1.4286 +      this.stream.polygonEnd();
  1.4287 +    }
  1.4288 +  };
  1.4289 +  function d3_geo_transformPoint(stream, point) {
  1.4290 +    return {
  1.4291 +      point: point,
  1.4292 +      sphere: function() {
  1.4293 +        stream.sphere();
  1.4294 +      },
  1.4295 +      lineStart: function() {
  1.4296 +        stream.lineStart();
  1.4297 +      },
  1.4298 +      lineEnd: function() {
  1.4299 +        stream.lineEnd();
  1.4300 +      },
  1.4301 +      polygonStart: function() {
  1.4302 +        stream.polygonStart();
  1.4303 +      },
  1.4304 +      polygonEnd: function() {
  1.4305 +        stream.polygonEnd();
  1.4306 +      }
  1.4307 +    };
  1.4308 +  }
  1.4309 +  d3.geo.projection = d3_geo_projection;
  1.4310 +  d3.geo.projectionMutator = d3_geo_projectionMutator;
  1.4311 +  function d3_geo_projection(project) {
  1.4312 +    return d3_geo_projectionMutator(function() {
  1.4313 +      return project;
  1.4314 +    })();
  1.4315 +  }
  1.4316 +  function d3_geo_projectionMutator(projectAt) {
  1.4317 +    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
  1.4318 +      x = project(x, y);
  1.4319 +      return [ x[0] * k + δx, δy - x[1] * k ];
  1.4320 +    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
  1.4321 +    function projection(point) {
  1.4322 +      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
  1.4323 +      return [ point[0] * k + δx, δy - point[1] * k ];
  1.4324 +    }
  1.4325 +    function invert(point) {
  1.4326 +      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
  1.4327 +      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
  1.4328 +    }
  1.4329 +    projection.stream = function(output) {
  1.4330 +      if (stream) stream.valid = false;
  1.4331 +      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
  1.4332 +      stream.valid = true;
  1.4333 +      return stream;
  1.4334 +    };
  1.4335 +    projection.clipAngle = function(_) {
  1.4336 +      if (!arguments.length) return clipAngle;
  1.4337 +      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
  1.4338 +      return invalidate();
  1.4339 +    };
  1.4340 +    projection.clipExtent = function(_) {
  1.4341 +      if (!arguments.length) return clipExtent;
  1.4342 +      clipExtent = _;
  1.4343 +      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
  1.4344 +      return invalidate();
  1.4345 +    };
  1.4346 +    projection.scale = function(_) {
  1.4347 +      if (!arguments.length) return k;
  1.4348 +      k = +_;
  1.4349 +      return reset();
  1.4350 +    };
  1.4351 +    projection.translate = function(_) {
  1.4352 +      if (!arguments.length) return [ x, y ];
  1.4353 +      x = +_[0];
  1.4354 +      y = +_[1];
  1.4355 +      return reset();
  1.4356 +    };
  1.4357 +    projection.center = function(_) {
  1.4358 +      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
  1.4359 +      λ = _[0] % 360 * d3_radians;
  1.4360 +      φ = _[1] % 360 * d3_radians;
  1.4361 +      return reset();
  1.4362 +    };
  1.4363 +    projection.rotate = function(_) {
  1.4364 +      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
  1.4365 +      δλ = _[0] % 360 * d3_radians;
  1.4366 +      δφ = _[1] % 360 * d3_radians;
  1.4367 +      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
  1.4368 +      return reset();
  1.4369 +    };
  1.4370 +    d3.rebind(projection, projectResample, "precision");
  1.4371 +    function reset() {
  1.4372 +      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
  1.4373 +      var center = project(λ, φ);
  1.4374 +      δx = x - center[0] * k;
  1.4375 +      δy = y + center[1] * k;
  1.4376 +      return invalidate();
  1.4377 +    }
  1.4378 +    function invalidate() {
  1.4379 +      if (stream) stream.valid = false, stream = null;
  1.4380 +      return projection;
  1.4381 +    }
  1.4382 +    return function() {
  1.4383 +      project = projectAt.apply(this, arguments);
  1.4384 +      projection.invert = project.invert && invert;
  1.4385 +      return reset();
  1.4386 +    };
  1.4387 +  }
  1.4388 +  function d3_geo_projectionRadians(stream) {
  1.4389 +    return d3_geo_transformPoint(stream, function(x, y) {
  1.4390 +      stream.point(x * d3_radians, y * d3_radians);
  1.4391 +    });
  1.4392 +  }
  1.4393 +  function d3_geo_equirectangular(λ, φ) {
  1.4394 +    return [ λ, φ ];
  1.4395 +  }
  1.4396 +  (d3.geo.equirectangular = function() {
  1.4397 +    return d3_geo_projection(d3_geo_equirectangular);
  1.4398 +  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
  1.4399 +  d3.geo.rotation = function(rotate) {
  1.4400 +    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
  1.4401 +    function forward(coordinates) {
  1.4402 +      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
  1.4403 +      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
  1.4404 +    }
  1.4405 +    forward.invert = function(coordinates) {
  1.4406 +      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
  1.4407 +      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
  1.4408 +    };
  1.4409 +    return forward;
  1.4410 +  };
  1.4411 +  function d3_geo_identityRotation(λ, φ) {
  1.4412 +    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
  1.4413 +  }
  1.4414 +  d3_geo_identityRotation.invert = d3_geo_equirectangular;
  1.4415 +  function d3_geo_rotation(δλ, δφ, δγ) {
  1.4416 +    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
  1.4417 +  }
  1.4418 +  function d3_geo_forwardRotationλ(δλ) {
  1.4419 +    return function(λ, φ) {
  1.4420 +      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
  1.4421 +    };
  1.4422 +  }
  1.4423 +  function d3_geo_rotationλ(δλ) {
  1.4424 +    var rotation = d3_geo_forwardRotationλ(δλ);
  1.4425 +    rotation.invert = d3_geo_forwardRotationλ(-δλ);
  1.4426 +    return rotation;
  1.4427 +  }
  1.4428 +  function d3_geo_rotationφγ(δφ, δγ) {
  1.4429 +    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
  1.4430 +    function rotation(λ, φ) {
  1.4431 +      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
  1.4432 +      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
  1.4433 +    }
  1.4434 +    rotation.invert = function(λ, φ) {
  1.4435 +      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
  1.4436 +      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
  1.4437 +    };
  1.4438 +    return rotation;
  1.4439 +  }
  1.4440 +  d3.geo.circle = function() {
  1.4441 +    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
  1.4442 +    function circle() {
  1.4443 +      var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
  1.4444 +      interpolate(null, null, 1, {
  1.4445 +        point: function(x, y) {
  1.4446 +          ring.push(x = rotate(x, y));
  1.4447 +          x[0] *= d3_degrees, x[1] *= d3_degrees;
  1.4448 +        }
  1.4449 +      });
  1.4450 +      return {
  1.4451 +        type: "Polygon",
  1.4452 +        coordinates: [ ring ]
  1.4453 +      };
  1.4454 +    }
  1.4455 +    circle.origin = function(x) {
  1.4456 +      if (!arguments.length) return origin;
  1.4457 +      origin = x;
  1.4458 +      return circle;
  1.4459 +    };
  1.4460 +    circle.angle = function(x) {
  1.4461 +      if (!arguments.length) return angle;
  1.4462 +      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
  1.4463 +      return circle;
  1.4464 +    };
  1.4465 +    circle.precision = function(_) {
  1.4466 +      if (!arguments.length) return precision;
  1.4467 +      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
  1.4468 +      return circle;
  1.4469 +    };
  1.4470 +    return circle.angle(90);
  1.4471 +  };
  1.4472 +  function d3_geo_circleInterpolate(radius, precision) {
  1.4473 +    var cr = Math.cos(radius), sr = Math.sin(radius);
  1.4474 +    return function(from, to, direction, listener) {
  1.4475 +      var step = direction * precision;
  1.4476 +      if (from != null) {
  1.4477 +        from = d3_geo_circleAngle(cr, from);
  1.4478 +        to = d3_geo_circleAngle(cr, to);
  1.4479 +        if (direction > 0 ? from < to : from > to) from += direction * τ;
  1.4480 +      } else {
  1.4481 +        from = radius + direction * τ;
  1.4482 +        to = radius - .5 * step;
  1.4483 +      }
  1.4484 +      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
  1.4485 +        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
  1.4486 +      }
  1.4487 +    };
  1.4488 +  }
  1.4489 +  function d3_geo_circleAngle(cr, point) {
  1.4490 +    var a = d3_geo_cartesian(point);
  1.4491 +    a[0] -= cr;
  1.4492 +    d3_geo_cartesianNormalize(a);
  1.4493 +    var angle = d3_acos(-a[1]);
  1.4494 +    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
  1.4495 +  }
  1.4496 +  d3.geo.distance = function(a, b) {
  1.4497 +    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
  1.4498 +    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
  1.4499 +  };
  1.4500 +  d3.geo.graticule = function() {
  1.4501 +    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
  1.4502 +    function graticule() {
  1.4503 +      return {
  1.4504 +        type: "MultiLineString",
  1.4505 +        coordinates: lines()
  1.4506 +      };
  1.4507 +    }
  1.4508 +    function lines() {
  1.4509 +      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
  1.4510 +        return abs(x % DX) > ε;
  1.4511 +      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
  1.4512 +        return abs(y % DY) > ε;
  1.4513 +      }).map(y));
  1.4514 +    }
  1.4515 +    graticule.lines = function() {
  1.4516 +      return lines().map(function(coordinates) {
  1.4517 +        return {
  1.4518 +          type: "LineString",
  1.4519 +          coordinates: coordinates
  1.4520 +        };
  1.4521 +      });
  1.4522 +    };
  1.4523 +    graticule.outline = function() {
  1.4524 +      return {
  1.4525 +        type: "Polygon",
  1.4526 +        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
  1.4527 +      };
  1.4528 +    };
  1.4529 +    graticule.extent = function(_) {
  1.4530 +      if (!arguments.length) return graticule.minorExtent();
  1.4531 +      return graticule.majorExtent(_).minorExtent(_);
  1.4532 +    };
  1.4533 +    graticule.majorExtent = function(_) {
  1.4534 +      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
  1.4535 +      X0 = +_[0][0], X1 = +_[1][0];
  1.4536 +      Y0 = +_[0][1], Y1 = +_[1][1];
  1.4537 +      if (X0 > X1) _ = X0, X0 = X1, X1 = _;
  1.4538 +      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
  1.4539 +      return graticule.precision(precision);
  1.4540 +    };
  1.4541 +    graticule.minorExtent = function(_) {
  1.4542 +      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
  1.4543 +      x0 = +_[0][0], x1 = +_[1][0];
  1.4544 +      y0 = +_[0][1], y1 = +_[1][1];
  1.4545 +      if (x0 > x1) _ = x0, x0 = x1, x1 = _;
  1.4546 +      if (y0 > y1) _ = y0, y0 = y1, y1 = _;
  1.4547 +      return graticule.precision(precision);
  1.4548 +    };
  1.4549 +    graticule.step = function(_) {
  1.4550 +      if (!arguments.length) return graticule.minorStep();
  1.4551 +      return graticule.majorStep(_).minorStep(_);
  1.4552 +    };
  1.4553 +    graticule.majorStep = function(_) {
  1.4554 +      if (!arguments.length) return [ DX, DY ];
  1.4555 +      DX = +_[0], DY = +_[1];
  1.4556 +      return graticule;
  1.4557 +    };
  1.4558 +    graticule.minorStep = function(_) {
  1.4559 +      if (!arguments.length) return [ dx, dy ];
  1.4560 +      dx = +_[0], dy = +_[1];
  1.4561 +      return graticule;
  1.4562 +    };
  1.4563 +    graticule.precision = function(_) {
  1.4564 +      if (!arguments.length) return precision;
  1.4565 +      precision = +_;
  1.4566 +      x = d3_geo_graticuleX(y0, y1, 90);
  1.4567 +      y = d3_geo_graticuleY(x0, x1, precision);
  1.4568 +      X = d3_geo_graticuleX(Y0, Y1, 90);
  1.4569 +      Y = d3_geo_graticuleY(X0, X1, precision);
  1.4570 +      return graticule;
  1.4571 +    };
  1.4572 +    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
  1.4573 +  };
  1.4574 +  function d3_geo_graticuleX(y0, y1, dy) {
  1.4575 +    var y = d3.range(y0, y1 - ε, dy).concat(y1);
  1.4576 +    return function(x) {
  1.4577 +      return y.map(function(y) {
  1.4578 +        return [ x, y ];
  1.4579 +      });
  1.4580 +    };
  1.4581 +  }
  1.4582 +  function d3_geo_graticuleY(x0, x1, dx) {
  1.4583 +    var x = d3.range(x0, x1 - ε, dx).concat(x1);
  1.4584 +    return function(y) {
  1.4585 +      return x.map(function(x) {
  1.4586 +        return [ x, y ];
  1.4587 +      });
  1.4588 +    };
  1.4589 +  }
  1.4590 +  function d3_source(d) {
  1.4591 +    return d.source;
  1.4592 +  }
  1.4593 +  function d3_target(d) {
  1.4594 +    return d.target;
  1.4595 +  }
  1.4596 +  d3.geo.greatArc = function() {
  1.4597 +    var source = d3_source, source_, target = d3_target, target_;
  1.4598 +    function greatArc() {
  1.4599 +      return {
  1.4600 +        type: "LineString",
  1.4601 +        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
  1.4602 +      };
  1.4603 +    }
  1.4604 +    greatArc.distance = function() {
  1.4605 +      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
  1.4606 +    };
  1.4607 +    greatArc.source = function(_) {
  1.4608 +      if (!arguments.length) return source;
  1.4609 +      source = _, source_ = typeof _ === "function" ? null : _;
  1.4610 +      return greatArc;
  1.4611 +    };
  1.4612 +    greatArc.target = function(_) {
  1.4613 +      if (!arguments.length) return target;
  1.4614 +      target = _, target_ = typeof _ === "function" ? null : _;
  1.4615 +      return greatArc;
  1.4616 +    };
  1.4617 +    greatArc.precision = function() {
  1.4618 +      return arguments.length ? greatArc : 0;
  1.4619 +    };
  1.4620 +    return greatArc;
  1.4621 +  };
  1.4622 +  d3.geo.interpolate = function(source, target) {
  1.4623 +    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
  1.4624 +  };
  1.4625 +  function d3_geo_interpolate(x0, y0, x1, y1) {
  1.4626 +    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
  1.4627 +    var interpolate = d ? function(t) {
  1.4628 +      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
  1.4629 +      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
  1.4630 +    } : function() {
  1.4631 +      return [ x0 * d3_degrees, y0 * d3_degrees ];
  1.4632 +    };
  1.4633 +    interpolate.distance = d;
  1.4634 +    return interpolate;
  1.4635 +  }
  1.4636 +  d3.geo.length = function(object) {
  1.4637 +    d3_geo_lengthSum = 0;
  1.4638 +    d3.geo.stream(object, d3_geo_length);
  1.4639 +    return d3_geo_lengthSum;
  1.4640 +  };
  1.4641 +  var d3_geo_lengthSum;
  1.4642 +  var d3_geo_length = {
  1.4643 +    sphere: d3_noop,
  1.4644 +    point: d3_noop,
  1.4645 +    lineStart: d3_geo_lengthLineStart,
  1.4646 +    lineEnd: d3_noop,
  1.4647 +    polygonStart: d3_noop,
  1.4648 +    polygonEnd: d3_noop
  1.4649 +  };
  1.4650 +  function d3_geo_lengthLineStart() {
  1.4651 +    var λ0, sinφ0, cosφ0;
  1.4652 +    d3_geo_length.point = function(λ, φ) {
  1.4653 +      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
  1.4654 +      d3_geo_length.point = nextPoint;
  1.4655 +    };
  1.4656 +    d3_geo_length.lineEnd = function() {
  1.4657 +      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
  1.4658 +    };
  1.4659 +    function nextPoint(λ, φ) {
  1.4660 +      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
  1.4661 +      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
  1.4662 +      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
  1.4663 +    }
  1.4664 +  }
  1.4665 +  function d3_geo_azimuthal(scale, angle) {
  1.4666 +    function azimuthal(λ, φ) {
  1.4667 +      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
  1.4668 +      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
  1.4669 +    }
  1.4670 +    azimuthal.invert = function(x, y) {
  1.4671 +      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
  1.4672 +      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
  1.4673 +    };
  1.4674 +    return azimuthal;
  1.4675 +  }
  1.4676 +  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
  1.4677 +    return Math.sqrt(2 / (1 + cosλcosφ));
  1.4678 +  }, function(ρ) {
  1.4679 +    return 2 * Math.asin(ρ / 2);
  1.4680 +  });
  1.4681 +  (d3.geo.azimuthalEqualArea = function() {
  1.4682 +    return d3_geo_projection(d3_geo_azimuthalEqualArea);
  1.4683 +  }).raw = d3_geo_azimuthalEqualArea;
  1.4684 +  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
  1.4685 +    var c = Math.acos(cosλcosφ);
  1.4686 +    return c && c / Math.sin(c);
  1.4687 +  }, d3_identity);
  1.4688 +  (d3.geo.azimuthalEquidistant = function() {
  1.4689 +    return d3_geo_projection(d3_geo_azimuthalEquidistant);
  1.4690 +  }).raw = d3_geo_azimuthalEquidistant;
  1.4691 +  function d3_geo_conicConformal(φ0, φ1) {
  1.4692 +    var cosφ0 = Math.cos(φ0), t = function(φ) {
  1.4693 +      return Math.tan(π / 4 + φ / 2);
  1.4694 +    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
  1.4695 +    if (!n) return d3_geo_mercator;
  1.4696 +    function forward(λ, φ) {
  1.4697 +      if (F > 0) {
  1.4698 +        if (φ < -halfπ + ε) φ = -halfπ + ε;
  1.4699 +      } else {
  1.4700 +        if (φ > halfπ - ε) φ = halfπ - ε;
  1.4701 +      }
  1.4702 +      var ρ = F / Math.pow(t(φ), n);
  1.4703 +      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
  1.4704 +    }
  1.4705 +    forward.invert = function(x, y) {
  1.4706 +      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
  1.4707 +      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
  1.4708 +    };
  1.4709 +    return forward;
  1.4710 +  }
  1.4711 +  (d3.geo.conicConformal = function() {
  1.4712 +    return d3_geo_conic(d3_geo_conicConformal);
  1.4713 +  }).raw = d3_geo_conicConformal;
  1.4714 +  function d3_geo_conicEquidistant(φ0, φ1) {
  1.4715 +    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
  1.4716 +    if (abs(n) < ε) return d3_geo_equirectangular;
  1.4717 +    function forward(λ, φ) {
  1.4718 +      var ρ = G - φ;
  1.4719 +      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
  1.4720 +    }
  1.4721 +    forward.invert = function(x, y) {
  1.4722 +      var ρ0_y = G - y;
  1.4723 +      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
  1.4724 +    };
  1.4725 +    return forward;
  1.4726 +  }
  1.4727 +  (d3.geo.conicEquidistant = function() {
  1.4728 +    return d3_geo_conic(d3_geo_conicEquidistant);
  1.4729 +  }).raw = d3_geo_conicEquidistant;
  1.4730 +  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
  1.4731 +    return 1 / cosλcosφ;
  1.4732 +  }, Math.atan);
  1.4733 +  (d3.geo.gnomonic = function() {
  1.4734 +    return d3_geo_projection(d3_geo_gnomonic);
  1.4735 +  }).raw = d3_geo_gnomonic;
  1.4736 +  function d3_geo_mercator(λ, φ) {
  1.4737 +    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
  1.4738 +  }
  1.4739 +  d3_geo_mercator.invert = function(x, y) {
  1.4740 +    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
  1.4741 +  };
  1.4742 +  function d3_geo_mercatorProjection(project) {
  1.4743 +    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
  1.4744 +    m.scale = function() {
  1.4745 +      var v = scale.apply(m, arguments);
  1.4746 +      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
  1.4747 +    };
  1.4748 +    m.translate = function() {
  1.4749 +      var v = translate.apply(m, arguments);
  1.4750 +      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
  1.4751 +    };
  1.4752 +    m.clipExtent = function(_) {
  1.4753 +      var v = clipExtent.apply(m, arguments);
  1.4754 +      if (v === m) {
  1.4755 +        if (clipAuto = _ == null) {
  1.4756 +          var k = π * scale(), t = translate();
  1.4757 +          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
  1.4758 +        }
  1.4759 +      } else if (clipAuto) {
  1.4760 +        v = null;
  1.4761 +      }
  1.4762 +      return v;
  1.4763 +    };
  1.4764 +    return m.clipExtent(null);
  1.4765 +  }
  1.4766 +  (d3.geo.mercator = function() {
  1.4767 +    return d3_geo_mercatorProjection(d3_geo_mercator);
  1.4768 +  }).raw = d3_geo_mercator;
  1.4769 +  var d3_geo_orthographic = d3_geo_azimuthal(function() {
  1.4770 +    return 1;
  1.4771 +  }, Math.asin);
  1.4772 +  (d3.geo.orthographic = function() {
  1.4773 +    return d3_geo_projection(d3_geo_orthographic);
  1.4774 +  }).raw = d3_geo_orthographic;
  1.4775 +  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
  1.4776 +    return 1 / (1 + cosλcosφ);
  1.4777 +  }, function(ρ) {
  1.4778 +    return 2 * Math.atan(ρ);
  1.4779 +  });
  1.4780 +  (d3.geo.stereographic = function() {
  1.4781 +    return d3_geo_projection(d3_geo_stereographic);
  1.4782 +  }).raw = d3_geo_stereographic;
  1.4783 +  function d3_geo_transverseMercator(λ, φ) {
  1.4784 +    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
  1.4785 +  }
  1.4786 +  d3_geo_transverseMercator.invert = function(x, y) {
  1.4787 +    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
  1.4788 +  };
  1.4789 +  (d3.geo.transverseMercator = function() {
  1.4790 +    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
  1.4791 +    projection.center = function(_) {
  1.4792 +      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
  1.4793 +    };
  1.4794 +    projection.rotate = function(_) {
  1.4795 +      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
  1.4796 +      [ _[0], _[1], _[2] - 90 ]);
  1.4797 +    };
  1.4798 +    return rotate([ 0, 0, 90 ]);
  1.4799 +  }).raw = d3_geo_transverseMercator;
  1.4800 +  d3.geom = {};
  1.4801 +  function d3_geom_pointX(d) {
  1.4802 +    return d[0];
  1.4803 +  }
  1.4804 +  function d3_geom_pointY(d) {
  1.4805 +    return d[1];
  1.4806 +  }
  1.4807 +  d3.geom.hull = function(vertices) {
  1.4808 +    var x = d3_geom_pointX, y = d3_geom_pointY;
  1.4809 +    if (arguments.length) return hull(vertices);
  1.4810 +    function hull(data) {
  1.4811 +      if (data.length < 3) return [];
  1.4812 +      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
  1.4813 +      for (i = 0; i < n; i++) {
  1.4814 +        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
  1.4815 +      }
  1.4816 +      points.sort(d3_geom_hullOrder);
  1.4817 +      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
  1.4818 +      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
  1.4819 +      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
  1.4820 +      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
  1.4821 +      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
  1.4822 +      return polygon;
  1.4823 +    }
  1.4824 +    hull.x = function(_) {
  1.4825 +      return arguments.length ? (x = _, hull) : x;
  1.4826 +    };
  1.4827 +    hull.y = function(_) {
  1.4828 +      return arguments.length ? (y = _, hull) : y;
  1.4829 +    };
  1.4830 +    return hull;
  1.4831 +  };
  1.4832 +  function d3_geom_hullUpper(points) {
  1.4833 +    var n = points.length, hull = [ 0, 1 ], hs = 2;
  1.4834 +    for (var i = 2; i < n; i++) {
  1.4835 +      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
  1.4836 +      hull[hs++] = i;
  1.4837 +    }
  1.4838 +    return hull.slice(0, hs);
  1.4839 +  }
  1.4840 +  function d3_geom_hullOrder(a, b) {
  1.4841 +    return a[0] - b[0] || a[1] - b[1];
  1.4842 +  }
  1.4843 +  d3.geom.polygon = function(coordinates) {
  1.4844 +    d3_subclass(coordinates, d3_geom_polygonPrototype);
  1.4845 +    return coordinates;
  1.4846 +  };
  1.4847 +  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
  1.4848 +  d3_geom_polygonPrototype.area = function() {
  1.4849 +    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
  1.4850 +    while (++i < n) {
  1.4851 +      a = b;
  1.4852 +      b = this[i];
  1.4853 +      area += a[1] * b[0] - a[0] * b[1];
  1.4854 +    }
  1.4855 +    return area * .5;
  1.4856 +  };
  1.4857 +  d3_geom_polygonPrototype.centroid = function(k) {
  1.4858 +    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
  1.4859 +    if (!arguments.length) k = -1 / (6 * this.area());
  1.4860 +    while (++i < n) {
  1.4861 +      a = b;
  1.4862 +      b = this[i];
  1.4863 +      c = a[0] * b[1] - b[0] * a[1];
  1.4864 +      x += (a[0] + b[0]) * c;
  1.4865 +      y += (a[1] + b[1]) * c;
  1.4866 +    }
  1.4867 +    return [ x * k, y * k ];
  1.4868 +  };
  1.4869 +  d3_geom_polygonPrototype.clip = function(subject) {
  1.4870 +    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
  1.4871 +    while (++i < n) {
  1.4872 +      input = subject.slice();
  1.4873 +      subject.length = 0;
  1.4874 +      b = this[i];
  1.4875 +      c = input[(m = input.length - closed) - 1];
  1.4876 +      j = -1;
  1.4877 +      while (++j < m) {
  1.4878 +        d = input[j];
  1.4879 +        if (d3_geom_polygonInside(d, a, b)) {
  1.4880 +          if (!d3_geom_polygonInside(c, a, b)) {
  1.4881 +            subject.push(d3_geom_polygonIntersect(c, d, a, b));
  1.4882 +          }
  1.4883 +          subject.push(d);
  1.4884 +        } else if (d3_geom_polygonInside(c, a, b)) {
  1.4885 +          subject.push(d3_geom_polygonIntersect(c, d, a, b));
  1.4886 +        }
  1.4887 +        c = d;
  1.4888 +      }
  1.4889 +      if (closed) subject.push(subject[0]);
  1.4890 +      a = b;
  1.4891 +    }
  1.4892 +    return subject;
  1.4893 +  };
  1.4894 +  function d3_geom_polygonInside(p, a, b) {
  1.4895 +    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
  1.4896 +  }
  1.4897 +  function d3_geom_polygonIntersect(c, d, a, b) {
  1.4898 +    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
  1.4899 +    return [ x1 + ua * x21, y1 + ua * y21 ];
  1.4900 +  }
  1.4901 +  function d3_geom_polygonClosed(coordinates) {
  1.4902 +    var a = coordinates[0], b = coordinates[coordinates.length - 1];
  1.4903 +    return !(a[0] - b[0] || a[1] - b[1]);
  1.4904 +  }
  1.4905 +  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
  1.4906 +  function d3_geom_voronoiBeach() {
  1.4907 +    d3_geom_voronoiRedBlackNode(this);
  1.4908 +    this.edge = this.site = this.circle = null;
  1.4909 +  }
  1.4910 +  function d3_geom_voronoiCreateBeach(site) {
  1.4911 +    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
  1.4912 +    beach.site = site;
  1.4913 +    return beach;
  1.4914 +  }
  1.4915 +  function d3_geom_voronoiDetachBeach(beach) {
  1.4916 +    d3_geom_voronoiDetachCircle(beach);
  1.4917 +    d3_geom_voronoiBeaches.remove(beach);
  1.4918 +    d3_geom_voronoiBeachPool.push(beach);
  1.4919 +    d3_geom_voronoiRedBlackNode(beach);
  1.4920 +  }
  1.4921 +  function d3_geom_voronoiRemoveBeach(beach) {
  1.4922 +    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
  1.4923 +      x: x,
  1.4924 +      y: y
  1.4925 +    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
  1.4926 +    d3_geom_voronoiDetachBeach(beach);
  1.4927 +    var lArc = previous;
  1.4928 +    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
  1.4929 +      previous = lArc.P;
  1.4930 +      disappearing.unshift(lArc);
  1.4931 +      d3_geom_voronoiDetachBeach(lArc);
  1.4932 +      lArc = previous;
  1.4933 +    }
  1.4934 +    disappearing.unshift(lArc);
  1.4935 +    d3_geom_voronoiDetachCircle(lArc);
  1.4936 +    var rArc = next;
  1.4937 +    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
  1.4938 +      next = rArc.N;
  1.4939 +      disappearing.push(rArc);
  1.4940 +      d3_geom_voronoiDetachBeach(rArc);
  1.4941 +      rArc = next;
  1.4942 +    }
  1.4943 +    disappearing.push(rArc);
  1.4944 +    d3_geom_voronoiDetachCircle(rArc);
  1.4945 +    var nArcs = disappearing.length, iArc;
  1.4946 +    for (iArc = 1; iArc < nArcs; ++iArc) {
  1.4947 +      rArc = disappearing[iArc];
  1.4948 +      lArc = disappearing[iArc - 1];
  1.4949 +      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
  1.4950 +    }
  1.4951 +    lArc = disappearing[0];
  1.4952 +    rArc = disappearing[nArcs - 1];
  1.4953 +    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
  1.4954 +    d3_geom_voronoiAttachCircle(lArc);
  1.4955 +    d3_geom_voronoiAttachCircle(rArc);
  1.4956 +  }
  1.4957 +  function d3_geom_voronoiAddBeach(site) {
  1.4958 +    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
  1.4959 +    while (node) {
  1.4960 +      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
  1.4961 +      if (dxl > ε) node = node.L; else {
  1.4962 +        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
  1.4963 +        if (dxr > ε) {
  1.4964 +          if (!node.R) {
  1.4965 +            lArc = node;
  1.4966 +            break;
  1.4967 +          }
  1.4968 +          node = node.R;
  1.4969 +        } else {
  1.4970 +          if (dxl > -ε) {
  1.4971 +            lArc = node.P;
  1.4972 +            rArc = node;
  1.4973 +          } else if (dxr > -ε) {
  1.4974 +            lArc = node;
  1.4975 +            rArc = node.N;
  1.4976 +          } else {
  1.4977 +            lArc = rArc = node;
  1.4978 +          }
  1.4979 +          break;
  1.4980 +        }
  1.4981 +      }
  1.4982 +    }
  1.4983 +    var newArc = d3_geom_voronoiCreateBeach(site);
  1.4984 +    d3_geom_voronoiBeaches.insert(lArc, newArc);
  1.4985 +    if (!lArc && !rArc) return;
  1.4986 +    if (lArc === rArc) {
  1.4987 +      d3_geom_voronoiDetachCircle(lArc);
  1.4988 +      rArc = d3_geom_voronoiCreateBeach(lArc.site);
  1.4989 +      d3_geom_voronoiBeaches.insert(newArc, rArc);
  1.4990 +      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
  1.4991 +      d3_geom_voronoiAttachCircle(lArc);
  1.4992 +      d3_geom_voronoiAttachCircle(rArc);
  1.4993 +      return;
  1.4994 +    }
  1.4995 +    if (!rArc) {
  1.4996 +      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
  1.4997 +      return;
  1.4998 +    }
  1.4999 +    d3_geom_voronoiDetachCircle(lArc);
  1.5000 +    d3_geom_voronoiDetachCircle(rArc);
  1.5001 +    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
  1.5002 +      x: (cy * hb - by * hc) / d + ax,
  1.5003 +      y: (bx * hc - cx * hb) / d + ay
  1.5004 +    };
  1.5005 +    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
  1.5006 +    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
  1.5007 +    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
  1.5008 +    d3_geom_voronoiAttachCircle(lArc);
  1.5009 +    d3_geom_voronoiAttachCircle(rArc);
  1.5010 +  }
  1.5011 +  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
  1.5012 +    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
  1.5013 +    if (!pby2) return rfocx;
  1.5014 +    var lArc = arc.P;
  1.5015 +    if (!lArc) return -Infinity;
  1.5016 +    site = lArc.site;
  1.5017 +    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
  1.5018 +    if (!plby2) return lfocx;
  1.5019 +    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
  1.5020 +    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
  1.5021 +    return (rfocx + lfocx) / 2;
  1.5022 +  }
  1.5023 +  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
  1.5024 +    var rArc = arc.N;
  1.5025 +    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
  1.5026 +    var site = arc.site;
  1.5027 +    return site.y === directrix ? site.x : Infinity;
  1.5028 +  }
  1.5029 +  function d3_geom_voronoiCell(site) {
  1.5030 +    this.site = site;
  1.5031 +    this.edges = [];
  1.5032 +  }
  1.5033 +  d3_geom_voronoiCell.prototype.prepare = function() {
  1.5034 +    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
  1.5035 +    while (iHalfEdge--) {
  1.5036 +      edge = halfEdges[iHalfEdge].edge;
  1.5037 +      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
  1.5038 +    }
  1.5039 +    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
  1.5040 +    return halfEdges.length;
  1.5041 +  };
  1.5042 +  function d3_geom_voronoiCloseCells(extent) {
  1.5043 +    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
  1.5044 +    while (iCell--) {
  1.5045 +      cell = cells[iCell];
  1.5046 +      if (!cell || !cell.prepare()) continue;
  1.5047 +      halfEdges = cell.edges;
  1.5048 +      nHalfEdges = halfEdges.length;
  1.5049 +      iHalfEdge = 0;
  1.5050 +      while (iHalfEdge < nHalfEdges) {
  1.5051 +        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
  1.5052 +        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
  1.5053 +        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
  1.5054 +          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
  1.5055 +            x: x0,
  1.5056 +            y: abs(x2 - x0) < ε ? y2 : y1
  1.5057 +          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
  1.5058 +            x: abs(y2 - y1) < ε ? x2 : x1,
  1.5059 +            y: y1
  1.5060 +          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
  1.5061 +            x: x1,
  1.5062 +            y: abs(x2 - x1) < ε ? y2 : y0
  1.5063 +          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
  1.5064 +            x: abs(y2 - y0) < ε ? x2 : x0,
  1.5065 +            y: y0
  1.5066 +          } : null), cell.site, null));
  1.5067 +          ++nHalfEdges;
  1.5068 +        }
  1.5069 +      }
  1.5070 +    }
  1.5071 +  }
  1.5072 +  function d3_geom_voronoiHalfEdgeOrder(a, b) {
  1.5073 +    return b.angle - a.angle;
  1.5074 +  }
  1.5075 +  function d3_geom_voronoiCircle() {
  1.5076 +    d3_geom_voronoiRedBlackNode(this);
  1.5077 +    this.x = this.y = this.arc = this.site = this.cy = null;
  1.5078 +  }
  1.5079 +  function d3_geom_voronoiAttachCircle(arc) {
  1.5080 +    var lArc = arc.P, rArc = arc.N;
  1.5081 +    if (!lArc || !rArc) return;
  1.5082 +    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
  1.5083 +    if (lSite === rSite) return;
  1.5084 +    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
  1.5085 +    var d = 2 * (ax * cy - ay * cx);
  1.5086 +    if (d >= -ε2) return;
  1.5087 +    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
  1.5088 +    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
  1.5089 +    circle.arc = arc;
  1.5090 +    circle.site = cSite;
  1.5091 +    circle.x = x + bx;
  1.5092 +    circle.y = cy + Math.sqrt(x * x + y * y);
  1.5093 +    circle.cy = cy;
  1.5094 +    arc.circle = circle;
  1.5095 +    var before = null, node = d3_geom_voronoiCircles._;
  1.5096 +    while (node) {
  1.5097 +      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
  1.5098 +        if (node.L) node = node.L; else {
  1.5099 +          before = node.P;
  1.5100 +          break;
  1.5101 +        }
  1.5102 +      } else {
  1.5103 +        if (node.R) node = node.R; else {
  1.5104 +          before = node;
  1.5105 +          break;
  1.5106 +        }
  1.5107 +      }
  1.5108 +    }
  1.5109 +    d3_geom_voronoiCircles.insert(before, circle);
  1.5110 +    if (!before) d3_geom_voronoiFirstCircle = circle;
  1.5111 +  }
  1.5112 +  function d3_geom_voronoiDetachCircle(arc) {
  1.5113 +    var circle = arc.circle;
  1.5114 +    if (circle) {
  1.5115 +      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
  1.5116 +      d3_geom_voronoiCircles.remove(circle);
  1.5117 +      d3_geom_voronoiCirclePool.push(circle);
  1.5118 +      d3_geom_voronoiRedBlackNode(circle);
  1.5119 +      arc.circle = null;
  1.5120 +    }
  1.5121 +  }
  1.5122 +  function d3_geom_voronoiClipEdges(extent) {
  1.5123 +    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
  1.5124 +    while (i--) {
  1.5125 +      e = edges[i];
  1.5126 +      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
  1.5127 +        e.a = e.b = null;
  1.5128 +        edges.splice(i, 1);
  1.5129 +      }
  1.5130 +    }
  1.5131 +  }
  1.5132 +  function d3_geom_voronoiConnectEdge(edge, extent) {
  1.5133 +    var vb = edge.b;
  1.5134 +    if (vb) return true;
  1.5135 +    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
  1.5136 +    if (ry === ly) {
  1.5137 +      if (fx < x0 || fx >= x1) return;
  1.5138 +      if (lx > rx) {
  1.5139 +        if (!va) va = {
  1.5140 +          x: fx,
  1.5141 +          y: y0
  1.5142 +        }; else if (va.y >= y1) return;
  1.5143 +        vb = {
  1.5144 +          x: fx,
  1.5145 +          y: y1
  1.5146 +        };
  1.5147 +      } else {
  1.5148 +        if (!va) va = {
  1.5149 +          x: fx,
  1.5150 +          y: y1
  1.5151 +        }; else if (va.y < y0) return;
  1.5152 +        vb = {
  1.5153 +          x: fx,
  1.5154 +          y: y0
  1.5155 +        };
  1.5156 +      }
  1.5157 +    } else {
  1.5158 +      fm = (lx - rx) / (ry - ly);
  1.5159 +      fb = fy - fm * fx;
  1.5160 +      if (fm < -1 || fm > 1) {
  1.5161 +        if (lx > rx) {
  1.5162 +          if (!va) va = {
  1.5163 +            x: (y0 - fb) / fm,
  1.5164 +            y: y0
  1.5165 +          }; else if (va.y >= y1) return;
  1.5166 +          vb = {
  1.5167 +            x: (y1 - fb) / fm,
  1.5168 +            y: y1
  1.5169 +          };
  1.5170 +        } else {
  1.5171 +          if (!va) va = {
  1.5172 +            x: (y1 - fb) / fm,
  1.5173 +            y: y1
  1.5174 +          }; else if (va.y < y0) return;
  1.5175 +          vb = {
  1.5176 +            x: (y0 - fb) / fm,
  1.5177 +            y: y0
  1.5178 +          };
  1.5179 +        }
  1.5180 +      } else {
  1.5181 +        if (ly < ry) {
  1.5182 +          if (!va) va = {
  1.5183 +            x: x0,
  1.5184 +            y: fm * x0 + fb
  1.5185 +          }; else if (va.x >= x1) return;
  1.5186 +          vb = {
  1.5187 +            x: x1,
  1.5188 +            y: fm * x1 + fb
  1.5189 +          };
  1.5190 +        } else {
  1.5191 +          if (!va) va = {
  1.5192 +            x: x1,
  1.5193 +            y: fm * x1 + fb
  1.5194 +          }; else if (va.x < x0) return;
  1.5195 +          vb = {
  1.5196 +            x: x0,
  1.5197 +            y: fm * x0 + fb
  1.5198 +          };
  1.5199 +        }
  1.5200 +      }
  1.5201 +    }
  1.5202 +    edge.a = va;
  1.5203 +    edge.b = vb;
  1.5204 +    return true;
  1.5205 +  }
  1.5206 +  function d3_geom_voronoiEdge(lSite, rSite) {
  1.5207 +    this.l = lSite;
  1.5208 +    this.r = rSite;
  1.5209 +    this.a = this.b = null;
  1.5210 +  }
  1.5211 +  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
  1.5212 +    var edge = new d3_geom_voronoiEdge(lSite, rSite);
  1.5213 +    d3_geom_voronoiEdges.push(edge);
  1.5214 +    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
  1.5215 +    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
  1.5216 +    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
  1.5217 +    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
  1.5218 +    return edge;
  1.5219 +  }
  1.5220 +  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
  1.5221 +    var edge = new d3_geom_voronoiEdge(lSite, null);
  1.5222 +    edge.a = va;
  1.5223 +    edge.b = vb;
  1.5224 +    d3_geom_voronoiEdges.push(edge);
  1.5225 +    return edge;
  1.5226 +  }
  1.5227 +  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
  1.5228 +    if (!edge.a && !edge.b) {
  1.5229 +      edge.a = vertex;
  1.5230 +      edge.l = lSite;
  1.5231 +      edge.r = rSite;
  1.5232 +    } else if (edge.l === rSite) {
  1.5233 +      edge.b = vertex;
  1.5234 +    } else {
  1.5235 +      edge.a = vertex;
  1.5236 +    }
  1.5237 +  }
  1.5238 +  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
  1.5239 +    var va = edge.a, vb = edge.b;
  1.5240 +    this.edge = edge;
  1.5241 +    this.site = lSite;
  1.5242 +    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
  1.5243 +  }
  1.5244 +  d3_geom_voronoiHalfEdge.prototype = {
  1.5245 +    start: function() {
  1.5246 +      return this.edge.l === this.site ? this.edge.a : this.edge.b;
  1.5247 +    },
  1.5248 +    end: function() {
  1.5249 +      return this.edge.l === this.site ? this.edge.b : this.edge.a;
  1.5250 +    }
  1.5251 +  };
  1.5252 +  function d3_geom_voronoiRedBlackTree() {
  1.5253 +    this._ = null;
  1.5254 +  }
  1.5255 +  function d3_geom_voronoiRedBlackNode(node) {
  1.5256 +    node.U = node.C = node.L = node.R = node.P = node.N = null;
  1.5257 +  }
  1.5258 +  d3_geom_voronoiRedBlackTree.prototype = {
  1.5259 +    insert: function(after, node) {
  1.5260 +      var parent, grandpa, uncle;
  1.5261 +      if (after) {
  1.5262 +        node.P = after;
  1.5263 +        node.N = after.N;
  1.5264 +        if (after.N) after.N.P = node;
  1.5265 +        after.N = node;
  1.5266 +        if (after.R) {
  1.5267 +          after = after.R;
  1.5268 +          while (after.L) after = after.L;
  1.5269 +          after.L = node;
  1.5270 +        } else {
  1.5271 +          after.R = node;
  1.5272 +        }
  1.5273 +        parent = after;
  1.5274 +      } else if (this._) {
  1.5275 +        after = d3_geom_voronoiRedBlackFirst(this._);
  1.5276 +        node.P = null;
  1.5277 +        node.N = after;
  1.5278 +        after.P = after.L = node;
  1.5279 +        parent = after;
  1.5280 +      } else {
  1.5281 +        node.P = node.N = null;
  1.5282 +        this._ = node;
  1.5283 +        parent = null;
  1.5284 +      }
  1.5285 +      node.L = node.R = null;
  1.5286 +      node.U = parent;
  1.5287 +      node.C = true;
  1.5288 +      after = node;
  1.5289 +      while (parent && parent.C) {
  1.5290 +        grandpa = parent.U;
  1.5291 +        if (parent === grandpa.L) {
  1.5292 +          uncle = grandpa.R;
  1.5293 +          if (uncle && uncle.C) {
  1.5294 +            parent.C = uncle.C = false;
  1.5295 +            grandpa.C = true;
  1.5296 +            after = grandpa;
  1.5297 +          } else {
  1.5298 +            if (after === parent.R) {
  1.5299 +              d3_geom_voronoiRedBlackRotateLeft(this, parent);
  1.5300 +              after = parent;
  1.5301 +              parent = after.U;
  1.5302 +            }
  1.5303 +            parent.C = false;
  1.5304 +            grandpa.C = true;
  1.5305 +            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
  1.5306 +          }
  1.5307 +        } else {
  1.5308 +          uncle = grandpa.L;
  1.5309 +          if (uncle && uncle.C) {
  1.5310 +            parent.C = uncle.C = false;
  1.5311 +            grandpa.C = true;
  1.5312 +            after = grandpa;
  1.5313 +          } else {
  1.5314 +            if (after === parent.L) {
  1.5315 +              d3_geom_voronoiRedBlackRotateRight(this, parent);
  1.5316 +              after = parent;
  1.5317 +              parent = after.U;
  1.5318 +            }
  1.5319 +            parent.C = false;
  1.5320 +            grandpa.C = true;
  1.5321 +            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
  1.5322 +          }
  1.5323 +        }
  1.5324 +        parent = after.U;
  1.5325 +      }
  1.5326 +      this._.C = false;
  1.5327 +    },
  1.5328 +    remove: function(node) {
  1.5329 +      if (node.N) node.N.P = node.P;
  1.5330 +      if (node.P) node.P.N = node.N;
  1.5331 +      node.N = node.P = null;
  1.5332 +      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
  1.5333 +      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
  1.5334 +      if (parent) {
  1.5335 +        if (parent.L === node) parent.L = next; else parent.R = next;
  1.5336 +      } else {
  1.5337 +        this._ = next;
  1.5338 +      }
  1.5339 +      if (left && right) {
  1.5340 +        red = next.C;
  1.5341 +        next.C = node.C;
  1.5342 +        next.L = left;
  1.5343 +        left.U = next;
  1.5344 +        if (next !== right) {
  1.5345 +          parent = next.U;
  1.5346 +          next.U = node.U;
  1.5347 +          node = next.R;
  1.5348 +          parent.L = node;
  1.5349 +          next.R = right;
  1.5350 +          right.U = next;
  1.5351 +        } else {
  1.5352 +          next.U = parent;
  1.5353 +          parent = next;
  1.5354 +          node = next.R;
  1.5355 +        }
  1.5356 +      } else {
  1.5357 +        red = node.C;
  1.5358 +        node = next;
  1.5359 +      }
  1.5360 +      if (node) node.U = parent;
  1.5361 +      if (red) return;
  1.5362 +      if (node && node.C) {
  1.5363 +        node.C = false;
  1.5364 +        return;
  1.5365 +      }
  1.5366 +      do {
  1.5367 +        if (node === this._) break;
  1.5368 +        if (node === parent.L) {
  1.5369 +          sibling = parent.R;
  1.5370 +          if (sibling.C) {
  1.5371 +            sibling.C = false;
  1.5372 +            parent.C = true;
  1.5373 +            d3_geom_voronoiRedBlackRotateLeft(this, parent);
  1.5374 +            sibling = parent.R;
  1.5375 +          }
  1.5376 +          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
  1.5377 +            if (!sibling.R || !sibling.R.C) {
  1.5378 +              sibling.L.C = false;
  1.5379 +              sibling.C = true;
  1.5380 +              d3_geom_voronoiRedBlackRotateRight(this, sibling);
  1.5381 +              sibling = parent.R;
  1.5382 +            }
  1.5383 +            sibling.C = parent.C;
  1.5384 +            parent.C = sibling.R.C = false;
  1.5385 +            d3_geom_voronoiRedBlackRotateLeft(this, parent);
  1.5386 +            node = this._;
  1.5387 +            break;
  1.5388 +          }
  1.5389 +        } else {
  1.5390 +          sibling = parent.L;
  1.5391 +          if (sibling.C) {
  1.5392 +            sibling.C = false;
  1.5393 +            parent.C = true;
  1.5394 +            d3_geom_voronoiRedBlackRotateRight(this, parent);
  1.5395 +            sibling = parent.L;
  1.5396 +          }
  1.5397 +          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
  1.5398 +            if (!sibling.L || !sibling.L.C) {
  1.5399 +              sibling.R.C = false;
  1.5400 +              sibling.C = true;
  1.5401 +              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
  1.5402 +              sibling = parent.L;
  1.5403 +            }
  1.5404 +            sibling.C = parent.C;
  1.5405 +            parent.C = sibling.L.C = false;
  1.5406 +            d3_geom_voronoiRedBlackRotateRight(this, parent);
  1.5407 +            node = this._;
  1.5408 +            break;
  1.5409 +          }
  1.5410 +        }
  1.5411 +        sibling.C = true;
  1.5412 +        node = parent;
  1.5413 +        parent = parent.U;
  1.5414 +      } while (!node.C);
  1.5415 +      if (node) node.C = false;
  1.5416 +    }
  1.5417 +  };
  1.5418 +  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
  1.5419 +    var p = node, q = node.R, parent = p.U;
  1.5420 +    if (parent) {
  1.5421 +      if (parent.L === p) parent.L = q; else parent.R = q;
  1.5422 +    } else {
  1.5423 +      tree._ = q;
  1.5424 +    }
  1.5425 +    q.U = parent;
  1.5426 +    p.U = q;
  1.5427 +    p.R = q.L;
  1.5428 +    if (p.R) p.R.U = p;
  1.5429 +    q.L = p;
  1.5430 +  }
  1.5431 +  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
  1.5432 +    var p = node, q = node.L, parent = p.U;
  1.5433 +    if (parent) {
  1.5434 +      if (parent.L === p) parent.L = q; else parent.R = q;
  1.5435 +    } else {
  1.5436 +      tree._ = q;
  1.5437 +    }
  1.5438 +    q.U = parent;
  1.5439 +    p.U = q;
  1.5440 +    p.L = q.R;
  1.5441 +    if (p.L) p.L.U = p;
  1.5442 +    q.R = p;
  1.5443 +  }
  1.5444 +  function d3_geom_voronoiRedBlackFirst(node) {
  1.5445 +    while (node.L) node = node.L;
  1.5446 +    return node;
  1.5447 +  }
  1.5448 +  function d3_geom_voronoi(sites, bbox) {
  1.5449 +    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
  1.5450 +    d3_geom_voronoiEdges = [];
  1.5451 +    d3_geom_voronoiCells = new Array(sites.length);
  1.5452 +    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
  1.5453 +    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
  1.5454 +    while (true) {
  1.5455 +      circle = d3_geom_voronoiFirstCircle;
  1.5456 +      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
  1.5457 +        if (site.x !== x0 || site.y !== y0) {
  1.5458 +          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
  1.5459 +          d3_geom_voronoiAddBeach(site);
  1.5460 +          x0 = site.x, y0 = site.y;
  1.5461 +        }
  1.5462 +        site = sites.pop();
  1.5463 +      } else if (circle) {
  1.5464 +        d3_geom_voronoiRemoveBeach(circle.arc);
  1.5465 +      } else {
  1.5466 +        break;
  1.5467 +      }
  1.5468 +    }
  1.5469 +    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
  1.5470 +    var diagram = {
  1.5471 +      cells: d3_geom_voronoiCells,
  1.5472 +      edges: d3_geom_voronoiEdges
  1.5473 +    };
  1.5474 +    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
  1.5475 +    return diagram;
  1.5476 +  }
  1.5477 +  function d3_geom_voronoiVertexOrder(a, b) {
  1.5478 +    return b.y - a.y || b.x - a.x;
  1.5479 +  }
  1.5480 +  d3.geom.voronoi = function(points) {
  1.5481 +    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
  1.5482 +    if (points) return voronoi(points);
  1.5483 +    function voronoi(data) {
  1.5484 +      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
  1.5485 +      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
  1.5486 +        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
  1.5487 +          var s = e.start();
  1.5488 +          return [ s.x, s.y ];
  1.5489 +        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
  1.5490 +        polygon.point = data[i];
  1.5491 +      });
  1.5492 +      return polygons;
  1.5493 +    }
  1.5494 +    function sites(data) {
  1.5495 +      return data.map(function(d, i) {
  1.5496 +        return {
  1.5497 +          x: Math.round(fx(d, i) / ε) * ε,
  1.5498 +          y: Math.round(fy(d, i) / ε) * ε,
  1.5499 +          i: i
  1.5500 +        };
  1.5501 +      });
  1.5502 +    }
  1.5503 +    voronoi.links = function(data) {
  1.5504 +      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
  1.5505 +        return edge.l && edge.r;
  1.5506 +      }).map(function(edge) {
  1.5507 +        return {
  1.5508 +          source: data[edge.l.i],
  1.5509 +          target: data[edge.r.i]
  1.5510 +        };
  1.5511 +      });
  1.5512 +    };
  1.5513 +    voronoi.triangles = function(data) {
  1.5514 +      var triangles = [];
  1.5515 +      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
  1.5516 +        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
  1.5517 +        while (++j < m) {
  1.5518 +          e0 = e1;
  1.5519 +          s0 = s1;
  1.5520 +          e1 = edges[j].edge;
  1.5521 +          s1 = e1.l === site ? e1.r : e1.l;
  1.5522 +          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
  1.5523 +            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
  1.5524 +          }
  1.5525 +        }
  1.5526 +      });
  1.5527 +      return triangles;
  1.5528 +    };
  1.5529 +    voronoi.x = function(_) {
  1.5530 +      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
  1.5531 +    };
  1.5532 +    voronoi.y = function(_) {
  1.5533 +      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
  1.5534 +    };
  1.5535 +    voronoi.clipExtent = function(_) {
  1.5536 +      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
  1.5537 +      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
  1.5538 +      return voronoi;
  1.5539 +    };
  1.5540 +    voronoi.size = function(_) {
  1.5541 +      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
  1.5542 +      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
  1.5543 +    };
  1.5544 +    return voronoi;
  1.5545 +  };
  1.5546 +  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
  1.5547 +  function d3_geom_voronoiTriangleArea(a, b, c) {
  1.5548 +    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
  1.5549 +  }
  1.5550 +  d3.geom.delaunay = function(vertices) {
  1.5551 +    return d3.geom.voronoi().triangles(vertices);
  1.5552 +  };
  1.5553 +  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
  1.5554 +    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
  1.5555 +    if (compat = arguments.length) {
  1.5556 +      x = d3_geom_quadtreeCompatX;
  1.5557 +      y = d3_geom_quadtreeCompatY;
  1.5558 +      if (compat === 3) {
  1.5559 +        y2 = y1;
  1.5560 +        x2 = x1;
  1.5561 +        y1 = x1 = 0;
  1.5562 +      }
  1.5563 +      return quadtree(points);
  1.5564 +    }
  1.5565 +    function quadtree(data) {
  1.5566 +      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
  1.5567 +      if (x1 != null) {
  1.5568 +        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
  1.5569 +      } else {
  1.5570 +        x2_ = y2_ = -(x1_ = y1_ = Infinity);
  1.5571 +        xs = [], ys = [];
  1.5572 +        n = data.length;
  1.5573 +        if (compat) for (i = 0; i < n; ++i) {
  1.5574 +          d = data[i];
  1.5575 +          if (d.x < x1_) x1_ = d.x;
  1.5576 +          if (d.y < y1_) y1_ = d.y;
  1.5577 +          if (d.x > x2_) x2_ = d.x;
  1.5578 +          if (d.y > y2_) y2_ = d.y;
  1.5579 +          xs.push(d.x);
  1.5580 +          ys.push(d.y);
  1.5581 +        } else for (i = 0; i < n; ++i) {
  1.5582 +          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
  1.5583 +          if (x_ < x1_) x1_ = x_;
  1.5584 +          if (y_ < y1_) y1_ = y_;
  1.5585 +          if (x_ > x2_) x2_ = x_;
  1.5586 +          if (y_ > y2_) y2_ = y_;
  1.5587 +          xs.push(x_);
  1.5588 +          ys.push(y_);
  1.5589 +        }
  1.5590 +      }
  1.5591 +      var dx = x2_ - x1_, dy = y2_ - y1_;
  1.5592 +      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
  1.5593 +      function insert(n, d, x, y, x1, y1, x2, y2) {
  1.5594 +        if (isNaN(x) || isNaN(y)) return;
  1.5595 +        if (n.leaf) {
  1.5596 +          var nx = n.x, ny = n.y;
  1.5597 +          if (nx != null) {
  1.5598 +            if (abs(nx - x) + abs(ny - y) < .01) {
  1.5599 +              insertChild(n, d, x, y, x1, y1, x2, y2);
  1.5600 +            } else {
  1.5601 +              var nPoint = n.point;
  1.5602 +              n.x = n.y = n.point = null;
  1.5603 +              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
  1.5604 +              insertChild(n, d, x, y, x1, y1, x2, y2);
  1.5605 +            }
  1.5606 +          } else {
  1.5607 +            n.x = x, n.y = y, n.point = d;
  1.5608 +          }
  1.5609 +        } else {
  1.5610 +          insertChild(n, d, x, y, x1, y1, x2, y2);
  1.5611 +        }
  1.5612 +      }
  1.5613 +      function insertChild(n, d, x, y, x1, y1, x2, y2) {
  1.5614 +        var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right;
  1.5615 +        n.leaf = false;
  1.5616 +        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
  1.5617 +        if (right) x1 = xm; else x2 = xm;
  1.5618 +        if (below) y1 = ym; else y2 = ym;
  1.5619 +        insert(n, d, x, y, x1, y1, x2, y2);
  1.5620 +      }
  1.5621 +      var root = d3_geom_quadtreeNode();
  1.5622 +      root.add = function(d) {
  1.5623 +        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
  1.5624 +      };
  1.5625 +      root.visit = function(f) {
  1.5626 +        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
  1.5627 +      };
  1.5628 +      root.find = function(point) {
  1.5629 +        return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_);
  1.5630 +      };
  1.5631 +      i = -1;
  1.5632 +      if (x1 == null) {
  1.5633 +        while (++i < n) {
  1.5634 +          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
  1.5635 +        }
  1.5636 +        --i;
  1.5637 +      } else data.forEach(root.add);
  1.5638 +      xs = ys = data = d = null;
  1.5639 +      return root;
  1.5640 +    }
  1.5641 +    quadtree.x = function(_) {
  1.5642 +      return arguments.length ? (x = _, quadtree) : x;
  1.5643 +    };
  1.5644 +    quadtree.y = function(_) {
  1.5645 +      return arguments.length ? (y = _, quadtree) : y;
  1.5646 +    };
  1.5647 +    quadtree.extent = function(_) {
  1.5648 +      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
  1.5649 +      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
  1.5650 +      y2 = +_[1][1];
  1.5651 +      return quadtree;
  1.5652 +    };
  1.5653 +    quadtree.size = function(_) {
  1.5654 +      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
  1.5655 +      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
  1.5656 +      return quadtree;
  1.5657 +    };
  1.5658 +    return quadtree;
  1.5659 +  };
  1.5660 +  function d3_geom_quadtreeCompatX(d) {
  1.5661 +    return d.x;
  1.5662 +  }
  1.5663 +  function d3_geom_quadtreeCompatY(d) {
  1.5664 +    return d.y;
  1.5665 +  }
  1.5666 +  function d3_geom_quadtreeNode() {
  1.5667 +    return {
  1.5668 +      leaf: true,
  1.5669 +      nodes: [],
  1.5670 +      point: null,
  1.5671 +      x: null,
  1.5672 +      y: null
  1.5673 +    };
  1.5674 +  }
  1.5675 +  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
  1.5676 +    if (!f(node, x1, y1, x2, y2)) {
  1.5677 +      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
  1.5678 +      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
  1.5679 +      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
  1.5680 +      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
  1.5681 +      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
  1.5682 +    }
  1.5683 +  }
  1.5684 +  function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) {
  1.5685 +    var minDistance2 = Infinity, closestPoint;
  1.5686 +    (function find(node, x1, y1, x2, y2) {
  1.5687 +      if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
  1.5688 +      if (point = node.point) {
  1.5689 +        var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy;
  1.5690 +        if (distance2 < minDistance2) {
  1.5691 +          var distance = Math.sqrt(minDistance2 = distance2);
  1.5692 +          x0 = x - distance, y0 = y - distance;
  1.5693 +          x3 = x + distance, y3 = y + distance;
  1.5694 +          closestPoint = point;
  1.5695 +        }
  1.5696 +      }
  1.5697 +      var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym;
  1.5698 +      for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
  1.5699 +        if (node = children[i & 3]) switch (i & 3) {
  1.5700 +         case 0:
  1.5701 +          find(node, x1, y1, xm, ym);
  1.5702 +          break;
  1.5703 +
  1.5704 +         case 1:
  1.5705 +          find(node, xm, y1, x2, ym);
  1.5706 +          break;
  1.5707 +
  1.5708 +         case 2:
  1.5709 +          find(node, x1, ym, xm, y2);
  1.5710 +          break;
  1.5711 +
  1.5712 +         case 3:
  1.5713 +          find(node, xm, ym, x2, y2);
  1.5714 +          break;
  1.5715 +        }
  1.5716 +      }
  1.5717 +    })(root, x0, y0, x3, y3);
  1.5718 +    return closestPoint;
  1.5719 +  }
  1.5720 +  d3.interpolateRgb = d3_interpolateRgb;
  1.5721 +  function d3_interpolateRgb(a, b) {
  1.5722 +    a = d3.rgb(a);
  1.5723 +    b = d3.rgb(b);
  1.5724 +    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
  1.5725 +    return function(t) {
  1.5726 +      return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
  1.5727 +    };
  1.5728 +  }
  1.5729 +  d3.interpolateObject = d3_interpolateObject;
  1.5730 +  function d3_interpolateObject(a, b) {
  1.5731 +    var i = {}, c = {}, k;
  1.5732 +    for (k in a) {
  1.5733 +      if (k in b) {
  1.5734 +        i[k] = d3_interpolate(a[k], b[k]);
  1.5735 +      } else {
  1.5736 +        c[k] = a[k];
  1.5737 +      }
  1.5738 +    }
  1.5739 +    for (k in b) {
  1.5740 +      if (!(k in a)) {
  1.5741 +        c[k] = b[k];
  1.5742 +      }
  1.5743 +    }
  1.5744 +    return function(t) {
  1.5745 +      for (k in i) c[k] = i[k](t);
  1.5746 +      return c;
  1.5747 +    };
  1.5748 +  }
  1.5749 +  d3.interpolateNumber = d3_interpolateNumber;
  1.5750 +  function d3_interpolateNumber(a, b) {
  1.5751 +    a = +a, b = +b;
  1.5752 +    return function(t) {
  1.5753 +      return a * (1 - t) + b * t;
  1.5754 +    };
  1.5755 +  }
  1.5756 +  d3.interpolateString = d3_interpolateString;
  1.5757 +  function d3_interpolateString(a, b) {
  1.5758 +    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
  1.5759 +    a = a + "", b = b + "";
  1.5760 +    while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
  1.5761 +      if ((bs = bm.index) > bi) {
  1.5762 +        bs = b.slice(bi, bs);
  1.5763 +        if (s[i]) s[i] += bs; else s[++i] = bs;
  1.5764 +      }
  1.5765 +      if ((am = am[0]) === (bm = bm[0])) {
  1.5766 +        if (s[i]) s[i] += bm; else s[++i] = bm;
  1.5767 +      } else {
  1.5768 +        s[++i] = null;
  1.5769 +        q.push({
  1.5770 +          i: i,
  1.5771 +          x: d3_interpolateNumber(am, bm)
  1.5772 +        });
  1.5773 +      }
  1.5774 +      bi = d3_interpolate_numberB.lastIndex;
  1.5775 +    }
  1.5776 +    if (bi < b.length) {
  1.5777 +      bs = b.slice(bi);
  1.5778 +      if (s[i]) s[i] += bs; else s[++i] = bs;
  1.5779 +    }
  1.5780 +    return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
  1.5781 +      return b(t) + "";
  1.5782 +    }) : function() {
  1.5783 +      return b;
  1.5784 +    } : (b = q.length, function(t) {
  1.5785 +      for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
  1.5786 +      return s.join("");
  1.5787 +    });
  1.5788 +  }
  1.5789 +  var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
  1.5790 +  d3.interpolate = d3_interpolate;
  1.5791 +  function d3_interpolate(a, b) {
  1.5792 +    var i = d3.interpolators.length, f;
  1.5793 +    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
  1.5794 +    return f;
  1.5795 +  }
  1.5796 +  d3.interpolators = [ function(a, b) {
  1.5797 +    var t = typeof b;
  1.5798 +    return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
  1.5799 +  } ];
  1.5800 +  d3.interpolateArray = d3_interpolateArray;
  1.5801 +  function d3_interpolateArray(a, b) {
  1.5802 +    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
  1.5803 +    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
  1.5804 +    for (;i < na; ++i) c[i] = a[i];
  1.5805 +    for (;i < nb; ++i) c[i] = b[i];
  1.5806 +    return function(t) {
  1.5807 +      for (i = 0; i < n0; ++i) c[i] = x[i](t);
  1.5808 +      return c;
  1.5809 +    };
  1.5810 +  }
  1.5811 +  var d3_ease_default = function() {
  1.5812 +    return d3_identity;
  1.5813 +  };
  1.5814 +  var d3_ease = d3.map({
  1.5815 +    linear: d3_ease_default,
  1.5816 +    poly: d3_ease_poly,
  1.5817 +    quad: function() {
  1.5818 +      return d3_ease_quad;
  1.5819 +    },
  1.5820 +    cubic: function() {
  1.5821 +      return d3_ease_cubic;
  1.5822 +    },
  1.5823 +    sin: function() {
  1.5824 +      return d3_ease_sin;
  1.5825 +    },
  1.5826 +    exp: function() {
  1.5827 +      return d3_ease_exp;
  1.5828 +    },
  1.5829 +    circle: function() {
  1.5830 +      return d3_ease_circle;
  1.5831 +    },
  1.5832 +    elastic: d3_ease_elastic,
  1.5833 +    back: d3_ease_back,
  1.5834 +    bounce: function() {
  1.5835 +      return d3_ease_bounce;
  1.5836 +    }
  1.5837 +  });
  1.5838 +  var d3_ease_mode = d3.map({
  1.5839 +    "in": d3_identity,
  1.5840 +    out: d3_ease_reverse,
  1.5841 +    "in-out": d3_ease_reflect,
  1.5842 +    "out-in": function(f) {
  1.5843 +      return d3_ease_reflect(d3_ease_reverse(f));
  1.5844 +    }
  1.5845 +  });
  1.5846 +  d3.ease = function(name) {
  1.5847 +    var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
  1.5848 +    t = d3_ease.get(t) || d3_ease_default;
  1.5849 +    m = d3_ease_mode.get(m) || d3_identity;
  1.5850 +    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
  1.5851 +  };
  1.5852 +  function d3_ease_clamp(f) {
  1.5853 +    return function(t) {
  1.5854 +      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
  1.5855 +    };
  1.5856 +  }
  1.5857 +  function d3_ease_reverse(f) {
  1.5858 +    return function(t) {
  1.5859 +      return 1 - f(1 - t);
  1.5860 +    };
  1.5861 +  }
  1.5862 +  function d3_ease_reflect(f) {
  1.5863 +    return function(t) {
  1.5864 +      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
  1.5865 +    };
  1.5866 +  }
  1.5867 +  function d3_ease_quad(t) {
  1.5868 +    return t * t;
  1.5869 +  }
  1.5870 +  function d3_ease_cubic(t) {
  1.5871 +    return t * t * t;
  1.5872 +  }
  1.5873 +  function d3_ease_cubicInOut(t) {
  1.5874 +    if (t <= 0) return 0;
  1.5875 +    if (t >= 1) return 1;
  1.5876 +    var t2 = t * t, t3 = t2 * t;
  1.5877 +    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
  1.5878 +  }
  1.5879 +  function d3_ease_poly(e) {
  1.5880 +    return function(t) {
  1.5881 +      return Math.pow(t, e);
  1.5882 +    };
  1.5883 +  }
  1.5884 +  function d3_ease_sin(t) {
  1.5885 +    return 1 - Math.cos(t * halfπ);
  1.5886 +  }
  1.5887 +  function d3_ease_exp(t) {
  1.5888 +    return Math.pow(2, 10 * (t - 1));
  1.5889 +  }
  1.5890 +  function d3_ease_circle(t) {
  1.5891 +    return 1 - Math.sqrt(1 - t * t);
  1.5892 +  }
  1.5893 +  function d3_ease_elastic(a, p) {
  1.5894 +    var s;
  1.5895 +    if (arguments.length < 2) p = .45;
  1.5896 +    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
  1.5897 +    return function(t) {
  1.5898 +      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
  1.5899 +    };
  1.5900 +  }
  1.5901 +  function d3_ease_back(s) {
  1.5902 +    if (!s) s = 1.70158;
  1.5903 +    return function(t) {
  1.5904 +      return t * t * ((s + 1) * t - s);
  1.5905 +    };
  1.5906 +  }
  1.5907 +  function d3_ease_bounce(t) {
  1.5908 +    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
  1.5909 +  }
  1.5910 +  d3.interpolateHcl = d3_interpolateHcl;
  1.5911 +  function d3_interpolateHcl(a, b) {
  1.5912 +    a = d3.hcl(a);
  1.5913 +    b = d3.hcl(b);
  1.5914 +    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
  1.5915 +    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
  1.5916 +    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
  1.5917 +    return function(t) {
  1.5918 +      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
  1.5919 +    };
  1.5920 +  }
  1.5921 +  d3.interpolateHsl = d3_interpolateHsl;
  1.5922 +  function d3_interpolateHsl(a, b) {
  1.5923 +    a = d3.hsl(a);
  1.5924 +    b = d3.hsl(b);
  1.5925 +    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
  1.5926 +    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
  1.5927 +    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
  1.5928 +    return function(t) {
  1.5929 +      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
  1.5930 +    };
  1.5931 +  }
  1.5932 +  d3.interpolateLab = d3_interpolateLab;
  1.5933 +  function d3_interpolateLab(a, b) {
  1.5934 +    a = d3.lab(a);
  1.5935 +    b = d3.lab(b);
  1.5936 +    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
  1.5937 +    return function(t) {
  1.5938 +      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
  1.5939 +    };
  1.5940 +  }
  1.5941 +  d3.interpolateRound = d3_interpolateRound;
  1.5942 +  function d3_interpolateRound(a, b) {
  1.5943 +    b -= a;
  1.5944 +    return function(t) {
  1.5945 +      return Math.round(a + b * t);
  1.5946 +    };
  1.5947 +  }
  1.5948 +  d3.transform = function(string) {
  1.5949 +    var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
  1.5950 +    return (d3.transform = function(string) {
  1.5951 +      if (string != null) {
  1.5952 +        g.setAttribute("transform", string);
  1.5953 +        var t = g.transform.baseVal.consolidate();
  1.5954 +      }
  1.5955 +      return new d3_transform(t ? t.matrix : d3_transformIdentity);
  1.5956 +    })(string);
  1.5957 +  };
  1.5958 +  function d3_transform(m) {
  1.5959 +    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
  1.5960 +    if (r0[0] * r1[1] < r1[0] * r0[1]) {
  1.5961 +      r0[0] *= -1;
  1.5962 +      r0[1] *= -1;
  1.5963 +      kx *= -1;
  1.5964 +      kz *= -1;
  1.5965 +    }
  1.5966 +    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
  1.5967 +    this.translate = [ m.e, m.f ];
  1.5968 +    this.scale = [ kx, ky ];
  1.5969 +    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
  1.5970 +  }
  1.5971 +  d3_transform.prototype.toString = function() {
  1.5972 +    return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
  1.5973 +  };
  1.5974 +  function d3_transformDot(a, b) {
  1.5975 +    return a[0] * b[0] + a[1] * b[1];
  1.5976 +  }
  1.5977 +  function d3_transformNormalize(a) {
  1.5978 +    var k = Math.sqrt(d3_transformDot(a, a));
  1.5979 +    if (k) {
  1.5980 +      a[0] /= k;
  1.5981 +      a[1] /= k;
  1.5982 +    }
  1.5983 +    return k;
  1.5984 +  }
  1.5985 +  function d3_transformCombine(a, b, k) {
  1.5986 +    a[0] += k * b[0];
  1.5987 +    a[1] += k * b[1];
  1.5988 +    return a;
  1.5989 +  }
  1.5990 +  var d3_transformIdentity = {
  1.5991 +    a: 1,
  1.5992 +    b: 0,
  1.5993 +    c: 0,
  1.5994 +    d: 1,
  1.5995 +    e: 0,
  1.5996 +    f: 0
  1.5997 +  };
  1.5998 +  d3.interpolateTransform = d3_interpolateTransform;
  1.5999 +  function d3_interpolateTransformPop(s) {
  1.6000 +    return s.length ? s.pop() + "," : "";
  1.6001 +  }
  1.6002 +  function d3_interpolateTranslate(ta, tb, s, q) {
  1.6003 +    if (ta[0] !== tb[0] || ta[1] !== tb[1]) {
  1.6004 +      var i = s.push("translate(", null, ",", null, ")");
  1.6005 +      q.push({
  1.6006 +        i: i - 4,
  1.6007 +        x: d3_interpolateNumber(ta[0], tb[0])
  1.6008 +      }, {
  1.6009 +        i: i - 2,
  1.6010 +        x: d3_interpolateNumber(ta[1], tb[1])
  1.6011 +      });
  1.6012 +    } else if (tb[0] || tb[1]) {
  1.6013 +      s.push("translate(" + tb + ")");
  1.6014 +    }
  1.6015 +  }
  1.6016 +  function d3_interpolateRotate(ra, rb, s, q) {
  1.6017 +    if (ra !== rb) {
  1.6018 +      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
  1.6019 +      q.push({
  1.6020 +        i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2,
  1.6021 +        x: d3_interpolateNumber(ra, rb)
  1.6022 +      });
  1.6023 +    } else if (rb) {
  1.6024 +      s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")");
  1.6025 +    }
  1.6026 +  }
  1.6027 +  function d3_interpolateSkew(wa, wb, s, q) {
  1.6028 +    if (wa !== wb) {
  1.6029 +      q.push({
  1.6030 +        i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2,
  1.6031 +        x: d3_interpolateNumber(wa, wb)
  1.6032 +      });
  1.6033 +    } else if (wb) {
  1.6034 +      s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")");
  1.6035 +    }
  1.6036 +  }
  1.6037 +  function d3_interpolateScale(ka, kb, s, q) {
  1.6038 +    if (ka[0] !== kb[0] || ka[1] !== kb[1]) {
  1.6039 +      var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")");
  1.6040 +      q.push({
  1.6041 +        i: i - 4,
  1.6042 +        x: d3_interpolateNumber(ka[0], kb[0])
  1.6043 +      }, {
  1.6044 +        i: i - 2,
  1.6045 +        x: d3_interpolateNumber(ka[1], kb[1])
  1.6046 +      });
  1.6047 +    } else if (kb[0] !== 1 || kb[1] !== 1) {
  1.6048 +      s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")");
  1.6049 +    }
  1.6050 +  }
  1.6051 +  function d3_interpolateTransform(a, b) {
  1.6052 +    var s = [], q = [];
  1.6053 +    a = d3.transform(a), b = d3.transform(b);
  1.6054 +    d3_interpolateTranslate(a.translate, b.translate, s, q);
  1.6055 +    d3_interpolateRotate(a.rotate, b.rotate, s, q);
  1.6056 +    d3_interpolateSkew(a.skew, b.skew, s, q);
  1.6057 +    d3_interpolateScale(a.scale, b.scale, s, q);
  1.6058 +    a = b = null;
  1.6059 +    return function(t) {
  1.6060 +      var i = -1, n = q.length, o;
  1.6061 +      while (++i < n) s[(o = q[i]).i] = o.x(t);
  1.6062 +      return s.join("");
  1.6063 +    };
  1.6064 +  }
  1.6065 +  function d3_uninterpolateNumber(a, b) {
  1.6066 +    b = (b -= a = +a) || 1 / b;
  1.6067 +    return function(x) {
  1.6068 +      return (x - a) / b;
  1.6069 +    };
  1.6070 +  }
  1.6071 +  function d3_uninterpolateClamp(a, b) {
  1.6072 +    b = (b -= a = +a) || 1 / b;
  1.6073 +    return function(x) {
  1.6074 +      return Math.max(0, Math.min(1, (x - a) / b));
  1.6075 +    };
  1.6076 +  }
  1.6077 +  d3.layout = {};
  1.6078 +  d3.layout.bundle = function() {
  1.6079 +    return function(links) {
  1.6080 +      var paths = [], i = -1, n = links.length;
  1.6081 +      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
  1.6082 +      return paths;
  1.6083 +    };
  1.6084 +  };
  1.6085 +  function d3_layout_bundlePath(link) {
  1.6086 +    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
  1.6087 +    while (start !== lca) {
  1.6088 +      start = start.parent;
  1.6089 +      points.push(start);
  1.6090 +    }
  1.6091 +    var k = points.length;
  1.6092 +    while (end !== lca) {
  1.6093 +      points.splice(k, 0, end);
  1.6094 +      end = end.parent;
  1.6095 +    }
  1.6096 +    return points;
  1.6097 +  }
  1.6098 +  function d3_layout_bundleAncestors(node) {
  1.6099 +    var ancestors = [], parent = node.parent;
  1.6100 +    while (parent != null) {
  1.6101 +      ancestors.push(node);
  1.6102 +      node = parent;
  1.6103 +      parent = parent.parent;
  1.6104 +    }
  1.6105 +    ancestors.push(node);
  1.6106 +    return ancestors;
  1.6107 +  }
  1.6108 +  function d3_layout_bundleLeastCommonAncestor(a, b) {
  1.6109 +    if (a === b) return a;
  1.6110 +    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
  1.6111 +    while (aNode === bNode) {
  1.6112 +      sharedNode = aNode;
  1.6113 +      aNode = aNodes.pop();
  1.6114 +      bNode = bNodes.pop();
  1.6115 +    }
  1.6116 +    return sharedNode;
  1.6117 +  }
  1.6118 +  d3.layout.chord = function() {
  1.6119 +    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
  1.6120 +    function relayout() {
  1.6121 +      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
  1.6122 +      chords = [];
  1.6123 +      groups = [];
  1.6124 +      k = 0, i = -1;
  1.6125 +      while (++i < n) {
  1.6126 +        x = 0, j = -1;
  1.6127 +        while (++j < n) {
  1.6128 +          x += matrix[i][j];
  1.6129 +        }
  1.6130 +        groupSums.push(x);
  1.6131 +        subgroupIndex.push(d3.range(n));
  1.6132 +        k += x;
  1.6133 +      }
  1.6134 +      if (sortGroups) {
  1.6135 +        groupIndex.sort(function(a, b) {
  1.6136 +          return sortGroups(groupSums[a], groupSums[b]);
  1.6137 +        });
  1.6138 +      }
  1.6139 +      if (sortSubgroups) {
  1.6140 +        subgroupIndex.forEach(function(d, i) {
  1.6141 +          d.sort(function(a, b) {
  1.6142 +            return sortSubgroups(matrix[i][a], matrix[i][b]);
  1.6143 +          });
  1.6144 +        });
  1.6145 +      }
  1.6146 +      k = (τ - padding * n) / k;
  1.6147 +      x = 0, i = -1;
  1.6148 +      while (++i < n) {
  1.6149 +        x0 = x, j = -1;
  1.6150 +        while (++j < n) {
  1.6151 +          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
  1.6152 +          subgroups[di + "-" + dj] = {
  1.6153 +            index: di,
  1.6154 +            subindex: dj,
  1.6155 +            startAngle: a0,
  1.6156 +            endAngle: a1,
  1.6157 +            value: v
  1.6158 +          };
  1.6159 +        }
  1.6160 +        groups[di] = {
  1.6161 +          index: di,
  1.6162 +          startAngle: x0,
  1.6163 +          endAngle: x,
  1.6164 +          value: groupSums[di]
  1.6165 +        };
  1.6166 +        x += padding;
  1.6167 +      }
  1.6168 +      i = -1;
  1.6169 +      while (++i < n) {
  1.6170 +        j = i - 1;
  1.6171 +        while (++j < n) {
  1.6172 +          var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
  1.6173 +          if (source.value || target.value) {
  1.6174 +            chords.push(source.value < target.value ? {
  1.6175 +              source: target,
  1.6176 +              target: source
  1.6177 +            } : {
  1.6178 +              source: source,
  1.6179 +              target: target
  1.6180 +            });
  1.6181 +          }
  1.6182 +        }
  1.6183 +      }
  1.6184 +      if (sortChords) resort();
  1.6185 +    }
  1.6186 +    function resort() {
  1.6187 +      chords.sort(function(a, b) {
  1.6188 +        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
  1.6189 +      });
  1.6190 +    }
  1.6191 +    chord.matrix = function(x) {
  1.6192 +      if (!arguments.length) return matrix;
  1.6193 +      n = (matrix = x) && matrix.length;
  1.6194 +      chords = groups = null;
  1.6195 +      return chord;
  1.6196 +    };
  1.6197 +    chord.padding = function(x) {
  1.6198 +      if (!arguments.length) return padding;
  1.6199 +      padding = x;
  1.6200 +      chords = groups = null;
  1.6201 +      return chord;
  1.6202 +    };
  1.6203 +    chord.sortGroups = function(x) {
  1.6204 +      if (!arguments.length) return sortGroups;
  1.6205 +      sortGroups = x;
  1.6206 +      chords = groups = null;
  1.6207 +      return chord;
  1.6208 +    };
  1.6209 +    chord.sortSubgroups = function(x) {
  1.6210 +      if (!arguments.length) return sortSubgroups;
  1.6211 +      sortSubgroups = x;
  1.6212 +      chords = null;
  1.6213 +      return chord;
  1.6214 +    };
  1.6215 +    chord.sortChords = function(x) {
  1.6216 +      if (!arguments.length) return sortChords;
  1.6217 +      sortChords = x;
  1.6218 +      if (chords) resort();
  1.6219 +      return chord;
  1.6220 +    };
  1.6221 +    chord.chords = function() {
  1.6222 +      if (!chords) relayout();
  1.6223 +      return chords;
  1.6224 +    };
  1.6225 +    chord.groups = function() {
  1.6226 +      if (!groups) relayout();
  1.6227 +      return groups;
  1.6228 +    };
  1.6229 +    return chord;
  1.6230 +  };
  1.6231 +  d3.layout.force = function() {
  1.6232 +    var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
  1.6233 +    function repulse(node) {
  1.6234 +      return function(quad, x1, _, x2) {
  1.6235 +        if (quad.point !== node) {
  1.6236 +          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
  1.6237 +          if (dw * dw / theta2 < dn) {
  1.6238 +            if (dn < chargeDistance2) {
  1.6239 +              var k = quad.charge / dn;
  1.6240 +              node.px -= dx * k;
  1.6241 +              node.py -= dy * k;
  1.6242 +            }
  1.6243 +            return true;
  1.6244 +          }
  1.6245 +          if (quad.point && dn && dn < chargeDistance2) {
  1.6246 +            var k = quad.pointCharge / dn;
  1.6247 +            node.px -= dx * k;
  1.6248 +            node.py -= dy * k;
  1.6249 +          }
  1.6250 +        }
  1.6251 +        return !quad.charge;
  1.6252 +      };
  1.6253 +    }
  1.6254 +    force.tick = function() {
  1.6255 +      if ((alpha *= .99) < .005) {
  1.6256 +        timer = null;
  1.6257 +        event.end({
  1.6258 +          type: "end",
  1.6259 +          alpha: alpha = 0
  1.6260 +        });
  1.6261 +        return true;
  1.6262 +      }
  1.6263 +      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
  1.6264 +      for (i = 0; i < m; ++i) {
  1.6265 +        o = links[i];
  1.6266 +        s = o.source;
  1.6267 +        t = o.target;
  1.6268 +        x = t.x - s.x;
  1.6269 +        y = t.y - s.y;
  1.6270 +        if (l = x * x + y * y) {
  1.6271 +          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
  1.6272 +          x *= l;
  1.6273 +          y *= l;
  1.6274 +          t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5);
  1.6275 +          t.y -= y * k;
  1.6276 +          s.x += x * (k = 1 - k);
  1.6277 +          s.y += y * k;
  1.6278 +        }
  1.6279 +      }
  1.6280 +      if (k = alpha * gravity) {
  1.6281 +        x = size[0] / 2;
  1.6282 +        y = size[1] / 2;
  1.6283 +        i = -1;
  1.6284 +        if (k) while (++i < n) {
  1.6285 +          o = nodes[i];
  1.6286 +          o.x += (x - o.x) * k;
  1.6287 +          o.y += (y - o.y) * k;
  1.6288 +        }
  1.6289 +      }
  1.6290 +      if (charge) {
  1.6291 +        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
  1.6292 +        i = -1;
  1.6293 +        while (++i < n) {
  1.6294 +          if (!(o = nodes[i]).fixed) {
  1.6295 +            q.visit(repulse(o));
  1.6296 +          }
  1.6297 +        }
  1.6298 +      }
  1.6299 +      i = -1;
  1.6300 +      while (++i < n) {
  1.6301 +        o = nodes[i];
  1.6302 +        if (o.fixed) {
  1.6303 +          o.x = o.px;
  1.6304 +          o.y = o.py;
  1.6305 +        } else {
  1.6306 +          o.x -= (o.px - (o.px = o.x)) * friction;
  1.6307 +          o.y -= (o.py - (o.py = o.y)) * friction;
  1.6308 +        }
  1.6309 +      }
  1.6310 +      event.tick({
  1.6311 +        type: "tick",
  1.6312 +        alpha: alpha
  1.6313 +      });
  1.6314 +    };
  1.6315 +    force.nodes = function(x) {
  1.6316 +      if (!arguments.length) return nodes;
  1.6317 +      nodes = x;
  1.6318 +      return force;
  1.6319 +    };
  1.6320 +    force.links = function(x) {
  1.6321 +      if (!arguments.length) return links;
  1.6322 +      links = x;
  1.6323 +      return force;
  1.6324 +    };
  1.6325 +    force.size = function(x) {
  1.6326 +      if (!arguments.length) return size;
  1.6327 +      size = x;
  1.6328 +      return force;
  1.6329 +    };
  1.6330 +    force.linkDistance = function(x) {
  1.6331 +      if (!arguments.length) return linkDistance;
  1.6332 +      linkDistance = typeof x === "function" ? x : +x;
  1.6333 +      return force;
  1.6334 +    };
  1.6335 +    force.distance = force.linkDistance;
  1.6336 +    force.linkStrength = function(x) {
  1.6337 +      if (!arguments.length) return linkStrength;
  1.6338 +      linkStrength = typeof x === "function" ? x : +x;
  1.6339 +      return force;
  1.6340 +    };
  1.6341 +    force.friction = function(x) {
  1.6342 +      if (!arguments.length) return friction;
  1.6343 +      friction = +x;
  1.6344 +      return force;
  1.6345 +    };
  1.6346 +    force.charge = function(x) {
  1.6347 +      if (!arguments.length) return charge;
  1.6348 +      charge = typeof x === "function" ? x : +x;
  1.6349 +      return force;
  1.6350 +    };
  1.6351 +    force.chargeDistance = function(x) {
  1.6352 +      if (!arguments.length) return Math.sqrt(chargeDistance2);
  1.6353 +      chargeDistance2 = x * x;
  1.6354 +      return force;
  1.6355 +    };
  1.6356 +    force.gravity = function(x) {
  1.6357 +      if (!arguments.length) return gravity;
  1.6358 +      gravity = +x;
  1.6359 +      return force;
  1.6360 +    };
  1.6361 +    force.theta = function(x) {
  1.6362 +      if (!arguments.length) return Math.sqrt(theta2);
  1.6363 +      theta2 = x * x;
  1.6364 +      return force;
  1.6365 +    };
  1.6366 +    force.alpha = function(x) {
  1.6367 +      if (!arguments.length) return alpha;
  1.6368 +      x = +x;
  1.6369 +      if (alpha) {
  1.6370 +        if (x > 0) {
  1.6371 +          alpha = x;
  1.6372 +        } else {
  1.6373 +          timer.c = null, timer.t = NaN, timer = null;
  1.6374 +          event.end({
  1.6375 +            type: "end",
  1.6376 +            alpha: alpha = 0
  1.6377 +          });
  1.6378 +        }
  1.6379 +      } else if (x > 0) {
  1.6380 +        event.start({
  1.6381 +          type: "start",
  1.6382 +          alpha: alpha = x
  1.6383 +        });
  1.6384 +        timer = d3_timer(force.tick);
  1.6385 +      }
  1.6386 +      return force;
  1.6387 +    };
  1.6388 +    force.start = function() {
  1.6389 +      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
  1.6390 +      for (i = 0; i < n; ++i) {
  1.6391 +        (o = nodes[i]).index = i;
  1.6392 +        o.weight = 0;
  1.6393 +      }
  1.6394 +      for (i = 0; i < m; ++i) {
  1.6395 +        o = links[i];
  1.6396 +        if (typeof o.source == "number") o.source = nodes[o.source];
  1.6397 +        if (typeof o.target == "number") o.target = nodes[o.target];
  1.6398 +        ++o.source.weight;
  1.6399 +        ++o.target.weight;
  1.6400 +      }
  1.6401 +      for (i = 0; i < n; ++i) {
  1.6402 +        o = nodes[i];
  1.6403 +        if (isNaN(o.x)) o.x = position("x", w);
  1.6404 +        if (isNaN(o.y)) o.y = position("y", h);
  1.6405 +        if (isNaN(o.px)) o.px = o.x;
  1.6406 +        if (isNaN(o.py)) o.py = o.y;
  1.6407 +      }
  1.6408 +      distances = [];
  1.6409 +      if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
  1.6410 +      strengths = [];
  1.6411 +      if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
  1.6412 +      charges = [];
  1.6413 +      if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
  1.6414 +      function position(dimension, size) {
  1.6415 +        if (!neighbors) {
  1.6416 +          neighbors = new Array(n);
  1.6417 +          for (j = 0; j < n; ++j) {
  1.6418 +            neighbors[j] = [];
  1.6419 +          }
  1.6420 +          for (j = 0; j < m; ++j) {
  1.6421 +            var o = links[j];
  1.6422 +            neighbors[o.source.index].push(o.target);
  1.6423 +            neighbors[o.target.index].push(o.source);
  1.6424 +          }
  1.6425 +        }
  1.6426 +        var candidates = neighbors[i], j = -1, l = candidates.length, x;
  1.6427 +        while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x;
  1.6428 +        return Math.random() * size;
  1.6429 +      }
  1.6430 +      return force.resume();
  1.6431 +    };
  1.6432 +    force.resume = function() {
  1.6433 +      return force.alpha(.1);
  1.6434 +    };
  1.6435 +    force.stop = function() {
  1.6436 +      return force.alpha(0);
  1.6437 +    };
  1.6438 +    force.drag = function() {
  1.6439 +      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
  1.6440 +      if (!arguments.length) return drag;
  1.6441 +      this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
  1.6442 +    };
  1.6443 +    function dragmove(d) {
  1.6444 +      d.px = d3.event.x, d.py = d3.event.y;
  1.6445 +      force.resume();
  1.6446 +    }
  1.6447 +    return d3.rebind(force, event, "on");
  1.6448 +  };
  1.6449 +  function d3_layout_forceDragstart(d) {
  1.6450 +    d.fixed |= 2;
  1.6451 +  }
  1.6452 +  function d3_layout_forceDragend(d) {
  1.6453 +    d.fixed &= ~6;
  1.6454 +  }
  1.6455 +  function d3_layout_forceMouseover(d) {
  1.6456 +    d.fixed |= 4;
  1.6457 +    d.px = d.x, d.py = d.y;
  1.6458 +  }
  1.6459 +  function d3_layout_forceMouseout(d) {
  1.6460 +    d.fixed &= ~4;
  1.6461 +  }
  1.6462 +  function d3_layout_forceAccumulate(quad, alpha, charges) {
  1.6463 +    var cx = 0, cy = 0;
  1.6464 +    quad.charge = 0;
  1.6465 +    if (!quad.leaf) {
  1.6466 +      var nodes = quad.nodes, n = nodes.length, i = -1, c;
  1.6467 +      while (++i < n) {
  1.6468 +        c = nodes[i];
  1.6469 +        if (c == null) continue;
  1.6470 +        d3_layout_forceAccumulate(c, alpha, charges);
  1.6471 +        quad.charge += c.charge;
  1.6472 +        cx += c.charge * c.cx;
  1.6473 +        cy += c.charge * c.cy;
  1.6474 +      }
  1.6475 +    }
  1.6476 +    if (quad.point) {
  1.6477 +      if (!quad.leaf) {
  1.6478 +        quad.point.x += Math.random() - .5;
  1.6479 +        quad.point.y += Math.random() - .5;
  1.6480 +      }
  1.6481 +      var k = alpha * charges[quad.point.index];
  1.6482 +      quad.charge += quad.pointCharge = k;
  1.6483 +      cx += k * quad.point.x;
  1.6484 +      cy += k * quad.point.y;
  1.6485 +    }
  1.6486 +    quad.cx = cx / quad.charge;
  1.6487 +    quad.cy = cy / quad.charge;
  1.6488 +  }
  1.6489 +  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
  1.6490 +  d3.layout.hierarchy = function() {
  1.6491 +    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
  1.6492 +    function hierarchy(root) {
  1.6493 +      var stack = [ root ], nodes = [], node;
  1.6494 +      root.depth = 0;
  1.6495 +      while ((node = stack.pop()) != null) {
  1.6496 +        nodes.push(node);
  1.6497 +        if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
  1.6498 +          var n, childs, child;
  1.6499 +          while (--n >= 0) {
  1.6500 +            stack.push(child = childs[n]);
  1.6501 +            child.parent = node;
  1.6502 +            child.depth = node.depth + 1;
  1.6503 +          }
  1.6504 +          if (value) node.value = 0;
  1.6505 +          node.children = childs;
  1.6506 +        } else {
  1.6507 +          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
  1.6508 +          delete node.children;
  1.6509 +        }
  1.6510 +      }
  1.6511 +      d3_layout_hierarchyVisitAfter(root, function(node) {
  1.6512 +        var childs, parent;
  1.6513 +        if (sort && (childs = node.children)) childs.sort(sort);
  1.6514 +        if (value && (parent = node.parent)) parent.value += node.value;
  1.6515 +      });
  1.6516 +      return nodes;
  1.6517 +    }
  1.6518 +    hierarchy.sort = function(x) {
  1.6519 +      if (!arguments.length) return sort;
  1.6520 +      sort = x;
  1.6521 +      return hierarchy;
  1.6522 +    };
  1.6523 +    hierarchy.children = function(x) {
  1.6524 +      if (!arguments.length) return children;
  1.6525 +      children = x;
  1.6526 +      return hierarchy;
  1.6527 +    };
  1.6528 +    hierarchy.value = function(x) {
  1.6529 +      if (!arguments.length) return value;
  1.6530 +      value = x;
  1.6531 +      return hierarchy;
  1.6532 +    };
  1.6533 +    hierarchy.revalue = function(root) {
  1.6534 +      if (value) {
  1.6535 +        d3_layout_hierarchyVisitBefore(root, function(node) {
  1.6536 +          if (node.children) node.value = 0;
  1.6537 +        });
  1.6538 +        d3_layout_hierarchyVisitAfter(root, function(node) {
  1.6539 +          var parent;
  1.6540 +          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
  1.6541 +          if (parent = node.parent) parent.value += node.value;
  1.6542 +        });
  1.6543 +      }
  1.6544 +      return root;
  1.6545 +    };
  1.6546 +    return hierarchy;
  1.6547 +  };
  1.6548 +  function d3_layout_hierarchyRebind(object, hierarchy) {
  1.6549 +    d3.rebind(object, hierarchy, "sort", "children", "value");
  1.6550 +    object.nodes = object;
  1.6551 +    object.links = d3_layout_hierarchyLinks;
  1.6552 +    return object;
  1.6553 +  }
  1.6554 +  function d3_layout_hierarchyVisitBefore(node, callback) {
  1.6555 +    var nodes = [ node ];
  1.6556 +    while ((node = nodes.pop()) != null) {
  1.6557 +      callback(node);
  1.6558 +      if ((children = node.children) && (n = children.length)) {
  1.6559 +        var n, children;
  1.6560 +        while (--n >= 0) nodes.push(children[n]);
  1.6561 +      }
  1.6562 +    }
  1.6563 +  }
  1.6564 +  function d3_layout_hierarchyVisitAfter(node, callback) {
  1.6565 +    var nodes = [ node ], nodes2 = [];
  1.6566 +    while ((node = nodes.pop()) != null) {
  1.6567 +      nodes2.push(node);
  1.6568 +      if ((children = node.children) && (n = children.length)) {
  1.6569 +        var i = -1, n, children;
  1.6570 +        while (++i < n) nodes.push(children[i]);
  1.6571 +      }
  1.6572 +    }
  1.6573 +    while ((node = nodes2.pop()) != null) {
  1.6574 +      callback(node);
  1.6575 +    }
  1.6576 +  }
  1.6577 +  function d3_layout_hierarchyChildren(d) {
  1.6578 +    return d.children;
  1.6579 +  }
  1.6580 +  function d3_layout_hierarchyValue(d) {
  1.6581 +    return d.value;
  1.6582 +  }
  1.6583 +  function d3_layout_hierarchySort(a, b) {
  1.6584 +    return b.value - a.value;
  1.6585 +  }
  1.6586 +  function d3_layout_hierarchyLinks(nodes) {
  1.6587 +    return d3.merge(nodes.map(function(parent) {
  1.6588 +      return (parent.children || []).map(function(child) {
  1.6589 +        return {
  1.6590 +          source: parent,
  1.6591 +          target: child
  1.6592 +        };
  1.6593 +      });
  1.6594 +    }));
  1.6595 +  }
  1.6596 +  d3.layout.partition = function() {
  1.6597 +    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
  1.6598 +    function position(node, x, dx, dy) {
  1.6599 +      var children = node.children;
  1.6600 +      node.x = x;
  1.6601 +      node.y = node.depth * dy;
  1.6602 +      node.dx = dx;
  1.6603 +      node.dy = dy;
  1.6604 +      if (children && (n = children.length)) {
  1.6605 +        var i = -1, n, c, d;
  1.6606 +        dx = node.value ? dx / node.value : 0;
  1.6607 +        while (++i < n) {
  1.6608 +          position(c = children[i], x, d = c.value * dx, dy);
  1.6609 +          x += d;
  1.6610 +        }
  1.6611 +      }
  1.6612 +    }
  1.6613 +    function depth(node) {
  1.6614 +      var children = node.children, d = 0;
  1.6615 +      if (children && (n = children.length)) {
  1.6616 +        var i = -1, n;
  1.6617 +        while (++i < n) d = Math.max(d, depth(children[i]));
  1.6618 +      }
  1.6619 +      return 1 + d;
  1.6620 +    }
  1.6621 +    function partition(d, i) {
  1.6622 +      var nodes = hierarchy.call(this, d, i);
  1.6623 +      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
  1.6624 +      return nodes;
  1.6625 +    }
  1.6626 +    partition.size = function(x) {
  1.6627 +      if (!arguments.length) return size;
  1.6628 +      size = x;
  1.6629 +      return partition;
  1.6630 +    };
  1.6631 +    return d3_layout_hierarchyRebind(partition, hierarchy);
  1.6632 +  };
  1.6633 +  d3.layout.pie = function() {
  1.6634 +    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0;
  1.6635 +    function pie(data) {
  1.6636 +      var n = data.length, values = data.map(function(d, i) {
  1.6637 +        return +value.call(pie, d, i);
  1.6638 +      }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v;
  1.6639 +      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
  1.6640 +        return values[j] - values[i];
  1.6641 +      } : function(i, j) {
  1.6642 +        return sort(data[i], data[j]);
  1.6643 +      });
  1.6644 +      index.forEach(function(i) {
  1.6645 +        arcs[i] = {
  1.6646 +          data: data[i],
  1.6647 +          value: v = values[i],
  1.6648 +          startAngle: a,
  1.6649 +          endAngle: a += v * k + pa,
  1.6650 +          padAngle: p
  1.6651 +        };
  1.6652 +      });
  1.6653 +      return arcs;
  1.6654 +    }
  1.6655 +    pie.value = function(_) {
  1.6656 +      if (!arguments.length) return value;
  1.6657 +      value = _;
  1.6658 +      return pie;
  1.6659 +    };
  1.6660 +    pie.sort = function(_) {
  1.6661 +      if (!arguments.length) return sort;
  1.6662 +      sort = _;
  1.6663 +      return pie;
  1.6664 +    };
  1.6665 +    pie.startAngle = function(_) {
  1.6666 +      if (!arguments.length) return startAngle;
  1.6667 +      startAngle = _;
  1.6668 +      return pie;
  1.6669 +    };
  1.6670 +    pie.endAngle = function(_) {
  1.6671 +      if (!arguments.length) return endAngle;
  1.6672 +      endAngle = _;
  1.6673 +      return pie;
  1.6674 +    };
  1.6675 +    pie.padAngle = function(_) {
  1.6676 +      if (!arguments.length) return padAngle;
  1.6677 +      padAngle = _;
  1.6678 +      return pie;
  1.6679 +    };
  1.6680 +    return pie;
  1.6681 +  };
  1.6682 +  var d3_layout_pieSortByValue = {};
  1.6683 +  d3.layout.stack = function() {
  1.6684 +    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
  1.6685 +    function stack(data, index) {
  1.6686 +      if (!(n = data.length)) return data;
  1.6687 +      var series = data.map(function(d, i) {
  1.6688 +        return values.call(stack, d, i);
  1.6689 +      });
  1.6690 +      var points = series.map(function(d) {
  1.6691 +        return d.map(function(v, i) {
  1.6692 +          return [ x.call(stack, v, i), y.call(stack, v, i) ];
  1.6693 +        });
  1.6694 +      });
  1.6695 +      var orders = order.call(stack, points, index);
  1.6696 +      series = d3.permute(series, orders);
  1.6697 +      points = d3.permute(points, orders);
  1.6698 +      var offsets = offset.call(stack, points, index);
  1.6699 +      var m = series[0].length, n, i, j, o;
  1.6700 +      for (j = 0; j < m; ++j) {
  1.6701 +        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
  1.6702 +        for (i = 1; i < n; ++i) {
  1.6703 +          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
  1.6704 +        }
  1.6705 +      }
  1.6706 +      return data;
  1.6707 +    }
  1.6708 +    stack.values = function(x) {
  1.6709 +      if (!arguments.length) return values;
  1.6710 +      values = x;
  1.6711 +      return stack;
  1.6712 +    };
  1.6713 +    stack.order = function(x) {
  1.6714 +      if (!arguments.length) return order;
  1.6715 +      order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
  1.6716 +      return stack;
  1.6717 +    };
  1.6718 +    stack.offset = function(x) {
  1.6719 +      if (!arguments.length) return offset;
  1.6720 +      offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
  1.6721 +      return stack;
  1.6722 +    };
  1.6723 +    stack.x = function(z) {
  1.6724 +      if (!arguments.length) return x;
  1.6725 +      x = z;
  1.6726 +      return stack;
  1.6727 +    };
  1.6728 +    stack.y = function(z) {
  1.6729 +      if (!arguments.length) return y;
  1.6730 +      y = z;
  1.6731 +      return stack;
  1.6732 +    };
  1.6733 +    stack.out = function(z) {
  1.6734 +      if (!arguments.length) return out;
  1.6735 +      out = z;
  1.6736 +      return stack;
  1.6737 +    };
  1.6738 +    return stack;
  1.6739 +  };
  1.6740 +  function d3_layout_stackX(d) {
  1.6741 +    return d.x;
  1.6742 +  }
  1.6743 +  function d3_layout_stackY(d) {
  1.6744 +    return d.y;
  1.6745 +  }
  1.6746 +  function d3_layout_stackOut(d, y0, y) {
  1.6747 +    d.y0 = y0;
  1.6748 +    d.y = y;
  1.6749 +  }
  1.6750 +  var d3_layout_stackOrders = d3.map({
  1.6751 +    "inside-out": function(data) {
  1.6752 +      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
  1.6753 +        return max[a] - max[b];
  1.6754 +      }), top = 0, bottom = 0, tops = [], bottoms = [];
  1.6755 +      for (i = 0; i < n; ++i) {
  1.6756 +        j = index[i];
  1.6757 +        if (top < bottom) {
  1.6758 +          top += sums[j];
  1.6759 +          tops.push(j);
  1.6760 +        } else {
  1.6761 +          bottom += sums[j];
  1.6762 +          bottoms.push(j);
  1.6763 +        }
  1.6764 +      }
  1.6765 +      return bottoms.reverse().concat(tops);
  1.6766 +    },
  1.6767 +    reverse: function(data) {
  1.6768 +      return d3.range(data.length).reverse();
  1.6769 +    },
  1.6770 +    "default": d3_layout_stackOrderDefault
  1.6771 +  });
  1.6772 +  var d3_layout_stackOffsets = d3.map({
  1.6773 +    silhouette: function(data) {
  1.6774 +      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
  1.6775 +      for (j = 0; j < m; ++j) {
  1.6776 +        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
  1.6777 +        if (o > max) max = o;
  1.6778 +        sums.push(o);
  1.6779 +      }
  1.6780 +      for (j = 0; j < m; ++j) {
  1.6781 +        y0[j] = (max - sums[j]) / 2;
  1.6782 +      }
  1.6783 +      return y0;
  1.6784 +    },
  1.6785 +    wiggle: function(data) {
  1.6786 +      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
  1.6787 +      y0[0] = o = o0 = 0;
  1.6788 +      for (j = 1; j < m; ++j) {
  1.6789 +        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
  1.6790 +        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
  1.6791 +          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
  1.6792 +            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
  1.6793 +          }
  1.6794 +          s2 += s3 * data[i][j][1];
  1.6795 +        }
  1.6796 +        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
  1.6797 +        if (o < o0) o0 = o;
  1.6798 +      }
  1.6799 +      for (j = 0; j < m; ++j) y0[j] -= o0;
  1.6800 +      return y0;
  1.6801 +    },
  1.6802 +    expand: function(data) {
  1.6803 +      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
  1.6804 +      for (j = 0; j < m; ++j) {
  1.6805 +        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
  1.6806 +        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
  1.6807 +      }
  1.6808 +      for (j = 0; j < m; ++j) y0[j] = 0;
  1.6809 +      return y0;
  1.6810 +    },
  1.6811 +    zero: d3_layout_stackOffsetZero
  1.6812 +  });
  1.6813 +  function d3_layout_stackOrderDefault(data) {
  1.6814 +    return d3.range(data.length);
  1.6815 +  }
  1.6816 +  function d3_layout_stackOffsetZero(data) {
  1.6817 +    var j = -1, m = data[0].length, y0 = [];
  1.6818 +    while (++j < m) y0[j] = 0;
  1.6819 +    return y0;
  1.6820 +  }
  1.6821 +  function d3_layout_stackMaxIndex(array) {
  1.6822 +    var i = 1, j = 0, v = array[0][1], k, n = array.length;
  1.6823 +    for (;i < n; ++i) {
  1.6824 +      if ((k = array[i][1]) > v) {
  1.6825 +        j = i;
  1.6826 +        v = k;
  1.6827 +      }
  1.6828 +    }
  1.6829 +    return j;
  1.6830 +  }
  1.6831 +  function d3_layout_stackReduceSum(d) {
  1.6832 +    return d.reduce(d3_layout_stackSum, 0);
  1.6833 +  }
  1.6834 +  function d3_layout_stackSum(p, d) {
  1.6835 +    return p + d[1];
  1.6836 +  }
  1.6837 +  d3.layout.histogram = function() {
  1.6838 +    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
  1.6839 +    function histogram(data, i) {
  1.6840 +      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
  1.6841 +      while (++i < m) {
  1.6842 +        bin = bins[i] = [];
  1.6843 +        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
  1.6844 +        bin.y = 0;
  1.6845 +      }
  1.6846 +      if (m > 0) {
  1.6847 +        i = -1;
  1.6848 +        while (++i < n) {
  1.6849 +          x = values[i];
  1.6850 +          if (x >= range[0] && x <= range[1]) {
  1.6851 +            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
  1.6852 +            bin.y += k;
  1.6853 +            bin.push(data[i]);
  1.6854 +          }
  1.6855 +        }
  1.6856 +      }
  1.6857 +      return bins;
  1.6858 +    }
  1.6859 +    histogram.value = function(x) {
  1.6860 +      if (!arguments.length) return valuer;
  1.6861 +      valuer = x;
  1.6862 +      return histogram;
  1.6863 +    };
  1.6864 +    histogram.range = function(x) {
  1.6865 +      if (!arguments.length) return ranger;
  1.6866 +      ranger = d3_functor(x);
  1.6867 +      return histogram;
  1.6868 +    };
  1.6869 +    histogram.bins = function(x) {
  1.6870 +      if (!arguments.length) return binner;
  1.6871 +      binner = typeof x === "number" ? function(range) {
  1.6872 +        return d3_layout_histogramBinFixed(range, x);
  1.6873 +      } : d3_functor(x);
  1.6874 +      return histogram;
  1.6875 +    };
  1.6876 +    histogram.frequency = function(x) {
  1.6877 +      if (!arguments.length) return frequency;
  1.6878 +      frequency = !!x;
  1.6879 +      return histogram;
  1.6880 +    };
  1.6881 +    return histogram;
  1.6882 +  };
  1.6883 +  function d3_layout_histogramBinSturges(range, values) {
  1.6884 +    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
  1.6885 +  }
  1.6886 +  function d3_layout_histogramBinFixed(range, n) {
  1.6887 +    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
  1.6888 +    while (++x <= n) f[x] = m * x + b;
  1.6889 +    return f;
  1.6890 +  }
  1.6891 +  function d3_layout_histogramRange(values) {
  1.6892 +    return [ d3.min(values), d3.max(values) ];
  1.6893 +  }
  1.6894 +  d3.layout.pack = function() {
  1.6895 +    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
  1.6896 +    function pack(d, i) {
  1.6897 +      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
  1.6898 +        return radius;
  1.6899 +      };
  1.6900 +      root.x = root.y = 0;
  1.6901 +      d3_layout_hierarchyVisitAfter(root, function(d) {
  1.6902 +        d.r = +r(d.value);
  1.6903 +      });
  1.6904 +      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
  1.6905 +      if (padding) {
  1.6906 +        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
  1.6907 +        d3_layout_hierarchyVisitAfter(root, function(d) {
  1.6908 +          d.r += dr;
  1.6909 +        });
  1.6910 +        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
  1.6911 +        d3_layout_hierarchyVisitAfter(root, function(d) {
  1.6912 +          d.r -= dr;
  1.6913 +        });
  1.6914 +      }
  1.6915 +      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
  1.6916 +      return nodes;
  1.6917 +    }
  1.6918 +    pack.size = function(_) {
  1.6919 +      if (!arguments.length) return size;
  1.6920 +      size = _;
  1.6921 +      return pack;
  1.6922 +    };
  1.6923 +    pack.radius = function(_) {
  1.6924 +      if (!arguments.length) return radius;
  1.6925 +      radius = _ == null || typeof _ === "function" ? _ : +_;
  1.6926 +      return pack;
  1.6927 +    };
  1.6928 +    pack.padding = function(_) {
  1.6929 +      if (!arguments.length) return padding;
  1.6930 +      padding = +_;
  1.6931 +      return pack;
  1.6932 +    };
  1.6933 +    return d3_layout_hierarchyRebind(pack, hierarchy);
  1.6934 +  };
  1.6935 +  function d3_layout_packSort(a, b) {
  1.6936 +    return a.value - b.value;
  1.6937 +  }
  1.6938 +  function d3_layout_packInsert(a, b) {
  1.6939 +    var c = a._pack_next;
  1.6940 +    a._pack_next = b;
  1.6941 +    b._pack_prev = a;
  1.6942 +    b._pack_next = c;
  1.6943 +    c._pack_prev = b;
  1.6944 +  }
  1.6945 +  function d3_layout_packSplice(a, b) {
  1.6946 +    a._pack_next = b;
  1.6947 +    b._pack_prev = a;
  1.6948 +  }
  1.6949 +  function d3_layout_packIntersects(a, b) {
  1.6950 +    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
  1.6951 +    return .999 * dr * dr > dx * dx + dy * dy;
  1.6952 +  }
  1.6953 +  function d3_layout_packSiblings(node) {
  1.6954 +    if (!(nodes = node.children) || !(n = nodes.length)) return;
  1.6955 +    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
  1.6956 +    function bound(node) {
  1.6957 +      xMin = Math.min(node.x - node.r, xMin);
  1.6958 +      xMax = Math.max(node.x + node.r, xMax);
  1.6959 +      yMin = Math.min(node.y - node.r, yMin);
  1.6960 +      yMax = Math.max(node.y + node.r, yMax);
  1.6961 +    }
  1.6962 +    nodes.forEach(d3_layout_packLink);
  1.6963 +    a = nodes[0];
  1.6964 +    a.x = -a.r;
  1.6965 +    a.y = 0;
  1.6966 +    bound(a);
  1.6967 +    if (n > 1) {
  1.6968 +      b = nodes[1];
  1.6969 +      b.x = b.r;
  1.6970 +      b.y = 0;
  1.6971 +      bound(b);
  1.6972 +      if (n > 2) {
  1.6973 +        c = nodes[2];
  1.6974 +        d3_layout_packPlace(a, b, c);
  1.6975 +        bound(c);
  1.6976 +        d3_layout_packInsert(a, c);
  1.6977 +        a._pack_prev = c;
  1.6978 +        d3_layout_packInsert(c, b);
  1.6979 +        b = a._pack_next;
  1.6980 +        for (i = 3; i < n; i++) {
  1.6981 +          d3_layout_packPlace(a, b, c = nodes[i]);
  1.6982 +          var isect = 0, s1 = 1, s2 = 1;
  1.6983 +          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
  1.6984 +            if (d3_layout_packIntersects(j, c)) {
  1.6985 +              isect = 1;
  1.6986 +              break;
  1.6987 +            }
  1.6988 +          }
  1.6989 +          if (isect == 1) {
  1.6990 +            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
  1.6991 +              if (d3_layout_packIntersects(k, c)) {
  1.6992 +                break;
  1.6993 +              }
  1.6994 +            }
  1.6995 +          }
  1.6996 +          if (isect) {
  1.6997 +            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
  1.6998 +            i--;
  1.6999 +          } else {
  1.7000 +            d3_layout_packInsert(a, c);
  1.7001 +            b = c;
  1.7002 +            bound(c);
  1.7003 +          }
  1.7004 +        }
  1.7005 +      }
  1.7006 +    }
  1.7007 +    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
  1.7008 +    for (i = 0; i < n; i++) {
  1.7009 +      c = nodes[i];
  1.7010 +      c.x -= cx;
  1.7011 +      c.y -= cy;
  1.7012 +      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
  1.7013 +    }
  1.7014 +    node.r = cr;
  1.7015 +    nodes.forEach(d3_layout_packUnlink);
  1.7016 +  }
  1.7017 +  function d3_layout_packLink(node) {
  1.7018 +    node._pack_next = node._pack_prev = node;
  1.7019 +  }
  1.7020 +  function d3_layout_packUnlink(node) {
  1.7021 +    delete node._pack_next;
  1.7022 +    delete node._pack_prev;
  1.7023 +  }
  1.7024 +  function d3_layout_packTransform(node, x, y, k) {
  1.7025 +    var children = node.children;
  1.7026 +    node.x = x += k * node.x;
  1.7027 +    node.y = y += k * node.y;
  1.7028 +    node.r *= k;
  1.7029 +    if (children) {
  1.7030 +      var i = -1, n = children.length;
  1.7031 +      while (++i < n) d3_layout_packTransform(children[i], x, y, k);
  1.7032 +    }
  1.7033 +  }
  1.7034 +  function d3_layout_packPlace(a, b, c) {
  1.7035 +    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
  1.7036 +    if (db && (dx || dy)) {
  1.7037 +      var da = b.r + c.r, dc = dx * dx + dy * dy;
  1.7038 +      da *= da;
  1.7039 +      db *= db;
  1.7040 +      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
  1.7041 +      c.x = a.x + x * dx + y * dy;
  1.7042 +      c.y = a.y + x * dy - y * dx;
  1.7043 +    } else {
  1.7044 +      c.x = a.x + db;
  1.7045 +      c.y = a.y;
  1.7046 +    }
  1.7047 +  }
  1.7048 +  d3.layout.tree = function() {
  1.7049 +    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
  1.7050 +    function tree(d, i) {
  1.7051 +      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
  1.7052 +      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
  1.7053 +      d3_layout_hierarchyVisitBefore(root1, secondWalk);
  1.7054 +      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
  1.7055 +        var left = root0, right = root0, bottom = root0;
  1.7056 +        d3_layout_hierarchyVisitBefore(root0, function(node) {
  1.7057 +          if (node.x < left.x) left = node;
  1.7058 +          if (node.x > right.x) right = node;
  1.7059 +          if (node.depth > bottom.depth) bottom = node;
  1.7060 +        });
  1.7061 +        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
  1.7062 +        d3_layout_hierarchyVisitBefore(root0, function(node) {
  1.7063 +          node.x = (node.x + tx) * kx;
  1.7064 +          node.y = node.depth * ky;
  1.7065 +        });
  1.7066 +      }
  1.7067 +      return nodes;
  1.7068 +    }
  1.7069 +    function wrapTree(root0) {
  1.7070 +      var root1 = {
  1.7071 +        A: null,
  1.7072 +        children: [ root0 ]
  1.7073 +      }, queue = [ root1 ], node1;
  1.7074 +      while ((node1 = queue.pop()) != null) {
  1.7075 +        for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
  1.7076 +          queue.push((children[i] = child = {
  1.7077 +            _: children[i],
  1.7078 +            parent: node1,
  1.7079 +            children: (child = children[i].children) && child.slice() || [],
  1.7080 +            A: null,
  1.7081 +            a: null,
  1.7082 +            z: 0,
  1.7083 +            m: 0,
  1.7084 +            c: 0,
  1.7085 +            s: 0,
  1.7086 +            t: null,
  1.7087 +            i: i
  1.7088 +          }).a = child);
  1.7089 +        }
  1.7090 +      }
  1.7091 +      return root1.children[0];
  1.7092 +    }
  1.7093 +    function firstWalk(v) {
  1.7094 +      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
  1.7095 +      if (children.length) {
  1.7096 +        d3_layout_treeShift(v);
  1.7097 +        var midpoint = (children[0].z + children[children.length - 1].z) / 2;
  1.7098 +        if (w) {
  1.7099 +          v.z = w.z + separation(v._, w._);
  1.7100 +          v.m = v.z - midpoint;
  1.7101 +        } else {
  1.7102 +          v.z = midpoint;
  1.7103 +        }
  1.7104 +      } else if (w) {
  1.7105 +        v.z = w.z + separation(v._, w._);
  1.7106 +      }
  1.7107 +      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
  1.7108 +    }
  1.7109 +    function secondWalk(v) {
  1.7110 +      v._.x = v.z + v.parent.m;
  1.7111 +      v.m += v.parent.m;
  1.7112 +    }
  1.7113 +    function apportion(v, w, ancestor) {
  1.7114 +      if (w) {
  1.7115 +        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
  1.7116 +        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
  1.7117 +          vom = d3_layout_treeLeft(vom);
  1.7118 +          vop = d3_layout_treeRight(vop);
  1.7119 +          vop.a = v;
  1.7120 +          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
  1.7121 +          if (shift > 0) {
  1.7122 +            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
  1.7123 +            sip += shift;
  1.7124 +            sop += shift;
  1.7125 +          }
  1.7126 +          sim += vim.m;
  1.7127 +          sip += vip.m;
  1.7128 +          som += vom.m;
  1.7129 +          sop += vop.m;
  1.7130 +        }
  1.7131 +        if (vim && !d3_layout_treeRight(vop)) {
  1.7132 +          vop.t = vim;
  1.7133 +          vop.m += sim - sop;
  1.7134 +        }
  1.7135 +        if (vip && !d3_layout_treeLeft(vom)) {
  1.7136 +          vom.t = vip;
  1.7137 +          vom.m += sip - som;
  1.7138 +          ancestor = v;
  1.7139 +        }
  1.7140 +      }
  1.7141 +      return ancestor;
  1.7142 +    }
  1.7143 +    function sizeNode(node) {
  1.7144 +      node.x *= size[0];
  1.7145 +      node.y = node.depth * size[1];
  1.7146 +    }
  1.7147 +    tree.separation = function(x) {
  1.7148 +      if (!arguments.length) return separation;
  1.7149 +      separation = x;
  1.7150 +      return tree;
  1.7151 +    };
  1.7152 +    tree.size = function(x) {
  1.7153 +      if (!arguments.length) return nodeSize ? null : size;
  1.7154 +      nodeSize = (size = x) == null ? sizeNode : null;
  1.7155 +      return tree;
  1.7156 +    };
  1.7157 +    tree.nodeSize = function(x) {
  1.7158 +      if (!arguments.length) return nodeSize ? size : null;
  1.7159 +      nodeSize = (size = x) == null ? null : sizeNode;
  1.7160 +      return tree;
  1.7161 +    };
  1.7162 +    return d3_layout_hierarchyRebind(tree, hierarchy);
  1.7163 +  };
  1.7164 +  function d3_layout_treeSeparation(a, b) {
  1.7165 +    return a.parent == b.parent ? 1 : 2;
  1.7166 +  }
  1.7167 +  function d3_layout_treeLeft(v) {
  1.7168 +    var children = v.children;
  1.7169 +    return children.length ? children[0] : v.t;
  1.7170 +  }
  1.7171 +  function d3_layout_treeRight(v) {
  1.7172 +    var children = v.children, n;
  1.7173 +    return (n = children.length) ? children[n - 1] : v.t;
  1.7174 +  }
  1.7175 +  function d3_layout_treeMove(wm, wp, shift) {
  1.7176 +    var change = shift / (wp.i - wm.i);
  1.7177 +    wp.c -= change;
  1.7178 +    wp.s += shift;
  1.7179 +    wm.c += change;
  1.7180 +    wp.z += shift;
  1.7181 +    wp.m += shift;
  1.7182 +  }
  1.7183 +  function d3_layout_treeShift(v) {
  1.7184 +    var shift = 0, change = 0, children = v.children, i = children.length, w;
  1.7185 +    while (--i >= 0) {
  1.7186 +      w = children[i];
  1.7187 +      w.z += shift;
  1.7188 +      w.m += shift;
  1.7189 +      shift += w.s + (change += w.c);
  1.7190 +    }
  1.7191 +  }
  1.7192 +  function d3_layout_treeAncestor(vim, v, ancestor) {
  1.7193 +    return vim.a.parent === v.parent ? vim.a : ancestor;
  1.7194 +  }
  1.7195 +  d3.layout.cluster = function() {
  1.7196 +    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
  1.7197 +    function cluster(d, i) {
  1.7198 +      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
  1.7199 +      d3_layout_hierarchyVisitAfter(root, function(node) {
  1.7200 +        var children = node.children;
  1.7201 +        if (children && children.length) {
  1.7202 +          node.x = d3_layout_clusterX(children);
  1.7203 +          node.y = d3_layout_clusterY(children);
  1.7204 +        } else {
  1.7205 +          node.x = previousNode ? x += separation(node, previousNode) : 0;
  1.7206 +          node.y = 0;
  1.7207 +          previousNode = node;
  1.7208 +        }
  1.7209 +      });
  1.7210 +      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
  1.7211 +      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
  1.7212 +        node.x = (node.x - root.x) * size[0];
  1.7213 +        node.y = (root.y - node.y) * size[1];
  1.7214 +      } : function(node) {
  1.7215 +        node.x = (node.x - x0) / (x1 - x0) * size[0];
  1.7216 +        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
  1.7217 +      });
  1.7218 +      return nodes;
  1.7219 +    }
  1.7220 +    cluster.separation = function(x) {
  1.7221 +      if (!arguments.length) return separation;
  1.7222 +      separation = x;
  1.7223 +      return cluster;
  1.7224 +    };
  1.7225 +    cluster.size = function(x) {
  1.7226 +      if (!arguments.length) return nodeSize ? null : size;
  1.7227 +      nodeSize = (size = x) == null;
  1.7228 +      return cluster;
  1.7229 +    };
  1.7230 +    cluster.nodeSize = function(x) {
  1.7231 +      if (!arguments.length) return nodeSize ? size : null;
  1.7232 +      nodeSize = (size = x) != null;
  1.7233 +      return cluster;
  1.7234 +    };
  1.7235 +    return d3_layout_hierarchyRebind(cluster, hierarchy);
  1.7236 +  };
  1.7237 +  function d3_layout_clusterY(children) {
  1.7238 +    return 1 + d3.max(children, function(child) {
  1.7239 +      return child.y;
  1.7240 +    });
  1.7241 +  }
  1.7242 +  function d3_layout_clusterX(children) {
  1.7243 +    return children.reduce(function(x, child) {
  1.7244 +      return x + child.x;
  1.7245 +    }, 0) / children.length;
  1.7246 +  }
  1.7247 +  function d3_layout_clusterLeft(node) {
  1.7248 +    var children = node.children;
  1.7249 +    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
  1.7250 +  }
  1.7251 +  function d3_layout_clusterRight(node) {
  1.7252 +    var children = node.children, n;
  1.7253 +    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
  1.7254 +  }
  1.7255 +  d3.layout.treemap = function() {
  1.7256 +    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
  1.7257 +    function scale(children, k) {
  1.7258 +      var i = -1, n = children.length, child, area;
  1.7259 +      while (++i < n) {
  1.7260 +        area = (child = children[i]).value * (k < 0 ? 0 : k);
  1.7261 +        child.area = isNaN(area) || area <= 0 ? 0 : area;
  1.7262 +      }
  1.7263 +    }
  1.7264 +    function squarify(node) {
  1.7265 +      var children = node.children;
  1.7266 +      if (children && children.length) {
  1.7267 +        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
  1.7268 +        scale(remaining, rect.dx * rect.dy / node.value);
  1.7269 +        row.area = 0;
  1.7270 +        while ((n = remaining.length) > 0) {
  1.7271 +          row.push(child = remaining[n - 1]);
  1.7272 +          row.area += child.area;
  1.7273 +          if (mode !== "squarify" || (score = worst(row, u)) <= best) {
  1.7274 +            remaining.pop();
  1.7275 +            best = score;
  1.7276 +          } else {
  1.7277 +            row.area -= row.pop().area;
  1.7278 +            position(row, u, rect, false);
  1.7279 +            u = Math.min(rect.dx, rect.dy);
  1.7280 +            row.length = row.area = 0;
  1.7281 +            best = Infinity;
  1.7282 +          }
  1.7283 +        }
  1.7284 +        if (row.length) {
  1.7285 +          position(row, u, rect, true);
  1.7286 +          row.length = row.area = 0;
  1.7287 +        }
  1.7288 +        children.forEach(squarify);
  1.7289 +      }
  1.7290 +    }
  1.7291 +    function stickify(node) {
  1.7292 +      var children = node.children;
  1.7293 +      if (children && children.length) {
  1.7294 +        var rect = pad(node), remaining = children.slice(), child, row = [];
  1.7295 +        scale(remaining, rect.dx * rect.dy / node.value);
  1.7296 +        row.area = 0;
  1.7297 +        while (child = remaining.pop()) {
  1.7298 +          row.push(child);
  1.7299 +          row.area += child.area;
  1.7300 +          if (child.z != null) {
  1.7301 +            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
  1.7302 +            row.length = row.area = 0;
  1.7303 +          }
  1.7304 +        }
  1.7305 +        children.forEach(stickify);
  1.7306 +      }
  1.7307 +    }
  1.7308 +    function worst(row, u) {
  1.7309 +      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
  1.7310 +      while (++i < n) {
  1.7311 +        if (!(r = row[i].area)) continue;
  1.7312 +        if (r < rmin) rmin = r;
  1.7313 +        if (r > rmax) rmax = r;
  1.7314 +      }
  1.7315 +      s *= s;
  1.7316 +      u *= u;
  1.7317 +      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
  1.7318 +    }
  1.7319 +    function position(row, u, rect, flush) {
  1.7320 +      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
  1.7321 +      if (u == rect.dx) {
  1.7322 +        if (flush || v > rect.dy) v = rect.dy;
  1.7323 +        while (++i < n) {
  1.7324 +          o = row[i];
  1.7325 +          o.x = x;
  1.7326 +          o.y = y;
  1.7327 +          o.dy = v;
  1.7328 +          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
  1.7329 +        }
  1.7330 +        o.z = true;
  1.7331 +        o.dx += rect.x + rect.dx - x;
  1.7332 +        rect.y += v;
  1.7333 +        rect.dy -= v;
  1.7334 +      } else {
  1.7335 +        if (flush || v > rect.dx) v = rect.dx;
  1.7336 +        while (++i < n) {
  1.7337 +          o = row[i];
  1.7338 +          o.x = x;
  1.7339 +          o.y = y;
  1.7340 +          o.dx = v;
  1.7341 +          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
  1.7342 +        }
  1.7343 +        o.z = false;
  1.7344 +        o.dy += rect.y + rect.dy - y;
  1.7345 +        rect.x += v;
  1.7346 +        rect.dx -= v;
  1.7347 +      }
  1.7348 +    }
  1.7349 +    function treemap(d) {
  1.7350 +      var nodes = stickies || hierarchy(d), root = nodes[0];
  1.7351 +      root.x = root.y = 0;
  1.7352 +      if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0;
  1.7353 +      if (stickies) hierarchy.revalue(root);
  1.7354 +      scale([ root ], root.dx * root.dy / root.value);
  1.7355 +      (stickies ? stickify : squarify)(root);
  1.7356 +      if (sticky) stickies = nodes;
  1.7357 +      return nodes;
  1.7358 +    }
  1.7359 +    treemap.size = function(x) {
  1.7360 +      if (!arguments.length) return size;
  1.7361 +      size = x;
  1.7362 +      return treemap;
  1.7363 +    };
  1.7364 +    treemap.padding = function(x) {
  1.7365 +      if (!arguments.length) return padding;
  1.7366 +      function padFunction(node) {
  1.7367 +        var p = x.call(treemap, node, node.depth);
  1.7368 +        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
  1.7369 +      }
  1.7370 +      function padConstant(node) {
  1.7371 +        return d3_layout_treemapPad(node, x);
  1.7372 +      }
  1.7373 +      var type;
  1.7374 +      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
  1.7375 +      padConstant) : padConstant;
  1.7376 +      return treemap;
  1.7377 +    };
  1.7378 +    treemap.round = function(x) {
  1.7379 +      if (!arguments.length) return round != Number;
  1.7380 +      round = x ? Math.round : Number;
  1.7381 +      return treemap;
  1.7382 +    };
  1.7383 +    treemap.sticky = function(x) {
  1.7384 +      if (!arguments.length) return sticky;
  1.7385 +      sticky = x;
  1.7386 +      stickies = null;
  1.7387 +      return treemap;
  1.7388 +    };
  1.7389 +    treemap.ratio = function(x) {
  1.7390 +      if (!arguments.length) return ratio;
  1.7391 +      ratio = x;
  1.7392 +      return treemap;
  1.7393 +    };
  1.7394 +    treemap.mode = function(x) {
  1.7395 +      if (!arguments.length) return mode;
  1.7396 +      mode = x + "";
  1.7397 +      return treemap;
  1.7398 +    };
  1.7399 +    return d3_layout_hierarchyRebind(treemap, hierarchy);
  1.7400 +  };
  1.7401 +  function d3_layout_treemapPadNull(node) {
  1.7402 +    return {
  1.7403 +      x: node.x,
  1.7404 +      y: node.y,
  1.7405 +      dx: node.dx,
  1.7406 +      dy: node.dy
  1.7407 +    };
  1.7408 +  }
  1.7409 +  function d3_layout_treemapPad(node, padding) {
  1.7410 +    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
  1.7411 +    if (dx < 0) {
  1.7412 +      x += dx / 2;
  1.7413 +      dx = 0;
  1.7414 +    }
  1.7415 +    if (dy < 0) {
  1.7416 +      y += dy / 2;
  1.7417 +      dy = 0;
  1.7418 +    }
  1.7419 +    return {
  1.7420 +      x: x,
  1.7421 +      y: y,
  1.7422 +      dx: dx,
  1.7423 +      dy: dy
  1.7424 +    };
  1.7425 +  }
  1.7426 +  d3.random = {
  1.7427 +    normal: function(µ, σ) {
  1.7428 +      var n = arguments.length;
  1.7429 +      if (n < 2) σ = 1;
  1.7430 +      if (n < 1) µ = 0;
  1.7431 +      return function() {
  1.7432 +        var x, y, r;
  1.7433 +        do {
  1.7434 +          x = Math.random() * 2 - 1;
  1.7435 +          y = Math.random() * 2 - 1;
  1.7436 +          r = x * x + y * y;
  1.7437 +        } while (!r || r > 1);
  1.7438 +        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
  1.7439 +      };
  1.7440 +    },
  1.7441 +    logNormal: function() {
  1.7442 +      var random = d3.random.normal.apply(d3, arguments);
  1.7443 +      return function() {
  1.7444 +        return Math.exp(random());
  1.7445 +      };
  1.7446 +    },
  1.7447 +    bates: function(m) {
  1.7448 +      var random = d3.random.irwinHall(m);
  1.7449 +      return function() {
  1.7450 +        return random() / m;
  1.7451 +      };
  1.7452 +    },
  1.7453 +    irwinHall: function(m) {
  1.7454 +      return function() {
  1.7455 +        for (var s = 0, j = 0; j < m; j++) s += Math.random();
  1.7456 +        return s;
  1.7457 +      };
  1.7458 +    }
  1.7459 +  };
  1.7460 +  d3.scale = {};
  1.7461 +  function d3_scaleExtent(domain) {
  1.7462 +    var start = domain[0], stop = domain[domain.length - 1];
  1.7463 +    return start < stop ? [ start, stop ] : [ stop, start ];
  1.7464 +  }
  1.7465 +  function d3_scaleRange(scale) {
  1.7466 +    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
  1.7467 +  }
  1.7468 +  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
  1.7469 +    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
  1.7470 +    return function(x) {
  1.7471 +      return i(u(x));
  1.7472 +    };
  1.7473 +  }
  1.7474 +  function d3_scale_nice(domain, nice) {
  1.7475 +    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
  1.7476 +    if (x1 < x0) {
  1.7477 +      dx = i0, i0 = i1, i1 = dx;
  1.7478 +      dx = x0, x0 = x1, x1 = dx;
  1.7479 +    }
  1.7480 +    domain[i0] = nice.floor(x0);
  1.7481 +    domain[i1] = nice.ceil(x1);
  1.7482 +    return domain;
  1.7483 +  }
  1.7484 +  function d3_scale_niceStep(step) {
  1.7485 +    return step ? {
  1.7486 +      floor: function(x) {
  1.7487 +        return Math.floor(x / step) * step;
  1.7488 +      },
  1.7489 +      ceil: function(x) {
  1.7490 +        return Math.ceil(x / step) * step;
  1.7491 +      }
  1.7492 +    } : d3_scale_niceIdentity;
  1.7493 +  }
  1.7494 +  var d3_scale_niceIdentity = {
  1.7495 +    floor: d3_identity,
  1.7496 +    ceil: d3_identity
  1.7497 +  };
  1.7498 +  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
  1.7499 +    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
  1.7500 +    if (domain[k] < domain[0]) {
  1.7501 +      domain = domain.slice().reverse();
  1.7502 +      range = range.slice().reverse();
  1.7503 +    }
  1.7504 +    while (++j <= k) {
  1.7505 +      u.push(uninterpolate(domain[j - 1], domain[j]));
  1.7506 +      i.push(interpolate(range[j - 1], range[j]));
  1.7507 +    }
  1.7508 +    return function(x) {
  1.7509 +      var j = d3.bisect(domain, x, 1, k) - 1;
  1.7510 +      return i[j](u[j](x));
  1.7511 +    };
  1.7512 +  }
  1.7513 +  d3.scale.linear = function() {
  1.7514 +    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
  1.7515 +  };
  1.7516 +  function d3_scale_linear(domain, range, interpolate, clamp) {
  1.7517 +    var output, input;
  1.7518 +    function rescale() {
  1.7519 +      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
  1.7520 +      output = linear(domain, range, uninterpolate, interpolate);
  1.7521 +      input = linear(range, domain, uninterpolate, d3_interpolate);
  1.7522 +      return scale;
  1.7523 +    }
  1.7524 +    function scale(x) {
  1.7525 +      return output(x);
  1.7526 +    }
  1.7527 +    scale.invert = function(y) {
  1.7528 +      return input(y);
  1.7529 +    };
  1.7530 +    scale.domain = function(x) {
  1.7531 +      if (!arguments.length) return domain;
  1.7532 +      domain = x.map(Number);
  1.7533 +      return rescale();
  1.7534 +    };
  1.7535 +    scale.range = function(x) {
  1.7536 +      if (!arguments.length) return range;
  1.7537 +      range = x;
  1.7538 +      return rescale();
  1.7539 +    };
  1.7540 +    scale.rangeRound = function(x) {
  1.7541 +      return scale.range(x).interpolate(d3_interpolateRound);
  1.7542 +    };
  1.7543 +    scale.clamp = function(x) {
  1.7544 +      if (!arguments.length) return clamp;
  1.7545 +      clamp = x;
  1.7546 +      return rescale();
  1.7547 +    };
  1.7548 +    scale.interpolate = function(x) {
  1.7549 +      if (!arguments.length) return interpolate;
  1.7550 +      interpolate = x;
  1.7551 +      return rescale();
  1.7552 +    };
  1.7553 +    scale.ticks = function(m) {
  1.7554 +      return d3_scale_linearTicks(domain, m);
  1.7555 +    };
  1.7556 +    scale.tickFormat = function(m, format) {
  1.7557 +      return d3_scale_linearTickFormat(domain, m, format);
  1.7558 +    };
  1.7559 +    scale.nice = function(m) {
  1.7560 +      d3_scale_linearNice(domain, m);
  1.7561 +      return rescale();
  1.7562 +    };
  1.7563 +    scale.copy = function() {
  1.7564 +      return d3_scale_linear(domain, range, interpolate, clamp);
  1.7565 +    };
  1.7566 +    return rescale();
  1.7567 +  }
  1.7568 +  function d3_scale_linearRebind(scale, linear) {
  1.7569 +    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
  1.7570 +  }
  1.7571 +  function d3_scale_linearNice(domain, m) {
  1.7572 +    d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
  1.7573 +    d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
  1.7574 +    return domain;
  1.7575 +  }
  1.7576 +  function d3_scale_linearTickRange(domain, m) {
  1.7577 +    if (m == null) m = 10;
  1.7578 +    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
  1.7579 +    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
  1.7580 +    extent[0] = Math.ceil(extent[0] / step) * step;
  1.7581 +    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
  1.7582 +    extent[2] = step;
  1.7583 +    return extent;
  1.7584 +  }
  1.7585 +  function d3_scale_linearTicks(domain, m) {
  1.7586 +    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
  1.7587 +  }
  1.7588 +  function d3_scale_linearTickFormat(domain, m, format) {
  1.7589 +    var range = d3_scale_linearTickRange(domain, m);
  1.7590 +    if (format) {
  1.7591 +      var match = d3_format_re.exec(format);
  1.7592 +      match.shift();
  1.7593 +      if (match[8] === "s") {
  1.7594 +        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
  1.7595 +        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
  1.7596 +        match[8] = "f";
  1.7597 +        format = d3.format(match.join(""));
  1.7598 +        return function(d) {
  1.7599 +          return format(prefix.scale(d)) + prefix.symbol;
  1.7600 +        };
  1.7601 +      }
  1.7602 +      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
  1.7603 +      format = match.join("");
  1.7604 +    } else {
  1.7605 +      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
  1.7606 +    }
  1.7607 +    return d3.format(format);
  1.7608 +  }
  1.7609 +  var d3_scale_linearFormatSignificant = {
  1.7610 +    s: 1,
  1.7611 +    g: 1,
  1.7612 +    p: 1,
  1.7613 +    r: 1,
  1.7614 +    e: 1
  1.7615 +  };
  1.7616 +  function d3_scale_linearPrecision(value) {
  1.7617 +    return -Math.floor(Math.log(value) / Math.LN10 + .01);
  1.7618 +  }
  1.7619 +  function d3_scale_linearFormatPrecision(type, range) {
  1.7620 +    var p = d3_scale_linearPrecision(range[2]);
  1.7621 +    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
  1.7622 +  }
  1.7623 +  d3.scale.log = function() {
  1.7624 +    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
  1.7625 +  };
  1.7626 +  function d3_scale_log(linear, base, positive, domain) {
  1.7627 +    function log(x) {
  1.7628 +      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
  1.7629 +    }
  1.7630 +    function pow(x) {
  1.7631 +      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
  1.7632 +    }
  1.7633 +    function scale(x) {
  1.7634 +      return linear(log(x));
  1.7635 +    }
  1.7636 +    scale.invert = function(x) {
  1.7637 +      return pow(linear.invert(x));
  1.7638 +    };
  1.7639 +    scale.domain = function(x) {
  1.7640 +      if (!arguments.length) return domain;
  1.7641 +      positive = x[0] >= 0;
  1.7642 +      linear.domain((domain = x.map(Number)).map(log));
  1.7643 +      return scale;
  1.7644 +    };
  1.7645 +    scale.base = function(_) {
  1.7646 +      if (!arguments.length) return base;
  1.7647 +      base = +_;
  1.7648 +      linear.domain(domain.map(log));
  1.7649 +      return scale;
  1.7650 +    };
  1.7651 +    scale.nice = function() {
  1.7652 +      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
  1.7653 +      linear.domain(niced);
  1.7654 +      domain = niced.map(pow);
  1.7655 +      return scale;
  1.7656 +    };
  1.7657 +    scale.ticks = function() {
  1.7658 +      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
  1.7659 +      if (isFinite(j - i)) {
  1.7660 +        if (positive) {
  1.7661 +          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
  1.7662 +          ticks.push(pow(i));
  1.7663 +        } else {
  1.7664 +          ticks.push(pow(i));
  1.7665 +          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
  1.7666 +        }
  1.7667 +        for (i = 0; ticks[i] < u; i++) {}
  1.7668 +        for (j = ticks.length; ticks[j - 1] > v; j--) {}
  1.7669 +        ticks = ticks.slice(i, j);
  1.7670 +      }
  1.7671 +      return ticks;
  1.7672 +    };
  1.7673 +    scale.tickFormat = function(n, format) {
  1.7674 +      if (!arguments.length) return d3_scale_logFormat;
  1.7675 +      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
  1.7676 +      var k = Math.max(1, base * n / scale.ticks().length);
  1.7677 +      return function(d) {
  1.7678 +        var i = d / pow(Math.round(log(d)));
  1.7679 +        if (i * base < base - .5) i *= base;
  1.7680 +        return i <= k ? format(d) : "";
  1.7681 +      };
  1.7682 +    };
  1.7683 +    scale.copy = function() {
  1.7684 +      return d3_scale_log(linear.copy(), base, positive, domain);
  1.7685 +    };
  1.7686 +    return d3_scale_linearRebind(scale, linear);
  1.7687 +  }
  1.7688 +  var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
  1.7689 +    floor: function(x) {
  1.7690 +      return -Math.ceil(-x);
  1.7691 +    },
  1.7692 +    ceil: function(x) {
  1.7693 +      return -Math.floor(-x);
  1.7694 +    }
  1.7695 +  };
  1.7696 +  d3.scale.pow = function() {
  1.7697 +    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
  1.7698 +  };
  1.7699 +  function d3_scale_pow(linear, exponent, domain) {
  1.7700 +    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
  1.7701 +    function scale(x) {
  1.7702 +      return linear(powp(x));
  1.7703 +    }
  1.7704 +    scale.invert = function(x) {
  1.7705 +      return powb(linear.invert(x));
  1.7706 +    };
  1.7707 +    scale.domain = function(x) {
  1.7708 +      if (!arguments.length) return domain;
  1.7709 +      linear.domain((domain = x.map(Number)).map(powp));
  1.7710 +      return scale;
  1.7711 +    };
  1.7712 +    scale.ticks = function(m) {
  1.7713 +      return d3_scale_linearTicks(domain, m);
  1.7714 +    };
  1.7715 +    scale.tickFormat = function(m, format) {
  1.7716 +      return d3_scale_linearTickFormat(domain, m, format);
  1.7717 +    };
  1.7718 +    scale.nice = function(m) {
  1.7719 +      return scale.domain(d3_scale_linearNice(domain, m));
  1.7720 +    };
  1.7721 +    scale.exponent = function(x) {
  1.7722 +      if (!arguments.length) return exponent;
  1.7723 +      powp = d3_scale_powPow(exponent = x);
  1.7724 +      powb = d3_scale_powPow(1 / exponent);
  1.7725 +      linear.domain(domain.map(powp));
  1.7726 +      return scale;
  1.7727 +    };
  1.7728 +    scale.copy = function() {
  1.7729 +      return d3_scale_pow(linear.copy(), exponent, domain);
  1.7730 +    };
  1.7731 +    return d3_scale_linearRebind(scale, linear);
  1.7732 +  }
  1.7733 +  function d3_scale_powPow(e) {
  1.7734 +    return function(x) {
  1.7735 +      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
  1.7736 +    };
  1.7737 +  }
  1.7738 +  d3.scale.sqrt = function() {
  1.7739 +    return d3.scale.pow().exponent(.5);
  1.7740 +  };
  1.7741 +  d3.scale.ordinal = function() {
  1.7742 +    return d3_scale_ordinal([], {
  1.7743 +      t: "range",
  1.7744 +      a: [ [] ]
  1.7745 +    });
  1.7746 +  };
  1.7747 +  function d3_scale_ordinal(domain, ranger) {
  1.7748 +    var index, range, rangeBand;
  1.7749 +    function scale(x) {
  1.7750 +      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
  1.7751 +    }
  1.7752 +    function steps(start, step) {
  1.7753 +      return d3.range(domain.length).map(function(i) {
  1.7754 +        return start + step * i;
  1.7755 +      });
  1.7756 +    }
  1.7757 +    scale.domain = function(x) {
  1.7758 +      if (!arguments.length) return domain;
  1.7759 +      domain = [];
  1.7760 +      index = new d3_Map();
  1.7761 +      var i = -1, n = x.length, xi;
  1.7762 +      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
  1.7763 +      return scale[ranger.t].apply(scale, ranger.a);
  1.7764 +    };
  1.7765 +    scale.range = function(x) {
  1.7766 +      if (!arguments.length) return range;
  1.7767 +      range = x;
  1.7768 +      rangeBand = 0;
  1.7769 +      ranger = {
  1.7770 +        t: "range",
  1.7771 +        a: arguments
  1.7772 +      };
  1.7773 +      return scale;
  1.7774 +    };
  1.7775 +    scale.rangePoints = function(x, padding) {
  1.7776 +      if (arguments.length < 2) padding = 0;
  1.7777 +      var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, 
  1.7778 +      0) : (stop - start) / (domain.length - 1 + padding);
  1.7779 +      range = steps(start + step * padding / 2, step);
  1.7780 +      rangeBand = 0;
  1.7781 +      ranger = {
  1.7782 +        t: "rangePoints",
  1.7783 +        a: arguments
  1.7784 +      };
  1.7785 +      return scale;
  1.7786 +    };
  1.7787 +    scale.rangeRoundPoints = function(x, padding) {
  1.7788 +      if (arguments.length < 2) padding = 0;
  1.7789 +      var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), 
  1.7790 +      0) : (stop - start) / (domain.length - 1 + padding) | 0;
  1.7791 +      range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
  1.7792 +      rangeBand = 0;
  1.7793 +      ranger = {
  1.7794 +        t: "rangeRoundPoints",
  1.7795 +        a: arguments
  1.7796 +      };
  1.7797 +      return scale;
  1.7798 +    };
  1.7799 +    scale.rangeBands = function(x, padding, outerPadding) {
  1.7800 +      if (arguments.length < 2) padding = 0;
  1.7801 +      if (arguments.length < 3) outerPadding = padding;
  1.7802 +      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
  1.7803 +      range = steps(start + step * outerPadding, step);
  1.7804 +      if (reverse) range.reverse();
  1.7805 +      rangeBand = step * (1 - padding);
  1.7806 +      ranger = {
  1.7807 +        t: "rangeBands",
  1.7808 +        a: arguments
  1.7809 +      };
  1.7810 +      return scale;
  1.7811 +    };
  1.7812 +    scale.rangeRoundBands = function(x, padding, outerPadding) {
  1.7813 +      if (arguments.length < 2) padding = 0;
  1.7814 +      if (arguments.length < 3) outerPadding = padding;
  1.7815 +      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
  1.7816 +      range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
  1.7817 +      if (reverse) range.reverse();
  1.7818 +      rangeBand = Math.round(step * (1 - padding));
  1.7819 +      ranger = {
  1.7820 +        t: "rangeRoundBands",
  1.7821 +        a: arguments
  1.7822 +      };
  1.7823 +      return scale;
  1.7824 +    };
  1.7825 +    scale.rangeBand = function() {
  1.7826 +      return rangeBand;
  1.7827 +    };
  1.7828 +    scale.rangeExtent = function() {
  1.7829 +      return d3_scaleExtent(ranger.a[0]);
  1.7830 +    };
  1.7831 +    scale.copy = function() {
  1.7832 +      return d3_scale_ordinal(domain, ranger);
  1.7833 +    };
  1.7834 +    return scale.domain(domain);
  1.7835 +  }
  1.7836 +  d3.scale.category10 = function() {
  1.7837 +    return d3.scale.ordinal().range(d3_category10);
  1.7838 +  };
  1.7839 +  d3.scale.category20 = function() {
  1.7840 +    return d3.scale.ordinal().range(d3_category20);
  1.7841 +  };
  1.7842 +  d3.scale.category20b = function() {
  1.7843 +    return d3.scale.ordinal().range(d3_category20b);
  1.7844 +  };
  1.7845 +  d3.scale.category20c = function() {
  1.7846 +    return d3.scale.ordinal().range(d3_category20c);
  1.7847 +  };
  1.7848 +  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
  1.7849 +  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
  1.7850 +  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
  1.7851 +  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
  1.7852 +  d3.scale.quantile = function() {
  1.7853 +    return d3_scale_quantile([], []);
  1.7854 +  };
  1.7855 +  function d3_scale_quantile(domain, range) {
  1.7856 +    var thresholds;
  1.7857 +    function rescale() {
  1.7858 +      var k = 0, q = range.length;
  1.7859 +      thresholds = [];
  1.7860 +      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
  1.7861 +      return scale;
  1.7862 +    }
  1.7863 +    function scale(x) {
  1.7864 +      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
  1.7865 +    }
  1.7866 +    scale.domain = function(x) {
  1.7867 +      if (!arguments.length) return domain;
  1.7868 +      domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
  1.7869 +      return rescale();
  1.7870 +    };
  1.7871 +    scale.range = function(x) {
  1.7872 +      if (!arguments.length) return range;
  1.7873 +      range = x;
  1.7874 +      return rescale();
  1.7875 +    };
  1.7876 +    scale.quantiles = function() {
  1.7877 +      return thresholds;
  1.7878 +    };
  1.7879 +    scale.invertExtent = function(y) {
  1.7880 +      y = range.indexOf(y);
  1.7881 +      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
  1.7882 +    };
  1.7883 +    scale.copy = function() {
  1.7884 +      return d3_scale_quantile(domain, range);
  1.7885 +    };
  1.7886 +    return rescale();
  1.7887 +  }
  1.7888 +  d3.scale.quantize = function() {
  1.7889 +    return d3_scale_quantize(0, 1, [ 0, 1 ]);
  1.7890 +  };
  1.7891 +  function d3_scale_quantize(x0, x1, range) {
  1.7892 +    var kx, i;
  1.7893 +    function scale(x) {
  1.7894 +      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
  1.7895 +    }
  1.7896 +    function rescale() {
  1.7897 +      kx = range.length / (x1 - x0);
  1.7898 +      i = range.length - 1;
  1.7899 +      return scale;
  1.7900 +    }
  1.7901 +    scale.domain = function(x) {
  1.7902 +      if (!arguments.length) return [ x0, x1 ];
  1.7903 +      x0 = +x[0];
  1.7904 +      x1 = +x[x.length - 1];
  1.7905 +      return rescale();
  1.7906 +    };
  1.7907 +    scale.range = function(x) {
  1.7908 +      if (!arguments.length) return range;
  1.7909 +      range = x;
  1.7910 +      return rescale();
  1.7911 +    };
  1.7912 +    scale.invertExtent = function(y) {
  1.7913 +      y = range.indexOf(y);
  1.7914 +      y = y < 0 ? NaN : y / kx + x0;
  1.7915 +      return [ y, y + 1 / kx ];
  1.7916 +    };
  1.7917 +    scale.copy = function() {
  1.7918 +      return d3_scale_quantize(x0, x1, range);
  1.7919 +    };
  1.7920 +    return rescale();
  1.7921 +  }
  1.7922 +  d3.scale.threshold = function() {
  1.7923 +    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
  1.7924 +  };
  1.7925 +  function d3_scale_threshold(domain, range) {
  1.7926 +    function scale(x) {
  1.7927 +      if (x <= x) return range[d3.bisect(domain, x)];
  1.7928 +    }
  1.7929 +    scale.domain = function(_) {
  1.7930 +      if (!arguments.length) return domain;
  1.7931 +      domain = _;
  1.7932 +      return scale;
  1.7933 +    };
  1.7934 +    scale.range = function(_) {
  1.7935 +      if (!arguments.length) return range;
  1.7936 +      range = _;
  1.7937 +      return scale;
  1.7938 +    };
  1.7939 +    scale.invertExtent = function(y) {
  1.7940 +      y = range.indexOf(y);
  1.7941 +      return [ domain[y - 1], domain[y] ];
  1.7942 +    };
  1.7943 +    scale.copy = function() {
  1.7944 +      return d3_scale_threshold(domain, range);
  1.7945 +    };
  1.7946 +    return scale;
  1.7947 +  }
  1.7948 +  d3.scale.identity = function() {
  1.7949 +    return d3_scale_identity([ 0, 1 ]);
  1.7950 +  };
  1.7951 +  function d3_scale_identity(domain) {
  1.7952 +    function identity(x) {
  1.7953 +      return +x;
  1.7954 +    }
  1.7955 +    identity.invert = identity;
  1.7956 +    identity.domain = identity.range = function(x) {
  1.7957 +      if (!arguments.length) return domain;
  1.7958 +      domain = x.map(identity);
  1.7959 +      return identity;
  1.7960 +    };
  1.7961 +    identity.ticks = function(m) {
  1.7962 +      return d3_scale_linearTicks(domain, m);
  1.7963 +    };
  1.7964 +    identity.tickFormat = function(m, format) {
  1.7965 +      return d3_scale_linearTickFormat(domain, m, format);
  1.7966 +    };
  1.7967 +    identity.copy = function() {
  1.7968 +      return d3_scale_identity(domain);
  1.7969 +    };
  1.7970 +    return identity;
  1.7971 +  }
  1.7972 +  d3.svg = {};
  1.7973 +  function d3_zero() {
  1.7974 +    return 0;
  1.7975 +  }
  1.7976 +  d3.svg.arc = function() {
  1.7977 +    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle;
  1.7978 +    function arc() {
  1.7979 +      var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1;
  1.7980 +      if (r1 < r0) rc = r1, r1 = r0, r0 = rc;
  1.7981 +      if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z";
  1.7982 +      var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = [];
  1.7983 +      if (ap = (+padAngle.apply(this, arguments) || 0) / 2) {
  1.7984 +        rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments);
  1.7985 +        if (!cw) p1 *= -1;
  1.7986 +        if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap));
  1.7987 +        if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap));
  1.7988 +      }
  1.7989 +      if (r1) {
  1.7990 +        x0 = r1 * Math.cos(a0 + p1);
  1.7991 +        y0 = r1 * Math.sin(a0 + p1);
  1.7992 +        x1 = r1 * Math.cos(a1 - p1);
  1.7993 +        y1 = r1 * Math.sin(a1 - p1);
  1.7994 +        var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1;
  1.7995 +        if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
  1.7996 +          var h1 = (a0 + a1) / 2;
  1.7997 +          x0 = r1 * Math.cos(h1);
  1.7998 +          y0 = r1 * Math.sin(h1);
  1.7999 +          x1 = y1 = null;
  1.8000 +        }
  1.8001 +      } else {
  1.8002 +        x0 = y0 = 0;
  1.8003 +      }
  1.8004 +      if (r0) {
  1.8005 +        x2 = r0 * Math.cos(a1 - p0);
  1.8006 +        y2 = r0 * Math.sin(a1 - p0);
  1.8007 +        x3 = r0 * Math.cos(a0 + p0);
  1.8008 +        y3 = r0 * Math.sin(a0 + p0);
  1.8009 +        var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1;
  1.8010 +        if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) {
  1.8011 +          var h0 = (a0 + a1) / 2;
  1.8012 +          x2 = r0 * Math.cos(h0);
  1.8013 +          y2 = r0 * Math.sin(h0);
  1.8014 +          x3 = y3 = null;
  1.8015 +        }
  1.8016 +      } else {
  1.8017 +        x2 = y2 = 0;
  1.8018 +      }
  1.8019 +      if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) {
  1.8020 +        cr = r0 < r1 ^ cw ? 0 : 1;
  1.8021 +        var rc1 = rc, rc0 = rc;
  1.8022 +        if (da < π) {
  1.8023 +          var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
  1.8024 +          rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
  1.8025 +          rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
  1.8026 +        }
  1.8027 +        if (x1 != null) {
  1.8028 +          var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw);
  1.8029 +          if (rc === rc1) {
  1.8030 +            path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
  1.8031 +          } else {
  1.8032 +            path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
  1.8033 +          }
  1.8034 +        } else {
  1.8035 +          path.push("M", x0, ",", y0);
  1.8036 +        }
  1.8037 +        if (x3 != null) {
  1.8038 +          var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
  1.8039 +          if (rc === rc0) {
  1.8040 +            path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
  1.8041 +          } else {
  1.8042 +            path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
  1.8043 +          }
  1.8044 +        } else {
  1.8045 +          path.push("L", x2, ",", y2);
  1.8046 +        }
  1.8047 +      } else {
  1.8048 +        path.push("M", x0, ",", y0);
  1.8049 +        if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1);
  1.8050 +        path.push("L", x2, ",", y2);
  1.8051 +        if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3);
  1.8052 +      }
  1.8053 +      path.push("Z");
  1.8054 +      return path.join("");
  1.8055 +    }
  1.8056 +    function circleSegment(r1, cw) {
  1.8057 +      return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1;
  1.8058 +    }
  1.8059 +    arc.innerRadius = function(v) {
  1.8060 +      if (!arguments.length) return innerRadius;
  1.8061 +      innerRadius = d3_functor(v);
  1.8062 +      return arc;
  1.8063 +    };
  1.8064 +    arc.outerRadius = function(v) {
  1.8065 +      if (!arguments.length) return outerRadius;
  1.8066 +      outerRadius = d3_functor(v);
  1.8067 +      return arc;
  1.8068 +    };
  1.8069 +    arc.cornerRadius = function(v) {
  1.8070 +      if (!arguments.length) return cornerRadius;
  1.8071 +      cornerRadius = d3_functor(v);
  1.8072 +      return arc;
  1.8073 +    };
  1.8074 +    arc.padRadius = function(v) {
  1.8075 +      if (!arguments.length) return padRadius;
  1.8076 +      padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v);
  1.8077 +      return arc;
  1.8078 +    };
  1.8079 +    arc.startAngle = function(v) {
  1.8080 +      if (!arguments.length) return startAngle;
  1.8081 +      startAngle = d3_functor(v);
  1.8082 +      return arc;
  1.8083 +    };
  1.8084 +    arc.endAngle = function(v) {
  1.8085 +      if (!arguments.length) return endAngle;
  1.8086 +      endAngle = d3_functor(v);
  1.8087 +      return arc;
  1.8088 +    };
  1.8089 +    arc.padAngle = function(v) {
  1.8090 +      if (!arguments.length) return padAngle;
  1.8091 +      padAngle = d3_functor(v);
  1.8092 +      return arc;
  1.8093 +    };
  1.8094 +    arc.centroid = function() {
  1.8095 +      var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ;
  1.8096 +      return [ Math.cos(a) * r, Math.sin(a) * r ];
  1.8097 +    };
  1.8098 +    return arc;
  1.8099 +  };
  1.8100 +  var d3_svg_arcAuto = "auto";
  1.8101 +  function d3_svg_arcInnerRadius(d) {
  1.8102 +    return d.innerRadius;
  1.8103 +  }
  1.8104 +  function d3_svg_arcOuterRadius(d) {
  1.8105 +    return d.outerRadius;
  1.8106 +  }
  1.8107 +  function d3_svg_arcStartAngle(d) {
  1.8108 +    return d.startAngle;
  1.8109 +  }
  1.8110 +  function d3_svg_arcEndAngle(d) {
  1.8111 +    return d.endAngle;
  1.8112 +  }
  1.8113 +  function d3_svg_arcPadAngle(d) {
  1.8114 +    return d && d.padAngle;
  1.8115 +  }
  1.8116 +  function d3_svg_arcSweep(x0, y0, x1, y1) {
  1.8117 +    return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
  1.8118 +  }
  1.8119 +  function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) {
  1.8120 +    var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3;
  1.8121 +    if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
  1.8122 +    return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ];
  1.8123 +  }
  1.8124 +  function d3_svg_line(projection) {
  1.8125 +    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
  1.8126 +    function line(data) {
  1.8127 +      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
  1.8128 +      function segment() {
  1.8129 +        segments.push("M", interpolate(projection(points), tension));
  1.8130 +      }
  1.8131 +      while (++i < n) {
  1.8132 +        if (defined.call(this, d = data[i], i)) {
  1.8133 +          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
  1.8134 +        } else if (points.length) {
  1.8135 +          segment();
  1.8136 +          points = [];
  1.8137 +        }
  1.8138 +      }
  1.8139 +      if (points.length) segment();
  1.8140 +      return segments.length ? segments.join("") : null;
  1.8141 +    }
  1.8142 +    line.x = function(_) {
  1.8143 +      if (!arguments.length) return x;
  1.8144 +      x = _;
  1.8145 +      return line;
  1.8146 +    };
  1.8147 +    line.y = function(_) {
  1.8148 +      if (!arguments.length) return y;
  1.8149 +      y = _;
  1.8150 +      return line;
  1.8151 +    };
  1.8152 +    line.defined = function(_) {
  1.8153 +      if (!arguments.length) return defined;
  1.8154 +      defined = _;
  1.8155 +      return line;
  1.8156 +    };
  1.8157 +    line.interpolate = function(_) {
  1.8158 +      if (!arguments.length) return interpolateKey;
  1.8159 +      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
  1.8160 +      return line;
  1.8161 +    };
  1.8162 +    line.tension = function(_) {
  1.8163 +      if (!arguments.length) return tension;
  1.8164 +      tension = _;
  1.8165 +      return line;
  1.8166 +    };
  1.8167 +    return line;
  1.8168 +  }
  1.8169 +  d3.svg.line = function() {
  1.8170 +    return d3_svg_line(d3_identity);
  1.8171 +  };
  1.8172 +  var d3_svg_lineInterpolators = d3.map({
  1.8173 +    linear: d3_svg_lineLinear,
  1.8174 +    "linear-closed": d3_svg_lineLinearClosed,
  1.8175 +    step: d3_svg_lineStep,
  1.8176 +    "step-before": d3_svg_lineStepBefore,
  1.8177 +    "step-after": d3_svg_lineStepAfter,
  1.8178 +    basis: d3_svg_lineBasis,
  1.8179 +    "basis-open": d3_svg_lineBasisOpen,
  1.8180 +    "basis-closed": d3_svg_lineBasisClosed,
  1.8181 +    bundle: d3_svg_lineBundle,
  1.8182 +    cardinal: d3_svg_lineCardinal,
  1.8183 +    "cardinal-open": d3_svg_lineCardinalOpen,
  1.8184 +    "cardinal-closed": d3_svg_lineCardinalClosed,
  1.8185 +    monotone: d3_svg_lineMonotone
  1.8186 +  });
  1.8187 +  d3_svg_lineInterpolators.forEach(function(key, value) {
  1.8188 +    value.key = key;
  1.8189 +    value.closed = /-closed$/.test(key);
  1.8190 +  });
  1.8191 +  function d3_svg_lineLinear(points) {
  1.8192 +    return points.length > 1 ? points.join("L") : points + "Z";
  1.8193 +  }
  1.8194 +  function d3_svg_lineLinearClosed(points) {
  1.8195 +    return points.join("L") + "Z";
  1.8196 +  }
  1.8197 +  function d3_svg_lineStep(points) {
  1.8198 +    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
  1.8199 +    while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
  1.8200 +    if (n > 1) path.push("H", p[0]);
  1.8201 +    return path.join("");
  1.8202 +  }
  1.8203 +  function d3_svg_lineStepBefore(points) {
  1.8204 +    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
  1.8205 +    while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
  1.8206 +    return path.join("");
  1.8207 +  }
  1.8208 +  function d3_svg_lineStepAfter(points) {
  1.8209 +    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
  1.8210 +    while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
  1.8211 +    return path.join("");
  1.8212 +  }
  1.8213 +  function d3_svg_lineCardinalOpen(points, tension) {
  1.8214 +    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension));
  1.8215 +  }
  1.8216 +  function d3_svg_lineCardinalClosed(points, tension) {
  1.8217 +    return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
  1.8218 +    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
  1.8219 +  }
  1.8220 +  function d3_svg_lineCardinal(points, tension) {
  1.8221 +    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
  1.8222 +  }
  1.8223 +  function d3_svg_lineHermite(points, tangents) {
  1.8224 +    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
  1.8225 +      return d3_svg_lineLinear(points);
  1.8226 +    }
  1.8227 +    var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
  1.8228 +    if (quad) {
  1.8229 +      path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
  1.8230 +      p0 = points[1];
  1.8231 +      pi = 2;
  1.8232 +    }
  1.8233 +    if (tangents.length > 1) {
  1.8234 +      t = tangents[1];
  1.8235 +      p = points[pi];
  1.8236 +      pi++;
  1.8237 +      path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
  1.8238 +      for (var i = 2; i < tangents.length; i++, pi++) {
  1.8239 +        p = points[pi];
  1.8240 +        t = tangents[i];
  1.8241 +        path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
  1.8242 +      }
  1.8243 +    }
  1.8244 +    if (quad) {
  1.8245 +      var lp = points[pi];
  1.8246 +      path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
  1.8247 +    }
  1.8248 +    return path;
  1.8249 +  }
  1.8250 +  function d3_svg_lineCardinalTangents(points, tension) {
  1.8251 +    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
  1.8252 +    while (++i < n) {
  1.8253 +      p0 = p1;
  1.8254 +      p1 = p2;
  1.8255 +      p2 = points[i];
  1.8256 +      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
  1.8257 +    }
  1.8258 +    return tangents;
  1.8259 +  }
  1.8260 +  function d3_svg_lineBasis(points) {
  1.8261 +    if (points.length < 3) return d3_svg_lineLinear(points);
  1.8262 +    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
  1.8263 +    points.push(points[n - 1]);
  1.8264 +    while (++i <= n) {
  1.8265 +      pi = points[i];
  1.8266 +      px.shift();
  1.8267 +      px.push(pi[0]);
  1.8268 +      py.shift();
  1.8269 +      py.push(pi[1]);
  1.8270 +      d3_svg_lineBasisBezier(path, px, py);
  1.8271 +    }
  1.8272 +    points.pop();
  1.8273 +    path.push("L", pi);
  1.8274 +    return path.join("");
  1.8275 +  }
  1.8276 +  function d3_svg_lineBasisOpen(points) {
  1.8277 +    if (points.length < 4) return d3_svg_lineLinear(points);
  1.8278 +    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
  1.8279 +    while (++i < 3) {
  1.8280 +      pi = points[i];
  1.8281 +      px.push(pi[0]);
  1.8282 +      py.push(pi[1]);
  1.8283 +    }
  1.8284 +    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
  1.8285 +    --i;
  1.8286 +    while (++i < n) {
  1.8287 +      pi = points[i];
  1.8288 +      px.shift();
  1.8289 +      px.push(pi[0]);
  1.8290 +      py.shift();
  1.8291 +      py.push(pi[1]);
  1.8292 +      d3_svg_lineBasisBezier(path, px, py);
  1.8293 +    }
  1.8294 +    return path.join("");
  1.8295 +  }
  1.8296 +  function d3_svg_lineBasisClosed(points) {
  1.8297 +    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
  1.8298 +    while (++i < 4) {
  1.8299 +      pi = points[i % n];
  1.8300 +      px.push(pi[0]);
  1.8301 +      py.push(pi[1]);
  1.8302 +    }
  1.8303 +    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
  1.8304 +    --i;
  1.8305 +    while (++i < m) {
  1.8306 +      pi = points[i % n];
  1.8307 +      px.shift();
  1.8308 +      px.push(pi[0]);
  1.8309 +      py.shift();
  1.8310 +      py.push(pi[1]);
  1.8311 +      d3_svg_lineBasisBezier(path, px, py);
  1.8312 +    }
  1.8313 +    return path.join("");
  1.8314 +  }
  1.8315 +  function d3_svg_lineBundle(points, tension) {
  1.8316 +    var n = points.length - 1;
  1.8317 +    if (n) {
  1.8318 +      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
  1.8319 +      while (++i <= n) {
  1.8320 +        p = points[i];
  1.8321 +        t = i / n;
  1.8322 +        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
  1.8323 +        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
  1.8324 +      }
  1.8325 +    }
  1.8326 +    return d3_svg_lineBasis(points);
  1.8327 +  }
  1.8328 +  function d3_svg_lineDot4(a, b) {
  1.8329 +    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  1.8330 +  }
  1.8331 +  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
  1.8332 +  function d3_svg_lineBasisBezier(path, x, y) {
  1.8333 +    path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
  1.8334 +  }
  1.8335 +  function d3_svg_lineSlope(p0, p1) {
  1.8336 +    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
  1.8337 +  }
  1.8338 +  function d3_svg_lineFiniteDifferences(points) {
  1.8339 +    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
  1.8340 +    while (++i < j) {
  1.8341 +      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
  1.8342 +    }
  1.8343 +    m[i] = d;
  1.8344 +    return m;
  1.8345 +  }
  1.8346 +  function d3_svg_lineMonotoneTangents(points) {
  1.8347 +    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
  1.8348 +    while (++i < j) {
  1.8349 +      d = d3_svg_lineSlope(points[i], points[i + 1]);
  1.8350 +      if (abs(d) < ε) {
  1.8351 +        m[i] = m[i + 1] = 0;
  1.8352 +      } else {
  1.8353 +        a = m[i] / d;
  1.8354 +        b = m[i + 1] / d;
  1.8355 +        s = a * a + b * b;
  1.8356 +        if (s > 9) {
  1.8357 +          s = d * 3 / Math.sqrt(s);
  1.8358 +          m[i] = s * a;
  1.8359 +          m[i + 1] = s * b;
  1.8360 +        }
  1.8361 +      }
  1.8362 +    }
  1.8363 +    i = -1;
  1.8364 +    while (++i <= j) {
  1.8365 +      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
  1.8366 +      tangents.push([ s || 0, m[i] * s || 0 ]);
  1.8367 +    }
  1.8368 +    return tangents;
  1.8369 +  }
  1.8370 +  function d3_svg_lineMonotone(points) {
  1.8371 +    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
  1.8372 +  }
  1.8373 +  d3.svg.line.radial = function() {
  1.8374 +    var line = d3_svg_line(d3_svg_lineRadial);
  1.8375 +    line.radius = line.x, delete line.x;
  1.8376 +    line.angle = line.y, delete line.y;
  1.8377 +    return line;
  1.8378 +  };
  1.8379 +  function d3_svg_lineRadial(points) {
  1.8380 +    var point, i = -1, n = points.length, r, a;
  1.8381 +    while (++i < n) {
  1.8382 +      point = points[i];
  1.8383 +      r = point[0];
  1.8384 +      a = point[1] - halfπ;
  1.8385 +      point[0] = r * Math.cos(a);
  1.8386 +      point[1] = r * Math.sin(a);
  1.8387 +    }
  1.8388 +    return points;
  1.8389 +  }
  1.8390 +  function d3_svg_area(projection) {
  1.8391 +    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
  1.8392 +    function area(data) {
  1.8393 +      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
  1.8394 +        return x;
  1.8395 +      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
  1.8396 +        return y;
  1.8397 +      } : d3_functor(y1), x, y;
  1.8398 +      function segment() {
  1.8399 +        segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
  1.8400 +      }
  1.8401 +      while (++i < n) {
  1.8402 +        if (defined.call(this, d = data[i], i)) {
  1.8403 +          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
  1.8404 +          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
  1.8405 +        } else if (points0.length) {
  1.8406 +          segment();
  1.8407 +          points0 = [];
  1.8408 +          points1 = [];
  1.8409 +        }
  1.8410 +      }
  1.8411 +      if (points0.length) segment();
  1.8412 +      return segments.length ? segments.join("") : null;
  1.8413 +    }
  1.8414 +    area.x = function(_) {
  1.8415 +      if (!arguments.length) return x1;
  1.8416 +      x0 = x1 = _;
  1.8417 +      return area;
  1.8418 +    };
  1.8419 +    area.x0 = function(_) {
  1.8420 +      if (!arguments.length) return x0;
  1.8421 +      x0 = _;
  1.8422 +      return area;
  1.8423 +    };
  1.8424 +    area.x1 = function(_) {
  1.8425 +      if (!arguments.length) return x1;
  1.8426 +      x1 = _;
  1.8427 +      return area;
  1.8428 +    };
  1.8429 +    area.y = function(_) {
  1.8430 +      if (!arguments.length) return y1;
  1.8431 +      y0 = y1 = _;
  1.8432 +      return area;
  1.8433 +    };
  1.8434 +    area.y0 = function(_) {
  1.8435 +      if (!arguments.length) return y0;
  1.8436 +      y0 = _;
  1.8437 +      return area;
  1.8438 +    };
  1.8439 +    area.y1 = function(_) {
  1.8440 +      if (!arguments.length) return y1;
  1.8441 +      y1 = _;
  1.8442 +      return area;
  1.8443 +    };
  1.8444 +    area.defined = function(_) {
  1.8445 +      if (!arguments.length) return defined;
  1.8446 +      defined = _;
  1.8447 +      return area;
  1.8448 +    };
  1.8449 +    area.interpolate = function(_) {
  1.8450 +      if (!arguments.length) return interpolateKey;
  1.8451 +      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
  1.8452 +      interpolateReverse = interpolate.reverse || interpolate;
  1.8453 +      L = interpolate.closed ? "M" : "L";
  1.8454 +      return area;
  1.8455 +    };
  1.8456 +    area.tension = function(_) {
  1.8457 +      if (!arguments.length) return tension;
  1.8458 +      tension = _;
  1.8459 +      return area;
  1.8460 +    };
  1.8461 +    return area;
  1.8462 +  }
  1.8463 +  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
  1.8464 +  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
  1.8465 +  d3.svg.area = function() {
  1.8466 +    return d3_svg_area(d3_identity);
  1.8467 +  };
  1.8468 +  d3.svg.area.radial = function() {
  1.8469 +    var area = d3_svg_area(d3_svg_lineRadial);
  1.8470 +    area.radius = area.x, delete area.x;
  1.8471 +    area.innerRadius = area.x0, delete area.x0;
  1.8472 +    area.outerRadius = area.x1, delete area.x1;
  1.8473 +    area.angle = area.y, delete area.y;
  1.8474 +    area.startAngle = area.y0, delete area.y0;
  1.8475 +    area.endAngle = area.y1, delete area.y1;
  1.8476 +    return area;
  1.8477 +  };
  1.8478 +  d3.svg.chord = function() {
  1.8479 +    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
  1.8480 +    function chord(d, i) {
  1.8481 +      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
  1.8482 +      return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
  1.8483 +    }
  1.8484 +    function subgroup(self, f, d, i) {
  1.8485 +      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ;
  1.8486 +      return {
  1.8487 +        r: r,
  1.8488 +        a0: a0,
  1.8489 +        a1: a1,
  1.8490 +        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
  1.8491 +        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
  1.8492 +      };
  1.8493 +    }
  1.8494 +    function equals(a, b) {
  1.8495 +      return a.a0 == b.a0 && a.a1 == b.a1;
  1.8496 +    }
  1.8497 +    function arc(r, p, a) {
  1.8498 +      return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
  1.8499 +    }
  1.8500 +    function curve(r0, p0, r1, p1) {
  1.8501 +      return "Q 0,0 " + p1;
  1.8502 +    }
  1.8503 +    chord.radius = function(v) {
  1.8504 +      if (!arguments.length) return radius;
  1.8505 +      radius = d3_functor(v);
  1.8506 +      return chord;
  1.8507 +    };
  1.8508 +    chord.source = function(v) {
  1.8509 +      if (!arguments.length) return source;
  1.8510 +      source = d3_functor(v);
  1.8511 +      return chord;
  1.8512 +    };
  1.8513 +    chord.target = function(v) {
  1.8514 +      if (!arguments.length) return target;
  1.8515 +      target = d3_functor(v);
  1.8516 +      return chord;
  1.8517 +    };
  1.8518 +    chord.startAngle = function(v) {
  1.8519 +      if (!arguments.length) return startAngle;
  1.8520 +      startAngle = d3_functor(v);
  1.8521 +      return chord;
  1.8522 +    };
  1.8523 +    chord.endAngle = function(v) {
  1.8524 +      if (!arguments.length) return endAngle;
  1.8525 +      endAngle = d3_functor(v);
  1.8526 +      return chord;
  1.8527 +    };
  1.8528 +    return chord;
  1.8529 +  };
  1.8530 +  function d3_svg_chordRadius(d) {
  1.8531 +    return d.radius;
  1.8532 +  }
  1.8533 +  d3.svg.diagonal = function() {
  1.8534 +    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
  1.8535 +    function diagonal(d, i) {
  1.8536 +      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
  1.8537 +        x: p0.x,
  1.8538 +        y: m
  1.8539 +      }, {
  1.8540 +        x: p3.x,
  1.8541 +        y: m
  1.8542 +      }, p3 ];
  1.8543 +      p = p.map(projection);
  1.8544 +      return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
  1.8545 +    }
  1.8546 +    diagonal.source = function(x) {
  1.8547 +      if (!arguments.length) return source;
  1.8548 +      source = d3_functor(x);
  1.8549 +      return diagonal;
  1.8550 +    };
  1.8551 +    diagonal.target = function(x) {
  1.8552 +      if (!arguments.length) return target;
  1.8553 +      target = d3_functor(x);
  1.8554 +      return diagonal;
  1.8555 +    };
  1.8556 +    diagonal.projection = function(x) {
  1.8557 +      if (!arguments.length) return projection;
  1.8558 +      projection = x;
  1.8559 +      return diagonal;
  1.8560 +    };
  1.8561 +    return diagonal;
  1.8562 +  };
  1.8563 +  function d3_svg_diagonalProjection(d) {
  1.8564 +    return [ d.x, d.y ];
  1.8565 +  }
  1.8566 +  d3.svg.diagonal.radial = function() {
  1.8567 +    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
  1.8568 +    diagonal.projection = function(x) {
  1.8569 +      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
  1.8570 +    };
  1.8571 +    return diagonal;
  1.8572 +  };
  1.8573 +  function d3_svg_diagonalRadialProjection(projection) {
  1.8574 +    return function() {
  1.8575 +      var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ;
  1.8576 +      return [ r * Math.cos(a), r * Math.sin(a) ];
  1.8577 +    };
  1.8578 +  }
  1.8579 +  d3.svg.symbol = function() {
  1.8580 +    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
  1.8581 +    function symbol(d, i) {
  1.8582 +      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
  1.8583 +    }
  1.8584 +    symbol.type = function(x) {
  1.8585 +      if (!arguments.length) return type;
  1.8586 +      type = d3_functor(x);
  1.8587 +      return symbol;
  1.8588 +    };
  1.8589 +    symbol.size = function(x) {
  1.8590 +      if (!arguments.length) return size;
  1.8591 +      size = d3_functor(x);
  1.8592 +      return symbol;
  1.8593 +    };
  1.8594 +    return symbol;
  1.8595 +  };
  1.8596 +  function d3_svg_symbolSize() {
  1.8597 +    return 64;
  1.8598 +  }
  1.8599 +  function d3_svg_symbolType() {
  1.8600 +    return "circle";
  1.8601 +  }
  1.8602 +  function d3_svg_symbolCircle(size) {
  1.8603 +    var r = Math.sqrt(size / π);
  1.8604 +    return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
  1.8605 +  }
  1.8606 +  var d3_svg_symbols = d3.map({
  1.8607 +    circle: d3_svg_symbolCircle,
  1.8608 +    cross: function(size) {
  1.8609 +      var r = Math.sqrt(size / 5) / 2;
  1.8610 +      return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
  1.8611 +    },
  1.8612 +    diamond: function(size) {
  1.8613 +      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
  1.8614 +      return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
  1.8615 +    },
  1.8616 +    square: function(size) {
  1.8617 +      var r = Math.sqrt(size) / 2;
  1.8618 +      return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
  1.8619 +    },
  1.8620 +    "triangle-down": function(size) {
  1.8621 +      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
  1.8622 +      return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
  1.8623 +    },
  1.8624 +    "triangle-up": function(size) {
  1.8625 +      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
  1.8626 +      return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
  1.8627 +    }
  1.8628 +  });
  1.8629 +  d3.svg.symbolTypes = d3_svg_symbols.keys();
  1.8630 +  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
  1.8631 +  d3_selectionPrototype.transition = function(name) {
  1.8632 +    var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || {
  1.8633 +      time: Date.now(),
  1.8634 +      ease: d3_ease_cubicInOut,
  1.8635 +      delay: 0,
  1.8636 +      duration: 250
  1.8637 +    };
  1.8638 +    for (var j = -1, m = this.length; ++j < m; ) {
  1.8639 +      subgroups.push(subgroup = []);
  1.8640 +      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  1.8641 +        if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
  1.8642 +        subgroup.push(node);
  1.8643 +      }
  1.8644 +    }
  1.8645 +    return d3_transition(subgroups, ns, id);
  1.8646 +  };
  1.8647 +  d3_selectionPrototype.interrupt = function(name) {
  1.8648 +    return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name)));
  1.8649 +  };
  1.8650 +  var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
  1.8651 +  function d3_selection_interruptNS(ns) {
  1.8652 +    return function() {
  1.8653 +      var lock, activeId, active;
  1.8654 +      if ((lock = this[ns]) && (active = lock[activeId = lock.active])) {
  1.8655 +        active.timer.c = null;
  1.8656 +        active.timer.t = NaN;
  1.8657 +        if (--lock.count) delete lock[activeId]; else delete this[ns];
  1.8658 +        lock.active += .5;
  1.8659 +        active.event && active.event.interrupt.call(this, this.__data__, active.index);
  1.8660 +      }
  1.8661 +    };
  1.8662 +  }
  1.8663 +  function d3_transition(groups, ns, id) {
  1.8664 +    d3_subclass(groups, d3_transitionPrototype);
  1.8665 +    groups.namespace = ns;
  1.8666 +    groups.id = id;
  1.8667 +    return groups;
  1.8668 +  }
  1.8669 +  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
  1.8670 +  d3_transitionPrototype.call = d3_selectionPrototype.call;
  1.8671 +  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
  1.8672 +  d3_transitionPrototype.node = d3_selectionPrototype.node;
  1.8673 +  d3_transitionPrototype.size = d3_selectionPrototype.size;
  1.8674 +  d3.transition = function(selection, name) {
  1.8675 +    return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection);
  1.8676 +  };
  1.8677 +  d3.transition.prototype = d3_transitionPrototype;
  1.8678 +  d3_transitionPrototype.select = function(selector) {
  1.8679 +    var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node;
  1.8680 +    selector = d3_selection_selector(selector);
  1.8681 +    for (var j = -1, m = this.length; ++j < m; ) {
  1.8682 +      subgroups.push(subgroup = []);
  1.8683 +      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  1.8684 +        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
  1.8685 +          if ("__data__" in node) subnode.__data__ = node.__data__;
  1.8686 +          d3_transitionNode(subnode, i, ns, id, node[ns][id]);
  1.8687 +          subgroup.push(subnode);
  1.8688 +        } else {
  1.8689 +          subgroup.push(null);
  1.8690 +        }
  1.8691 +      }
  1.8692 +    }
  1.8693 +    return d3_transition(subgroups, ns, id);
  1.8694 +  };
  1.8695 +  d3_transitionPrototype.selectAll = function(selector) {
  1.8696 +    var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition;
  1.8697 +    selector = d3_selection_selectorAll(selector);
  1.8698 +    for (var j = -1, m = this.length; ++j < m; ) {
  1.8699 +      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  1.8700 +        if (node = group[i]) {
  1.8701 +          transition = node[ns][id];
  1.8702 +          subnodes = selector.call(node, node.__data__, i, j);
  1.8703 +          subgroups.push(subgroup = []);
  1.8704 +          for (var k = -1, o = subnodes.length; ++k < o; ) {
  1.8705 +            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
  1.8706 +            subgroup.push(subnode);
  1.8707 +          }
  1.8708 +        }
  1.8709 +      }
  1.8710 +    }
  1.8711 +    return d3_transition(subgroups, ns, id);
  1.8712 +  };
  1.8713 +  d3_transitionPrototype.filter = function(filter) {
  1.8714 +    var subgroups = [], subgroup, group, node;
  1.8715 +    if (typeof filter !== "function") filter = d3_selection_filter(filter);
  1.8716 +    for (var j = 0, m = this.length; j < m; j++) {
  1.8717 +      subgroups.push(subgroup = []);
  1.8718 +      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
  1.8719 +        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
  1.8720 +          subgroup.push(node);
  1.8721 +        }
  1.8722 +      }
  1.8723 +    }
  1.8724 +    return d3_transition(subgroups, this.namespace, this.id);
  1.8725 +  };
  1.8726 +  d3_transitionPrototype.tween = function(name, tween) {
  1.8727 +    var id = this.id, ns = this.namespace;
  1.8728 +    if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
  1.8729 +    return d3_selection_each(this, tween == null ? function(node) {
  1.8730 +      node[ns][id].tween.remove(name);
  1.8731 +    } : function(node) {
  1.8732 +      node[ns][id].tween.set(name, tween);
  1.8733 +    });
  1.8734 +  };
  1.8735 +  function d3_transition_tween(groups, name, value, tween) {
  1.8736 +    var id = groups.id, ns = groups.namespace;
  1.8737 +    return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
  1.8738 +      node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
  1.8739 +    } : (value = tween(value), function(node) {
  1.8740 +      node[ns][id].tween.set(name, value);
  1.8741 +    }));
  1.8742 +  }
  1.8743 +  d3_transitionPrototype.attr = function(nameNS, value) {
  1.8744 +    if (arguments.length < 2) {
  1.8745 +      for (value in nameNS) this.attr(value, nameNS[value]);
  1.8746 +      return this;
  1.8747 +    }
  1.8748 +    var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
  1.8749 +    function attrNull() {
  1.8750 +      this.removeAttribute(name);
  1.8751 +    }
  1.8752 +    function attrNullNS() {
  1.8753 +      this.removeAttributeNS(name.space, name.local);
  1.8754 +    }
  1.8755 +    function attrTween(b) {
  1.8756 +      return b == null ? attrNull : (b += "", function() {
  1.8757 +        var a = this.getAttribute(name), i;
  1.8758 +        return a !== b && (i = interpolate(a, b), function(t) {
  1.8759 +          this.setAttribute(name, i(t));
  1.8760 +        });
  1.8761 +      });
  1.8762 +    }
  1.8763 +    function attrTweenNS(b) {
  1.8764 +      return b == null ? attrNullNS : (b += "", function() {
  1.8765 +        var a = this.getAttributeNS(name.space, name.local), i;
  1.8766 +        return a !== b && (i = interpolate(a, b), function(t) {
  1.8767 +          this.setAttributeNS(name.space, name.local, i(t));
  1.8768 +        });
  1.8769 +      });
  1.8770 +    }
  1.8771 +    return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
  1.8772 +  };
  1.8773 +  d3_transitionPrototype.attrTween = function(nameNS, tween) {
  1.8774 +    var name = d3.ns.qualify(nameNS);
  1.8775 +    function attrTween(d, i) {
  1.8776 +      var f = tween.call(this, d, i, this.getAttribute(name));
  1.8777 +      return f && function(t) {
  1.8778 +        this.setAttribute(name, f(t));
  1.8779 +      };
  1.8780 +    }
  1.8781 +    function attrTweenNS(d, i) {
  1.8782 +      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
  1.8783 +      return f && function(t) {
  1.8784 +        this.setAttributeNS(name.space, name.local, f(t));
  1.8785 +      };
  1.8786 +    }
  1.8787 +    return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
  1.8788 +  };
  1.8789 +  d3_transitionPrototype.style = function(name, value, priority) {
  1.8790 +    var n = arguments.length;
  1.8791 +    if (n < 3) {
  1.8792 +      if (typeof name !== "string") {
  1.8793 +        if (n < 2) value = "";
  1.8794 +        for (priority in name) this.style(priority, name[priority], value);
  1.8795 +        return this;
  1.8796 +      }
  1.8797 +      priority = "";
  1.8798 +    }
  1.8799 +    function styleNull() {
  1.8800 +      this.style.removeProperty(name);
  1.8801 +    }
  1.8802 +    function styleString(b) {
  1.8803 +      return b == null ? styleNull : (b += "", function() {
  1.8804 +        var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
  1.8805 +        return a !== b && (i = d3_interpolate(a, b), function(t) {
  1.8806 +          this.style.setProperty(name, i(t), priority);
  1.8807 +        });
  1.8808 +      });
  1.8809 +    }
  1.8810 +    return d3_transition_tween(this, "style." + name, value, styleString);
  1.8811 +  };
  1.8812 +  d3_transitionPrototype.styleTween = function(name, tween, priority) {
  1.8813 +    if (arguments.length < 3) priority = "";
  1.8814 +    function styleTween(d, i) {
  1.8815 +      var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
  1.8816 +      return f && function(t) {
  1.8817 +        this.style.setProperty(name, f(t), priority);
  1.8818 +      };
  1.8819 +    }
  1.8820 +    return this.tween("style." + name, styleTween);
  1.8821 +  };
  1.8822 +  d3_transitionPrototype.text = function(value) {
  1.8823 +    return d3_transition_tween(this, "text", value, d3_transition_text);
  1.8824 +  };
  1.8825 +  function d3_transition_text(b) {
  1.8826 +    if (b == null) b = "";
  1.8827 +    return function() {
  1.8828 +      this.textContent = b;
  1.8829 +    };
  1.8830 +  }
  1.8831 +  d3_transitionPrototype.remove = function() {
  1.8832 +    var ns = this.namespace;
  1.8833 +    return this.each("end.transition", function() {
  1.8834 +      var p;
  1.8835 +      if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
  1.8836 +    });
  1.8837 +  };
  1.8838 +  d3_transitionPrototype.ease = function(value) {
  1.8839 +    var id = this.id, ns = this.namespace;
  1.8840 +    if (arguments.length < 1) return this.node()[ns][id].ease;
  1.8841 +    if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
  1.8842 +    return d3_selection_each(this, function(node) {
  1.8843 +      node[ns][id].ease = value;
  1.8844 +    });
  1.8845 +  };
  1.8846 +  d3_transitionPrototype.delay = function(value) {
  1.8847 +    var id = this.id, ns = this.namespace;
  1.8848 +    if (arguments.length < 1) return this.node()[ns][id].delay;
  1.8849 +    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
  1.8850 +      node[ns][id].delay = +value.call(node, node.__data__, i, j);
  1.8851 +    } : (value = +value, function(node) {
  1.8852 +      node[ns][id].delay = value;
  1.8853 +    }));
  1.8854 +  };
  1.8855 +  d3_transitionPrototype.duration = function(value) {
  1.8856 +    var id = this.id, ns = this.namespace;
  1.8857 +    if (arguments.length < 1) return this.node()[ns][id].duration;
  1.8858 +    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
  1.8859 +      node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j));
  1.8860 +    } : (value = Math.max(1, value), function(node) {
  1.8861 +      node[ns][id].duration = value;
  1.8862 +    }));
  1.8863 +  };
  1.8864 +  d3_transitionPrototype.each = function(type, listener) {
  1.8865 +    var id = this.id, ns = this.namespace;
  1.8866 +    if (arguments.length < 2) {
  1.8867 +      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
  1.8868 +      try {
  1.8869 +        d3_transitionInheritId = id;
  1.8870 +        d3_selection_each(this, function(node, i, j) {
  1.8871 +          d3_transitionInherit = node[ns][id];
  1.8872 +          type.call(node, node.__data__, i, j);
  1.8873 +        });
  1.8874 +      } finally {
  1.8875 +        d3_transitionInherit = inherit;
  1.8876 +        d3_transitionInheritId = inheritId;
  1.8877 +      }
  1.8878 +    } else {
  1.8879 +      d3_selection_each(this, function(node) {
  1.8880 +        var transition = node[ns][id];
  1.8881 +        (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
  1.8882 +      });
  1.8883 +    }
  1.8884 +    return this;
  1.8885 +  };
  1.8886 +  d3_transitionPrototype.transition = function() {
  1.8887 +    var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition;
  1.8888 +    for (var j = 0, m = this.length; j < m; j++) {
  1.8889 +      subgroups.push(subgroup = []);
  1.8890 +      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
  1.8891 +        if (node = group[i]) {
  1.8892 +          transition = node[ns][id0];
  1.8893 +          d3_transitionNode(node, i, ns, id1, {
  1.8894 +            time: transition.time,
  1.8895 +            ease: transition.ease,
  1.8896 +            delay: transition.delay + transition.duration,
  1.8897 +            duration: transition.duration
  1.8898 +          });
  1.8899 +        }
  1.8900 +        subgroup.push(node);
  1.8901 +      }
  1.8902 +    }
  1.8903 +    return d3_transition(subgroups, ns, id1);
  1.8904 +  };
  1.8905 +  function d3_transitionNamespace(name) {
  1.8906 +    return name == null ? "__transition__" : "__transition_" + name + "__";
  1.8907 +  }
  1.8908 +  function d3_transitionNode(node, i, ns, id, inherit) {
  1.8909 +    var lock = node[ns] || (node[ns] = {
  1.8910 +      active: 0,
  1.8911 +      count: 0
  1.8912 +    }), transition = lock[id], time, timer, duration, ease, tweens;
  1.8913 +    function schedule(elapsed) {
  1.8914 +      var delay = transition.delay;
  1.8915 +      timer.t = delay + time;
  1.8916 +      if (delay <= elapsed) return start(elapsed - delay);
  1.8917 +      timer.c = start;
  1.8918 +    }
  1.8919 +    function start(elapsed) {
  1.8920 +      var activeId = lock.active, active = lock[activeId];
  1.8921 +      if (active) {
  1.8922 +        active.timer.c = null;
  1.8923 +        active.timer.t = NaN;
  1.8924 +        --lock.count;
  1.8925 +        delete lock[activeId];
  1.8926 +        active.event && active.event.interrupt.call(node, node.__data__, active.index);
  1.8927 +      }
  1.8928 +      for (var cancelId in lock) {
  1.8929 +        if (+cancelId < id) {
  1.8930 +          var cancel = lock[cancelId];
  1.8931 +          cancel.timer.c = null;
  1.8932 +          cancel.timer.t = NaN;
  1.8933 +          --lock.count;
  1.8934 +          delete lock[cancelId];
  1.8935 +        }
  1.8936 +      }
  1.8937 +      timer.c = tick;
  1.8938 +      d3_timer(function() {
  1.8939 +        if (timer.c && tick(elapsed || 1)) {
  1.8940 +          timer.c = null;
  1.8941 +          timer.t = NaN;
  1.8942 +        }
  1.8943 +        return 1;
  1.8944 +      }, 0, time);
  1.8945 +      lock.active = id;
  1.8946 +      transition.event && transition.event.start.call(node, node.__data__, i);
  1.8947 +      tweens = [];
  1.8948 +      transition.tween.forEach(function(key, value) {
  1.8949 +        if (value = value.call(node, node.__data__, i)) {
  1.8950 +          tweens.push(value);
  1.8951 +        }
  1.8952 +      });
  1.8953 +      ease = transition.ease;
  1.8954 +      duration = transition.duration;
  1.8955 +    }
  1.8956 +    function tick(elapsed) {
  1.8957 +      var t = elapsed / duration, e = ease(t), n = tweens.length;
  1.8958 +      while (n > 0) {
  1.8959 +        tweens[--n].call(node, e);
  1.8960 +      }
  1.8961 +      if (t >= 1) {
  1.8962 +        transition.event && transition.event.end.call(node, node.__data__, i);
  1.8963 +        if (--lock.count) delete lock[id]; else delete node[ns];
  1.8964 +        return 1;
  1.8965 +      }
  1.8966 +    }
  1.8967 +    if (!transition) {
  1.8968 +      time = inherit.time;
  1.8969 +      timer = d3_timer(schedule, 0, time);
  1.8970 +      transition = lock[id] = {
  1.8971 +        tween: new d3_Map(),
  1.8972 +        time: time,
  1.8973 +        timer: timer,
  1.8974 +        delay: inherit.delay,
  1.8975 +        duration: inherit.duration,
  1.8976 +        ease: inherit.ease,
  1.8977 +        index: i
  1.8978 +      };
  1.8979 +      inherit = null;
  1.8980 +      ++lock.count;
  1.8981 +    }
  1.8982 +  }
  1.8983 +  d3.svg.axis = function() {
  1.8984 +    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
  1.8985 +    function axis(g) {
  1.8986 +      g.each(function() {
  1.8987 +        var g = d3.select(this);
  1.8988 +        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
  1.8989 +        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
  1.8990 +        var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
  1.8991 +        d3.transition(path));
  1.8992 +        tickEnter.append("line");
  1.8993 +        tickEnter.append("text");
  1.8994 +        var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
  1.8995 +        if (orient === "bottom" || orient === "top") {
  1.8996 +          tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2";
  1.8997 +          text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
  1.8998 +          pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
  1.8999 +        } else {
  1.9000 +          tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2";
  1.9001 +          text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
  1.9002 +          pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
  1.9003 +        }
  1.9004 +        lineEnter.attr(y2, sign * innerTickSize);
  1.9005 +        textEnter.attr(y1, sign * tickSpacing);
  1.9006 +        lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
  1.9007 +        textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
  1.9008 +        if (scale1.rangeBand) {
  1.9009 +          var x = scale1, dx = x.rangeBand() / 2;
  1.9010 +          scale0 = scale1 = function(d) {
  1.9011 +            return x(d) + dx;
  1.9012 +          };
  1.9013 +        } else if (scale0.rangeBand) {
  1.9014 +          scale0 = scale1;
  1.9015 +        } else {
  1.9016 +          tickExit.call(tickTransform, scale1, scale0);
  1.9017 +        }
  1.9018 +        tickEnter.call(tickTransform, scale0, scale1);
  1.9019 +        tickUpdate.call(tickTransform, scale1, scale1);
  1.9020 +      });
  1.9021 +    }
  1.9022 +    axis.scale = function(x) {
  1.9023 +      if (!arguments.length) return scale;
  1.9024 +      scale = x;
  1.9025 +      return axis;
  1.9026 +    };
  1.9027 +    axis.orient = function(x) {
  1.9028 +      if (!arguments.length) return orient;
  1.9029 +      orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
  1.9030 +      return axis;
  1.9031 +    };
  1.9032 +    axis.ticks = function() {
  1.9033 +      if (!arguments.length) return tickArguments_;
  1.9034 +      tickArguments_ = d3_array(arguments);
  1.9035 +      return axis;
  1.9036 +    };
  1.9037 +    axis.tickValues = function(x) {
  1.9038 +      if (!arguments.length) return tickValues;
  1.9039 +      tickValues = x;
  1.9040 +      return axis;
  1.9041 +    };
  1.9042 +    axis.tickFormat = function(x) {
  1.9043 +      if (!arguments.length) return tickFormat_;
  1.9044 +      tickFormat_ = x;
  1.9045 +      return axis;
  1.9046 +    };
  1.9047 +    axis.tickSize = function(x) {
  1.9048 +      var n = arguments.length;
  1.9049 +      if (!n) return innerTickSize;
  1.9050 +      innerTickSize = +x;
  1.9051 +      outerTickSize = +arguments[n - 1];
  1.9052 +      return axis;
  1.9053 +    };
  1.9054 +    axis.innerTickSize = function(x) {
  1.9055 +      if (!arguments.length) return innerTickSize;
  1.9056 +      innerTickSize = +x;
  1.9057 +      return axis;
  1.9058 +    };
  1.9059 +    axis.outerTickSize = function(x) {
  1.9060 +      if (!arguments.length) return outerTickSize;
  1.9061 +      outerTickSize = +x;
  1.9062 +      return axis;
  1.9063 +    };
  1.9064 +    axis.tickPadding = function(x) {
  1.9065 +      if (!arguments.length) return tickPadding;
  1.9066 +      tickPadding = +x;
  1.9067 +      return axis;
  1.9068 +    };
  1.9069 +    axis.tickSubdivide = function() {
  1.9070 +      return arguments.length && axis;
  1.9071 +    };
  1.9072 +    return axis;
  1.9073 +  };
  1.9074 +  var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
  1.9075 +    top: 1,
  1.9076 +    right: 1,
  1.9077 +    bottom: 1,
  1.9078 +    left: 1
  1.9079 +  };
  1.9080 +  function d3_svg_axisX(selection, x0, x1) {
  1.9081 +    selection.attr("transform", function(d) {
  1.9082 +      var v0 = x0(d);
  1.9083 +      return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
  1.9084 +    });
  1.9085 +  }
  1.9086 +  function d3_svg_axisY(selection, y0, y1) {
  1.9087 +    selection.attr("transform", function(d) {
  1.9088 +      var v0 = y0(d);
  1.9089 +      return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
  1.9090 +    });
  1.9091 +  }
  1.9092 +  d3.svg.brush = function() {
  1.9093 +    var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
  1.9094 +    function brush(g) {
  1.9095 +      g.each(function() {
  1.9096 +        var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
  1.9097 +        var background = g.selectAll(".background").data([ 0 ]);
  1.9098 +        background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
  1.9099 +        g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
  1.9100 +        var resize = g.selectAll(".resize").data(resizes, d3_identity);
  1.9101 +        resize.exit().remove();
  1.9102 +        resize.enter().append("g").attr("class", function(d) {
  1.9103 +          return "resize " + d;
  1.9104 +        }).style("cursor", function(d) {
  1.9105 +          return d3_svg_brushCursor[d];
  1.9106 +        }).append("rect").attr("x", function(d) {
  1.9107 +          return /[ew]$/.test(d) ? -3 : null;
  1.9108 +        }).attr("y", function(d) {
  1.9109 +          return /^[ns]/.test(d) ? -3 : null;
  1.9110 +        }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
  1.9111 +        resize.style("display", brush.empty() ? "none" : null);
  1.9112 +        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
  1.9113 +        if (x) {
  1.9114 +          range = d3_scaleRange(x);
  1.9115 +          backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
  1.9116 +          redrawX(gUpdate);
  1.9117 +        }
  1.9118 +        if (y) {
  1.9119 +          range = d3_scaleRange(y);
  1.9120 +          backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
  1.9121 +          redrawY(gUpdate);
  1.9122 +        }
  1.9123 +        redraw(gUpdate);
  1.9124 +      });
  1.9125 +    }
  1.9126 +    brush.event = function(g) {
  1.9127 +      g.each(function() {
  1.9128 +        var event_ = event.of(this, arguments), extent1 = {
  1.9129 +          x: xExtent,
  1.9130 +          y: yExtent,
  1.9131 +          i: xExtentDomain,
  1.9132 +          j: yExtentDomain
  1.9133 +        }, extent0 = this.__chart__ || extent1;
  1.9134 +        this.__chart__ = extent1;
  1.9135 +        if (d3_transitionInheritId) {
  1.9136 +          d3.select(this).transition().each("start.brush", function() {
  1.9137 +            xExtentDomain = extent0.i;
  1.9138 +            yExtentDomain = extent0.j;
  1.9139 +            xExtent = extent0.x;
  1.9140 +            yExtent = extent0.y;
  1.9141 +            event_({
  1.9142 +              type: "brushstart"
  1.9143 +            });
  1.9144 +          }).tween("brush:brush", function() {
  1.9145 +            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
  1.9146 +            xExtentDomain = yExtentDomain = null;
  1.9147 +            return function(t) {
  1.9148 +              xExtent = extent1.x = xi(t);
  1.9149 +              yExtent = extent1.y = yi(t);
  1.9150 +              event_({
  1.9151 +                type: "brush",
  1.9152 +                mode: "resize"
  1.9153 +              });
  1.9154 +            };
  1.9155 +          }).each("end.brush", function() {
  1.9156 +            xExtentDomain = extent1.i;
  1.9157 +            yExtentDomain = extent1.j;
  1.9158 +            event_({
  1.9159 +              type: "brush",
  1.9160 +              mode: "resize"
  1.9161 +            });
  1.9162 +            event_({
  1.9163 +              type: "brushend"
  1.9164 +            });
  1.9165 +          });
  1.9166 +        } else {
  1.9167 +          event_({
  1.9168 +            type: "brushstart"
  1.9169 +          });
  1.9170 +          event_({
  1.9171 +            type: "brush",
  1.9172 +            mode: "resize"
  1.9173 +          });
  1.9174 +          event_({
  1.9175 +            type: "brushend"
  1.9176 +          });
  1.9177 +        }
  1.9178 +      });
  1.9179 +    };
  1.9180 +    function redraw(g) {
  1.9181 +      g.selectAll(".resize").attr("transform", function(d) {
  1.9182 +        return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
  1.9183 +      });
  1.9184 +    }
  1.9185 +    function redrawX(g) {
  1.9186 +      g.select(".extent").attr("x", xExtent[0]);
  1.9187 +      g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
  1.9188 +    }
  1.9189 +    function redrawY(g) {
  1.9190 +      g.select(".extent").attr("y", yExtent[0]);
  1.9191 +      g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
  1.9192 +    }
  1.9193 +    function brushstart() {
  1.9194 +      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset;
  1.9195 +      var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup);
  1.9196 +      if (d3.event.changedTouches) {
  1.9197 +        w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
  1.9198 +      } else {
  1.9199 +        w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
  1.9200 +      }
  1.9201 +      g.interrupt().selectAll("*").interrupt();
  1.9202 +      if (dragging) {
  1.9203 +        origin[0] = xExtent[0] - origin[0];
  1.9204 +        origin[1] = yExtent[0] - origin[1];
  1.9205 +      } else if (resizing) {
  1.9206 +        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
  1.9207 +        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
  1.9208 +        origin[0] = xExtent[ex];
  1.9209 +        origin[1] = yExtent[ey];
  1.9210 +      } else if (d3.event.altKey) center = origin.slice();
  1.9211 +      g.style("pointer-events", "none").selectAll(".resize").style("display", null);
  1.9212 +      d3.select("body").style("cursor", eventTarget.style("cursor"));
  1.9213 +      event_({
  1.9214 +        type: "brushstart"
  1.9215 +      });
  1.9216 +      brushmove();
  1.9217 +      function keydown() {
  1.9218 +        if (d3.event.keyCode == 32) {
  1.9219 +          if (!dragging) {
  1.9220 +            center = null;
  1.9221 +            origin[0] -= xExtent[1];
  1.9222 +            origin[1] -= yExtent[1];
  1.9223 +            dragging = 2;
  1.9224 +          }
  1.9225 +          d3_eventPreventDefault();
  1.9226 +        }
  1.9227 +      }
  1.9228 +      function keyup() {
  1.9229 +        if (d3.event.keyCode == 32 && dragging == 2) {
  1.9230 +          origin[0] += xExtent[1];
  1.9231 +          origin[1] += yExtent[1];
  1.9232 +          dragging = 0;
  1.9233 +          d3_eventPreventDefault();
  1.9234 +        }
  1.9235 +      }
  1.9236 +      function brushmove() {
  1.9237 +        var point = d3.mouse(target), moved = false;
  1.9238 +        if (offset) {
  1.9239 +          point[0] += offset[0];
  1.9240 +          point[1] += offset[1];
  1.9241 +        }
  1.9242 +        if (!dragging) {
  1.9243 +          if (d3.event.altKey) {
  1.9244 +            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
  1.9245 +            origin[0] = xExtent[+(point[0] < center[0])];
  1.9246 +            origin[1] = yExtent[+(point[1] < center[1])];
  1.9247 +          } else center = null;
  1.9248 +        }
  1.9249 +        if (resizingX && move1(point, x, 0)) {
  1.9250 +          redrawX(g);
  1.9251 +          moved = true;
  1.9252 +        }
  1.9253 +        if (resizingY && move1(point, y, 1)) {
  1.9254 +          redrawY(g);
  1.9255 +          moved = true;
  1.9256 +        }
  1.9257 +        if (moved) {
  1.9258 +          redraw(g);
  1.9259 +          event_({
  1.9260 +            type: "brush",
  1.9261 +            mode: dragging ? "move" : "resize"
  1.9262 +          });
  1.9263 +        }
  1.9264 +      }
  1.9265 +      function move1(point, scale, i) {
  1.9266 +        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
  1.9267 +        if (dragging) {
  1.9268 +          r0 -= position;
  1.9269 +          r1 -= size + position;
  1.9270 +        }
  1.9271 +        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
  1.9272 +        if (dragging) {
  1.9273 +          max = (min += position) + size;
  1.9274 +        } else {
  1.9275 +          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
  1.9276 +          if (position < min) {
  1.9277 +            max = min;
  1.9278 +            min = position;
  1.9279 +          } else {
  1.9280 +            max = position;
  1.9281 +          }
  1.9282 +        }
  1.9283 +        if (extent[0] != min || extent[1] != max) {
  1.9284 +          if (i) yExtentDomain = null; else xExtentDomain = null;
  1.9285 +          extent[0] = min;
  1.9286 +          extent[1] = max;
  1.9287 +          return true;
  1.9288 +        }
  1.9289 +      }
  1.9290 +      function brushend() {
  1.9291 +        brushmove();
  1.9292 +        g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
  1.9293 +        d3.select("body").style("cursor", null);
  1.9294 +        w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
  1.9295 +        dragRestore();
  1.9296 +        event_({
  1.9297 +          type: "brushend"
  1.9298 +        });
  1.9299 +      }
  1.9300 +    }
  1.9301 +    brush.x = function(z) {
  1.9302 +      if (!arguments.length) return x;
  1.9303 +      x = z;
  1.9304 +      resizes = d3_svg_brushResizes[!x << 1 | !y];
  1.9305 +      return brush;
  1.9306 +    };
  1.9307 +    brush.y = function(z) {
  1.9308 +      if (!arguments.length) return y;
  1.9309 +      y = z;
  1.9310 +      resizes = d3_svg_brushResizes[!x << 1 | !y];
  1.9311 +      return brush;
  1.9312 +    };
  1.9313 +    brush.clamp = function(z) {
  1.9314 +      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
  1.9315 +      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
  1.9316 +      return brush;
  1.9317 +    };
  1.9318 +    brush.extent = function(z) {
  1.9319 +      var x0, x1, y0, y1, t;
  1.9320 +      if (!arguments.length) {
  1.9321 +        if (x) {
  1.9322 +          if (xExtentDomain) {
  1.9323 +            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
  1.9324 +          } else {
  1.9325 +            x0 = xExtent[0], x1 = xExtent[1];
  1.9326 +            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
  1.9327 +            if (x1 < x0) t = x0, x0 = x1, x1 = t;
  1.9328 +          }
  1.9329 +        }
  1.9330 +        if (y) {
  1.9331 +          if (yExtentDomain) {
  1.9332 +            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
  1.9333 +          } else {
  1.9334 +            y0 = yExtent[0], y1 = yExtent[1];
  1.9335 +            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
  1.9336 +            if (y1 < y0) t = y0, y0 = y1, y1 = t;
  1.9337 +          }
  1.9338 +        }
  1.9339 +        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
  1.9340 +      }
  1.9341 +      if (x) {
  1.9342 +        x0 = z[0], x1 = z[1];
  1.9343 +        if (y) x0 = x0[0], x1 = x1[0];
  1.9344 +        xExtentDomain = [ x0, x1 ];
  1.9345 +        if (x.invert) x0 = x(x0), x1 = x(x1);
  1.9346 +        if (x1 < x0) t = x0, x0 = x1, x1 = t;
  1.9347 +        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
  1.9348 +      }
  1.9349 +      if (y) {
  1.9350 +        y0 = z[0], y1 = z[1];
  1.9351 +        if (x) y0 = y0[1], y1 = y1[1];
  1.9352 +        yExtentDomain = [ y0, y1 ];
  1.9353 +        if (y.invert) y0 = y(y0), y1 = y(y1);
  1.9354 +        if (y1 < y0) t = y0, y0 = y1, y1 = t;
  1.9355 +        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
  1.9356 +      }
  1.9357 +      return brush;
  1.9358 +    };
  1.9359 +    brush.clear = function() {
  1.9360 +      if (!brush.empty()) {
  1.9361 +        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
  1.9362 +        xExtentDomain = yExtentDomain = null;
  1.9363 +      }
  1.9364 +      return brush;
  1.9365 +    };
  1.9366 +    brush.empty = function() {
  1.9367 +      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
  1.9368 +    };
  1.9369 +    return d3.rebind(brush, event, "on");
  1.9370 +  };
  1.9371 +  var d3_svg_brushCursor = {
  1.9372 +    n: "ns-resize",
  1.9373 +    e: "ew-resize",
  1.9374 +    s: "ns-resize",
  1.9375 +    w: "ew-resize",
  1.9376 +    nw: "nwse-resize",
  1.9377 +    ne: "nesw-resize",
  1.9378 +    se: "nwse-resize",
  1.9379 +    sw: "nesw-resize"
  1.9380 +  };
  1.9381 +  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
  1.9382 +  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
  1.9383 +  var d3_time_formatUtc = d3_time_format.utc;
  1.9384 +  var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
  1.9385 +  d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
  1.9386 +  function d3_time_formatIsoNative(date) {
  1.9387 +    return date.toISOString();
  1.9388 +  }
  1.9389 +  d3_time_formatIsoNative.parse = function(string) {
  1.9390 +    var date = new Date(string);
  1.9391 +    return isNaN(date) ? null : date;
  1.9392 +  };
  1.9393 +  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
  1.9394 +  d3_time.second = d3_time_interval(function(date) {
  1.9395 +    return new d3_date(Math.floor(date / 1e3) * 1e3);
  1.9396 +  }, function(date, offset) {
  1.9397 +    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
  1.9398 +  }, function(date) {
  1.9399 +    return date.getSeconds();
  1.9400 +  });
  1.9401 +  d3_time.seconds = d3_time.second.range;
  1.9402 +  d3_time.seconds.utc = d3_time.second.utc.range;
  1.9403 +  d3_time.minute = d3_time_interval(function(date) {
  1.9404 +    return new d3_date(Math.floor(date / 6e4) * 6e4);
  1.9405 +  }, function(date, offset) {
  1.9406 +    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
  1.9407 +  }, function(date) {
  1.9408 +    return date.getMinutes();
  1.9409 +  });
  1.9410 +  d3_time.minutes = d3_time.minute.range;
  1.9411 +  d3_time.minutes.utc = d3_time.minute.utc.range;
  1.9412 +  d3_time.hour = d3_time_interval(function(date) {
  1.9413 +    var timezone = date.getTimezoneOffset() / 60;
  1.9414 +    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
  1.9415 +  }, function(date, offset) {
  1.9416 +    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
  1.9417 +  }, function(date) {
  1.9418 +    return date.getHours();
  1.9419 +  });
  1.9420 +  d3_time.hours = d3_time.hour.range;
  1.9421 +  d3_time.hours.utc = d3_time.hour.utc.range;
  1.9422 +  d3_time.month = d3_time_interval(function(date) {
  1.9423 +    date = d3_time.day(date);
  1.9424 +    date.setDate(1);
  1.9425 +    return date;
  1.9426 +  }, function(date, offset) {
  1.9427 +    date.setMonth(date.getMonth() + offset);
  1.9428 +  }, function(date) {
  1.9429 +    return date.getMonth();
  1.9430 +  });
  1.9431 +  d3_time.months = d3_time.month.range;
  1.9432 +  d3_time.months.utc = d3_time.month.utc.range;
  1.9433 +  function d3_time_scale(linear, methods, format) {
  1.9434 +    function scale(x) {
  1.9435 +      return linear(x);
  1.9436 +    }
  1.9437 +    scale.invert = function(x) {
  1.9438 +      return d3_time_scaleDate(linear.invert(x));
  1.9439 +    };
  1.9440 +    scale.domain = function(x) {
  1.9441 +      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
  1.9442 +      linear.domain(x);
  1.9443 +      return scale;
  1.9444 +    };
  1.9445 +    function tickMethod(extent, count) {
  1.9446 +      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
  1.9447 +      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
  1.9448 +        return d / 31536e6;
  1.9449 +      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
  1.9450 +    }
  1.9451 +    scale.nice = function(interval, skip) {
  1.9452 +      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
  1.9453 +      if (method) interval = method[0], skip = method[1];
  1.9454 +      function skipped(date) {
  1.9455 +        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
  1.9456 +      }
  1.9457 +      return scale.domain(d3_scale_nice(domain, skip > 1 ? {
  1.9458 +        floor: function(date) {
  1.9459 +          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
  1.9460 +          return date;
  1.9461 +        },
  1.9462 +        ceil: function(date) {
  1.9463 +          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
  1.9464 +          return date;
  1.9465 +        }
  1.9466 +      } : interval));
  1.9467 +    };
  1.9468 +    scale.ticks = function(interval, skip) {
  1.9469 +      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
  1.9470 +        range: interval
  1.9471 +      }, skip ];
  1.9472 +      if (method) interval = method[0], skip = method[1];
  1.9473 +      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
  1.9474 +    };
  1.9475 +    scale.tickFormat = function() {
  1.9476 +      return format;
  1.9477 +    };
  1.9478 +    scale.copy = function() {
  1.9479 +      return d3_time_scale(linear.copy(), methods, format);
  1.9480 +    };
  1.9481 +    return d3_scale_linearRebind(scale, linear);
  1.9482 +  }
  1.9483 +  function d3_time_scaleDate(t) {
  1.9484 +    return new Date(t);
  1.9485 +  }
  1.9486 +  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
  1.9487 +  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
  1.9488 +  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
  1.9489 +    return d.getMilliseconds();
  1.9490 +  } ], [ ":%S", function(d) {
  1.9491 +    return d.getSeconds();
  1.9492 +  } ], [ "%I:%M", function(d) {
  1.9493 +    return d.getMinutes();
  1.9494 +  } ], [ "%I %p", function(d) {
  1.9495 +    return d.getHours();
  1.9496 +  } ], [ "%a %d", function(d) {
  1.9497 +    return d.getDay() && d.getDate() != 1;
  1.9498 +  } ], [ "%b %d", function(d) {
  1.9499 +    return d.getDate() != 1;
  1.9500 +  } ], [ "%B", function(d) {
  1.9501 +    return d.getMonth();
  1.9502 +  } ], [ "%Y", d3_true ] ]);
  1.9503 +  var d3_time_scaleMilliseconds = {
  1.9504 +    range: function(start, stop, step) {
  1.9505 +      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
  1.9506 +    },
  1.9507 +    floor: d3_identity,
  1.9508 +    ceil: d3_identity
  1.9509 +  };
  1.9510 +  d3_time_scaleLocalMethods.year = d3_time.year;
  1.9511 +  d3_time.scale = function() {
  1.9512 +    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
  1.9513 +  };
  1.9514 +  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
  1.9515 +    return [ m[0].utc, m[1] ];
  1.9516 +  });
  1.9517 +  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
  1.9518 +    return d.getUTCMilliseconds();
  1.9519 +  } ], [ ":%S", function(d) {
  1.9520 +    return d.getUTCSeconds();
  1.9521 +  } ], [ "%I:%M", function(d) {
  1.9522 +    return d.getUTCMinutes();
  1.9523 +  } ], [ "%I %p", function(d) {
  1.9524 +    return d.getUTCHours();
  1.9525 +  } ], [ "%a %d", function(d) {
  1.9526 +    return d.getUTCDay() && d.getUTCDate() != 1;
  1.9527 +  } ], [ "%b %d", function(d) {
  1.9528 +    return d.getUTCDate() != 1;
  1.9529 +  } ], [ "%B", function(d) {
  1.9530 +    return d.getUTCMonth();
  1.9531 +  } ], [ "%Y", d3_true ] ]);
  1.9532 +  d3_time_scaleUtcMethods.year = d3_time.year.utc;
  1.9533 +  d3_time.scale.utc = function() {
  1.9534 +    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
  1.9535 +  };
  1.9536 +  d3.text = d3_xhrType(function(request) {
  1.9537 +    return request.responseText;
  1.9538 +  });
  1.9539 +  d3.json = function(url, callback) {
  1.9540 +    return d3_xhr(url, "application/json", d3_json, callback);
  1.9541 +  };
  1.9542 +  function d3_json(request) {
  1.9543 +    return JSON.parse(request.responseText);
  1.9544 +  }
  1.9545 +  d3.html = function(url, callback) {
  1.9546 +    return d3_xhr(url, "text/html", d3_html, callback);
  1.9547 +  };
  1.9548 +  function d3_html(request) {
  1.9549 +    var range = d3_document.createRange();
  1.9550 +    range.selectNode(d3_document.body);
  1.9551 +    return range.createContextualFragment(request.responseText);
  1.9552 +  }
  1.9553 +  d3.xml = d3_xhrType(function(request) {
  1.9554 +    return request.responseXML;
  1.9555 +  });
  1.9556 +  if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3;
  1.9557 +}();
  1.9558 \ No newline at end of file
     2.1 Binary file gtc/d3.zip has changed
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/gtc/gtc.js	Sun Feb 19 19:45:31 2017 -0800
     3.3 @@ -0,0 +1,139 @@
     3.4 +var myChart;
     3.5 +var myData;
     3.6 +var showCorrBtn = document.getElementById('showcorr');
     3.7 +
     3.8 +nv.addGraph(function() {
     3.9 +  myChart = nv.models.scatterChart()
    3.10 +                .showLegend(false)
    3.11 +                .showDistX(true)
    3.12 +                .showDistY(true)
    3.13 +                .xDomain([-1, 1])
    3.14 +                .yDomain([-1, 1])
    3.15 +                .duration(350)
    3.16 +                .color(d3.scale.category10().range());
    3.17 +  myChart.tooltip.contentGenerator(function(data) {
    3.18 +    return '(' + data.point.x.toFixed(2) + ', ' + data.point.y.toFixed(2) + ')';
    3.19 +  });
    3.20 +
    3.21 +  myChart.xAxis.tickFormat(d3.format('.02f'));
    3.22 +  myChart.yAxis.tickFormat(d3.format('.02f'));
    3.23 +
    3.24 +  reload();
    3.25 +
    3.26 +  return myChart;
    3.27 +});
    3.28 +
    3.29 +
    3.30 +function randomData(groups, points) {
    3.31 +  var data = [],
    3.32 +      shapes = ['circle', 'cross', 'triangle-up', 'triangle-down', 'diamond', 'square'],
    3.33 +      random = d3.random.normal();
    3.34 +
    3.35 +  for (i = 0; i < groups; i++) {
    3.36 +    data.push({
    3.37 +      key: 'Group ' + i,
    3.38 +      values: []
    3.39 +    });
    3.40 +
    3.41 +    for (j = 0; j < points; j++) {
    3.42 +      data[i].values.push({
    3.43 +        x: random(),
    3.44 +        y: random(),
    3.45 +        size: Math.random(),
    3.46 +        shape: (Math.random() > 0.95) ? shapes[j % 6] : 'circle'
    3.47 +      });
    3.48 +    }
    3.49 +  }
    3.50 +
    3.51 +  return data;
    3.52 +}
    3.53 +
    3.54 +function myDataGen() {
    3.55 +  var data = [];
    3.56 +  var values = [];
    3.57 +  var n = 25;
    3.58 +  var m = 2*Math.random() - 1.0;
    3.59 +  var dv = Math.random();
    3.60 +  var normal = d3.random.normal(0.0, dv)
    3.61 +
    3.62 +  for (i = 0; i < n; i++) {
    3.63 +    var x = i/n + 0.5*normal() - 0.5;
    3.64 +    var y = m*x + normal();
    3.65 +    values.push({
    3.66 +      x: x,
    3.67 +      y: y,
    3.68 +      size: 2.0,
    3.69 +      shape: 'circle',
    3.70 +    });
    3.71 +  }
    3.72 +
    3.73 +  data.push({
    3.74 +    //key: 'Points',
    3.75 +    values: values,
    3.76 +    //slope: m,
    3.77 +    //intercept: 0.001,
    3.78 +  })
    3.79 +
    3.80 +  return data;
    3.81 +}
    3.82 +
    3.83 +function corr(values) {
    3.84 +  var x_a = [];
    3.85 +  var y_a = [];
    3.86 +
    3.87 +  for (i = 0; i < values.length; i++) {
    3.88 +    x_a.push(values[i].x);
    3.89 +    y_a.push(values[i].y);
    3.90 +  }
    3.91 +
    3.92 +  return ss.sampleCorrelation(x_a, y_a);
    3.93 +}
    3.94 +
    3.95 +function lr(values) {
    3.96 +  var x_y = [];
    3.97 +
    3.98 +  for (i = 0; i < values.length; i++) {
    3.99 +    x_y.push([values[i].x, values[i].y]);
   3.100 +  }
   3.101 +
   3.102 +  return ss.linearRegression(x_y);
   3.103 +}
   3.104 +
   3.105 +function print_corr() {
   3.106 +  console.log('corr = ' + corr(myData[0].values))
   3.107 +}
   3.108 +
   3.109 +function print_lr() {
   3.110 +  var lro = lr(myData[0].values);
   3.111 +  console.log('m = ' + lro.m);
   3.112 +  console.log('b = ' + lro.b);
   3.113 +}
   3.114 +
   3.115 +function add_lr(lro, data) {
   3.116 +  data.push({
   3.117 +    values: [],
   3.118 +    slope: lro.m,
   3.119 +    intercept: lro.b,
   3.120 +  })
   3.121 +}
   3.122 +
   3.123 +function show_corr() {
   3.124 +  var ans = corr(myData[0].values);
   3.125 +  showCorrBtn.textContent = ans.toFixed(2);
   3.126 +  showCorrBtn.onclick = reload;
   3.127 +}  
   3.128 +
   3.129 +function reload() {
   3.130 +  myData = myDataGen();
   3.131 +  add_lr(lr(myData[0].values), myData);
   3.132 +  showCorrBtn.disabled = false;
   3.133 +  showCorrBtn.textContent = 'Show Correlation';
   3.134 +  showCorrBtn.onclick = show_corr;
   3.135 +
   3.136 +  d3.select('#chart svg')
   3.137 +    .style('height', '95%')
   3.138 +    .datum(myData)
   3.139 +    .call(myChart);  
   3.140 +
   3.141 +  nv.utils.windowResize(myChart.update);
   3.142 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/gtc/index.html	Sun Feb 19 19:45:31 2017 -0800
     4.3 @@ -0,0 +1,18 @@
     4.4 +<html>
     4.5 +<head>
     4.6 +  <meta charset="utf-8">
     4.7 +</head>
     4.8 +<body>
     4.9 +<div id="chart">
    4.10 +  <svg></svg>
    4.11 +</div>
    4.12 +<div>
    4.13 +  <button id="showcorr">Show correlation</button>
    4.14 +</div>  
    4.15 +<link href="nv.d3.css" rel="stylesheet">
    4.16 +<script src="d3.js"></script>
    4.17 +<script src="nv.d3.js"></script>
    4.18 +<script src="simple-statistics.js"></script>
    4.19 +<script src="gtc.js"></script>
    4.20 +</body>
    4.21 +</html>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/gtc/nv.d3.css	Sun Feb 19 19:45:31 2017 -0800
     5.3 @@ -0,0 +1,641 @@
     5.4 +/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-06-15 */
     5.5 +.nvd3 .nv-axis {
     5.6 +    pointer-events:none;
     5.7 +    opacity: 1;
     5.8 +}
     5.9 +
    5.10 +.nvd3 .nv-axis path {
    5.11 +    fill: none;
    5.12 +    stroke: #000;
    5.13 +    stroke-opacity: .75;
    5.14 +    shape-rendering: crispEdges;
    5.15 +}
    5.16 +
    5.17 +.nvd3 .nv-axis path.domain {
    5.18 +    stroke-opacity: .75;
    5.19 +}
    5.20 +
    5.21 +.nvd3 .nv-axis.nv-x path.domain {
    5.22 +    stroke-opacity: 0;
    5.23 +}
    5.24 +
    5.25 +.nvd3 .nv-axis line {
    5.26 +    fill: none;
    5.27 +    stroke: #e5e5e5;
    5.28 +    shape-rendering: crispEdges;
    5.29 +}
    5.30 +
    5.31 +.nvd3 .nv-axis .zero line,
    5.32 +    /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero {
    5.33 +    stroke-opacity: .75;
    5.34 +}
    5.35 +
    5.36 +.nvd3 .nv-axis .nv-axisMaxMin text {
    5.37 +    font-weight: bold;
    5.38 +}
    5.39 +
    5.40 +.nvd3 .x  .nv-axis .nv-axisMaxMin text,
    5.41 +.nvd3 .x2 .nv-axis .nv-axisMaxMin text,
    5.42 +.nvd3 .x3 .nv-axis .nv-axisMaxMin text {
    5.43 +    text-anchor: middle
    5.44 +}
    5.45 +
    5.46 +.nvd3 .nv-axis.nv-disabled {
    5.47 +    opacity: 0;
    5.48 +}
    5.49 +
    5.50 +.nvd3 .nv-bars rect {
    5.51 +    fill-opacity: .75;
    5.52 +
    5.53 +    transition: fill-opacity 250ms linear;
    5.54 +    -moz-transition: fill-opacity 250ms linear;
    5.55 +    -webkit-transition: fill-opacity 250ms linear;
    5.56 +}
    5.57 +
    5.58 +.nvd3 .nv-bars rect.hover {
    5.59 +    fill-opacity: 1;
    5.60 +}
    5.61 +
    5.62 +.nvd3 .nv-bars .hover rect {
    5.63 +    fill: lightblue;
    5.64 +}
    5.65 +
    5.66 +.nvd3 .nv-bars text {
    5.67 +    fill: rgba(0,0,0,0);
    5.68 +}
    5.69 +
    5.70 +.nvd3 .nv-bars .hover text {
    5.71 +    fill: rgba(0,0,0,1);
    5.72 +}
    5.73 +
    5.74 +.nvd3 .nv-multibar .nv-groups rect,
    5.75 +.nvd3 .nv-multibarHorizontal .nv-groups rect,
    5.76 +.nvd3 .nv-discretebar .nv-groups rect {
    5.77 +    stroke-opacity: 0;
    5.78 +
    5.79 +    transition: fill-opacity 250ms linear;
    5.80 +    -moz-transition: fill-opacity 250ms linear;
    5.81 +    -webkit-transition: fill-opacity 250ms linear;
    5.82 +}
    5.83 +
    5.84 +.nvd3 .nv-multibar .nv-groups rect:hover,
    5.85 +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,
    5.86 +.nvd3 .nv-candlestickBar .nv-ticks rect:hover,
    5.87 +.nvd3 .nv-discretebar .nv-groups rect:hover {
    5.88 +    fill-opacity: 1;
    5.89 +}
    5.90 +
    5.91 +.nvd3 .nv-discretebar .nv-groups text,
    5.92 +.nvd3 .nv-multibarHorizontal .nv-groups text {
    5.93 +    font-weight: bold;
    5.94 +    fill: rgba(0,0,0,1);
    5.95 +    stroke: rgba(0,0,0,0);
    5.96 +}
    5.97 +
    5.98 +/* boxplot CSS */
    5.99 +.nvd3 .nv-boxplot circle {
   5.100 +  fill-opacity: 0.5;
   5.101 +}
   5.102 +
   5.103 +.nvd3 .nv-boxplot circle:hover {
   5.104 +  fill-opacity: 1;
   5.105 +}
   5.106 +
   5.107 +.nvd3 .nv-boxplot rect:hover {
   5.108 +  fill-opacity: 1;
   5.109 +}
   5.110 +
   5.111 +.nvd3 line.nv-boxplot-median {
   5.112 +  stroke: black;
   5.113 +}
   5.114 +
   5.115 +.nv-boxplot-tick:hover {
   5.116 +  stroke-width: 2.5px;
   5.117 +}
   5.118 +/* bullet */
   5.119 +.nvd3.nv-bullet { font: 10px sans-serif; }
   5.120 +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
   5.121 +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
   5.122 +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
   5.123 +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
   5.124 +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
   5.125 +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
   5.126 +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
   5.127 +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
   5.128 +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
   5.129 +.nvd3.nv-bullet .nv-subtitle { fill: #999; }
   5.130 +
   5.131 +
   5.132 +.nvd3.nv-bullet .nv-range {
   5.133 +    fill: #bababa;
   5.134 +    fill-opacity: .4;
   5.135 +}
   5.136 +.nvd3.nv-bullet .nv-range:hover {
   5.137 +    fill-opacity: .7;
   5.138 +}
   5.139 +
   5.140 +.nvd3.nv-candlestickBar .nv-ticks .nv-tick {
   5.141 +    stroke-width: 1px;
   5.142 +}
   5.143 +
   5.144 +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover {
   5.145 +    stroke-width: 2px;
   5.146 +}
   5.147 +
   5.148 +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect {
   5.149 +    stroke: #2ca02c;
   5.150 +    fill: #2ca02c;
   5.151 +}
   5.152 +
   5.153 +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect {
   5.154 +    stroke: #d62728;
   5.155 +    fill: #d62728;
   5.156 +}
   5.157 +
   5.158 +.with-transitions .nv-candlestickBar .nv-ticks .nv-tick {
   5.159 +    transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.160 +    -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.161 +    -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.162 +
   5.163 +}
   5.164 +
   5.165 +.nvd3.nv-candlestickBar .nv-ticks line {
   5.166 +    stroke: #333;
   5.167 +}
   5.168 +
   5.169 +
   5.170 +.nvd3 .nv-legend .nv-disabled rect {
   5.171 +    /*fill-opacity: 0;*/
   5.172 +}
   5.173 +
   5.174 +.nvd3 .nv-check-box .nv-box {
   5.175 +    fill-opacity:0;
   5.176 +    stroke-width:2;
   5.177 +}
   5.178 +
   5.179 +.nvd3 .nv-check-box .nv-check {
   5.180 +    fill-opacity:0;
   5.181 +    stroke-width:4;
   5.182 +}
   5.183 +
   5.184 +.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check {
   5.185 +    fill-opacity:0;
   5.186 +    stroke-opacity:0;
   5.187 +}
   5.188 +
   5.189 +.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check {
   5.190 +    opacity: 0;
   5.191 +}
   5.192 +
   5.193 +/* line plus bar */
   5.194 +.nvd3.nv-linePlusBar .nv-bar rect {
   5.195 +    fill-opacity: .75;
   5.196 +}
   5.197 +
   5.198 +.nvd3.nv-linePlusBar .nv-bar rect:hover {
   5.199 +    fill-opacity: 1;
   5.200 +}
   5.201 +.nvd3 .nv-groups path.nv-line {
   5.202 +    fill: none;
   5.203 +}
   5.204 +
   5.205 +.nvd3 .nv-groups path.nv-area {
   5.206 +    stroke: none;
   5.207 +}
   5.208 +
   5.209 +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point {
   5.210 +    fill-opacity: 0;
   5.211 +    stroke-opacity: 0;
   5.212 +}
   5.213 +
   5.214 +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
   5.215 +    fill-opacity: .5 !important;
   5.216 +    stroke-opacity: .5 !important;
   5.217 +}
   5.218 +
   5.219 +
   5.220 +.with-transitions .nvd3 .nv-groups .nv-point {
   5.221 +    transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.222 +    -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.223 +    -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.224 +
   5.225 +}
   5.226 +
   5.227 +.nvd3.nv-scatter .nv-groups .nv-point.hover,
   5.228 +.nvd3 .nv-groups .nv-point.hover {
   5.229 +    stroke-width: 7px;
   5.230 +    fill-opacity: .95 !important;
   5.231 +    stroke-opacity: .95 !important;
   5.232 +}
   5.233 +
   5.234 +
   5.235 +.nvd3 .nv-point-paths path {
   5.236 +    stroke: #aaa;
   5.237 +    stroke-opacity: 0;
   5.238 +    fill: #eee;
   5.239 +    fill-opacity: 0;
   5.240 +}
   5.241 +
   5.242 +
   5.243 +
   5.244 +.nvd3 .nv-indexLine {
   5.245 +    cursor: ew-resize;
   5.246 +}
   5.247 +
   5.248 +/********************
   5.249 + * SVG CSS
   5.250 + */
   5.251 +
   5.252 +/********************
   5.253 +  Default CSS for an svg element nvd3 used
   5.254 +*/
   5.255 +svg.nvd3-svg {
   5.256 +    -webkit-touch-callout: none;
   5.257 +    -webkit-user-select: none;
   5.258 +    -khtml-user-select: none;
   5.259 +    -ms-user-select: none;
   5.260 +    -moz-user-select: none;
   5.261 +    user-select: none;
   5.262 +    display: block;
   5.263 +    width:100%;
   5.264 +    height:100%;
   5.265 +}
   5.266 +
   5.267 +/********************
   5.268 +  Box shadow and border radius styling
   5.269 +*/
   5.270 +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip {
   5.271 +    -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
   5.272 +    -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
   5.273 +    box-shadow: 0 5px 10px rgba(0,0,0,.2);
   5.274 +
   5.275 +    -webkit-border-radius: 5px;
   5.276 +    -moz-border-radius: 5px;
   5.277 +    border-radius: 5px;
   5.278 +}
   5.279 +
   5.280 +
   5.281 +.nvd3 text {
   5.282 +    font: normal 12px Arial;
   5.283 +}
   5.284 +
   5.285 +.nvd3 .title {
   5.286 +    font: bold 14px Arial;
   5.287 +}
   5.288 +
   5.289 +.nvd3 .nv-background {
   5.290 +    fill: white;
   5.291 +    fill-opacity: 0;
   5.292 +}
   5.293 +
   5.294 +.nvd3.nv-noData {
   5.295 +    font-size: 18px;
   5.296 +    font-weight: bold;
   5.297 +}
   5.298 +
   5.299 +
   5.300 +/**********
   5.301 +*  Brush
   5.302 +*/
   5.303 +
   5.304 +.nv-brush .extent {
   5.305 +    fill-opacity: .125;
   5.306 +    shape-rendering: crispEdges;
   5.307 +}
   5.308 +
   5.309 +.nv-brush .resize path {
   5.310 +    fill: #eee;
   5.311 +    stroke: #666;
   5.312 +}
   5.313 +
   5.314 +
   5.315 +/**********
   5.316 +*  Legend
   5.317 +*/
   5.318 +
   5.319 +.nvd3 .nv-legend .nv-series {
   5.320 +    cursor: pointer;
   5.321 +}
   5.322 +
   5.323 +.nvd3 .nv-legend .nv-disabled circle {
   5.324 +    fill-opacity: 0;
   5.325 +}
   5.326 +
   5.327 +/* focus */
   5.328 +.nvd3 .nv-brush .extent {
   5.329 +    fill-opacity: 0 !important;
   5.330 +}
   5.331 +
   5.332 +.nvd3 .nv-brushBackground rect {
   5.333 +    stroke: #000;
   5.334 +    stroke-width: .4;
   5.335 +    fill: #fff;
   5.336 +    fill-opacity: .7;
   5.337 +}
   5.338 +
   5.339 +
   5.340 +.nvd3.nv-ohlcBar .nv-ticks .nv-tick {
   5.341 +    stroke-width: 1px;
   5.342 +}
   5.343 +
   5.344 +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover {
   5.345 +    stroke-width: 2px;
   5.346 +}
   5.347 +
   5.348 +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive {
   5.349 +    stroke: #2ca02c;
   5.350 +}
   5.351 +
   5.352 +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative {
   5.353 +    stroke: #d62728;
   5.354 +}
   5.355 +
   5.356 +
   5.357 +.nvd3 .background path {
   5.358 +    fill: none;
   5.359 +    stroke: #EEE;
   5.360 +    stroke-opacity: .4;
   5.361 +    shape-rendering: crispEdges;
   5.362 +}
   5.363 +
   5.364 +.nvd3 .foreground path {
   5.365 +    fill: none;
   5.366 +    stroke-opacity: .7;
   5.367 +}
   5.368 +
   5.369 +.nvd3 .nv-parallelCoordinates-brush .extent 
   5.370 +{
   5.371 +    fill: #fff;
   5.372 +    fill-opacity: .6;
   5.373 +    stroke: gray;
   5.374 +    shape-rendering: crispEdges;
   5.375 +}
   5.376 +
   5.377 +.nvd3 .nv-parallelCoordinates .hover  {
   5.378 +    fill-opacity: 1;
   5.379 +	stroke-width: 3px;
   5.380 +}
   5.381 +
   5.382 +
   5.383 +.nvd3 .missingValuesline line {
   5.384 +  fill: none;
   5.385 +  stroke: black;
   5.386 +  stroke-width: 1;
   5.387 +  stroke-opacity: 1;
   5.388 +  stroke-dasharray: 5, 5; 
   5.389 +}
   5.390 +.nvd3.nv-pie path {
   5.391 +    stroke-opacity: 0;
   5.392 +    transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.393 +    -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.394 +    -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
   5.395 +
   5.396 +}
   5.397 +
   5.398 +.nvd3.nv-pie .nv-pie-title {
   5.399 +    font-size: 24px;
   5.400 +    fill: rgba(19, 196, 249, 0.59);
   5.401 +}
   5.402 +
   5.403 +.nvd3.nv-pie .nv-slice text {
   5.404 +    stroke: #000;
   5.405 +    stroke-width: 0;
   5.406 +}
   5.407 +
   5.408 +.nvd3.nv-pie path {
   5.409 +    stroke: #fff;
   5.410 +    stroke-width: 1px;
   5.411 +    stroke-opacity: 1;
   5.412 +}
   5.413 +
   5.414 +.nvd3.nv-pie .hover path {
   5.415 +    fill-opacity: .7;
   5.416 +}
   5.417 +.nvd3.nv-pie .nv-label {
   5.418 +    pointer-events: none;
   5.419 +}
   5.420 +.nvd3.nv-pie .nv-label rect {
   5.421 +    fill-opacity: 0;
   5.422 +    stroke-opacity: 0;
   5.423 +}
   5.424 +
   5.425 +/* scatter */
   5.426 +.nvd3 .nv-groups .nv-point.hover {
   5.427 +    stroke-width: 20px;
   5.428 +    stroke-opacity: .5;
   5.429 +}
   5.430 +
   5.431 +.nvd3 .nv-scatter .nv-point.hover {
   5.432 +    fill-opacity: 1;
   5.433 +}
   5.434 +.nv-noninteractive {
   5.435 +    pointer-events: none;
   5.436 +}
   5.437 +
   5.438 +.nv-distx, .nv-disty {
   5.439 +    pointer-events: none;
   5.440 +}
   5.441 +
   5.442 +/* sparkline */
   5.443 +.nvd3.nv-sparkline path {
   5.444 +    fill: none;
   5.445 +}
   5.446 +
   5.447 +.nvd3.nv-sparklineplus g.nv-hoverValue {
   5.448 +    pointer-events: none;
   5.449 +}
   5.450 +
   5.451 +.nvd3.nv-sparklineplus .nv-hoverValue line {
   5.452 +    stroke: #333;
   5.453 +    stroke-width: 1.5px;
   5.454 +}
   5.455 +
   5.456 +.nvd3.nv-sparklineplus,
   5.457 +.nvd3.nv-sparklineplus g {
   5.458 +    pointer-events: all;
   5.459 +}
   5.460 +
   5.461 +.nvd3 .nv-hoverArea {
   5.462 +    fill-opacity: 0;
   5.463 +    stroke-opacity: 0;
   5.464 +}
   5.465 +
   5.466 +.nvd3.nv-sparklineplus .nv-xValue,
   5.467 +.nvd3.nv-sparklineplus .nv-yValue {
   5.468 +    stroke-width: 0;
   5.469 +    font-size: .9em;
   5.470 +    font-weight: normal;
   5.471 +}
   5.472 +
   5.473 +.nvd3.nv-sparklineplus .nv-yValue {
   5.474 +    stroke: #f66;
   5.475 +}
   5.476 +
   5.477 +.nvd3.nv-sparklineplus .nv-maxValue {
   5.478 +    stroke: #2ca02c;
   5.479 +    fill: #2ca02c;
   5.480 +}
   5.481 +
   5.482 +.nvd3.nv-sparklineplus .nv-minValue {
   5.483 +    stroke: #d62728;
   5.484 +    fill: #d62728;
   5.485 +}
   5.486 +
   5.487 +.nvd3.nv-sparklineplus .nv-currentValue {
   5.488 +    font-weight: bold;
   5.489 +    font-size: 1.1em;
   5.490 +}
   5.491 +/* stacked area */
   5.492 +.nvd3.nv-stackedarea path.nv-area {
   5.493 +    fill-opacity: .7;
   5.494 +    stroke-opacity: 0;
   5.495 +    transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
   5.496 +    -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
   5.497 +    -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
   5.498 +}
   5.499 +
   5.500 +.nvd3.nv-stackedarea path.nv-area.hover {
   5.501 +    fill-opacity: .9;
   5.502 +}
   5.503 +
   5.504 +
   5.505 +.nvd3.nv-stackedarea .nv-groups .nv-point {
   5.506 +    stroke-opacity: 0;
   5.507 +    fill-opacity: 0;
   5.508 +}
   5.509 +
   5.510 +
   5.511 +.nvtooltip {
   5.512 +    position: absolute;
   5.513 +    background-color: rgba(255,255,255,1.0);
   5.514 +    color: rgba(0,0,0,1.0);
   5.515 +    padding: 1px;
   5.516 +    border: 1px solid rgba(0,0,0,.2);
   5.517 +    z-index: 10000;
   5.518 +    display: block;
   5.519 +
   5.520 +    font-family: Arial;
   5.521 +    font-size: 13px;
   5.522 +    text-align: left;
   5.523 +    pointer-events: none;
   5.524 +
   5.525 +    white-space: nowrap;
   5.526 +
   5.527 +    -webkit-touch-callout: none;
   5.528 +    -webkit-user-select: none;
   5.529 +    -khtml-user-select: none;
   5.530 +    -moz-user-select: none;
   5.531 +    -ms-user-select: none;
   5.532 +    user-select: none;
   5.533 +}
   5.534 +
   5.535 +.nvtooltip {
   5.536 +    background: rgba(255,255,255, 0.8);
   5.537 +    border: 1px solid rgba(0,0,0,0.5);
   5.538 +    border-radius: 4px;
   5.539 +}
   5.540 +
   5.541 +/*Give tooltips that old fade in transition by
   5.542 +    putting a "with-transitions" class on the container div.
   5.543 +*/
   5.544 +.nvtooltip.with-transitions, .with-transitions .nvtooltip {
   5.545 +    transition: opacity 50ms linear;
   5.546 +    -moz-transition: opacity 50ms linear;
   5.547 +    -webkit-transition: opacity 50ms linear;
   5.548 +
   5.549 +    transition-delay: 200ms;
   5.550 +    -moz-transition-delay: 200ms;
   5.551 +    -webkit-transition-delay: 200ms;
   5.552 +}
   5.553 +
   5.554 +.nvtooltip.x-nvtooltip,
   5.555 +.nvtooltip.y-nvtooltip {
   5.556 +    padding: 8px;
   5.557 +}
   5.558 +
   5.559 +.nvtooltip h3 {
   5.560 +    margin: 0;
   5.561 +    padding: 4px 14px;
   5.562 +    line-height: 18px;
   5.563 +    font-weight: normal;
   5.564 +    background-color: rgba(247,247,247,0.75);
   5.565 +    color: rgba(0,0,0,1.0);
   5.566 +    text-align: center;
   5.567 +
   5.568 +    border-bottom: 1px solid #ebebeb;
   5.569 +
   5.570 +    -webkit-border-radius: 5px 5px 0 0;
   5.571 +    -moz-border-radius: 5px 5px 0 0;
   5.572 +    border-radius: 5px 5px 0 0;
   5.573 +}
   5.574 +
   5.575 +.nvtooltip p {
   5.576 +    margin: 0;
   5.577 +    padding: 5px 14px;
   5.578 +    text-align: center;
   5.579 +}
   5.580 +
   5.581 +.nvtooltip span {
   5.582 +    display: inline-block;
   5.583 +    margin: 2px 0;
   5.584 +}
   5.585 +
   5.586 +.nvtooltip table {
   5.587 +    margin: 6px;
   5.588 +    border-spacing:0;
   5.589 +}
   5.590 +
   5.591 +
   5.592 +.nvtooltip table td {
   5.593 +    padding: 2px 9px 2px 0;
   5.594 +    vertical-align: middle;
   5.595 +}
   5.596 +
   5.597 +.nvtooltip table td.key {
   5.598 +    font-weight:normal;
   5.599 +}
   5.600 +.nvtooltip table td.value {
   5.601 +    text-align: right;
   5.602 +    font-weight: bold;
   5.603 +}
   5.604 +
   5.605 +.nvtooltip table tr.highlight td {
   5.606 +    padding: 1px 9px 1px 0;
   5.607 +    border-bottom-style: solid;
   5.608 +    border-bottom-width: 1px;
   5.609 +    border-top-style: solid;
   5.610 +    border-top-width: 1px;
   5.611 +}
   5.612 +
   5.613 +.nvtooltip table td.legend-color-guide div {
   5.614 +    width: 8px;
   5.615 +    height: 8px;
   5.616 +    vertical-align: middle;
   5.617 +}
   5.618 +
   5.619 +.nvtooltip table td.legend-color-guide div {
   5.620 +    width: 12px;
   5.621 +    height: 12px;
   5.622 +    border: 1px solid #999;
   5.623 +}
   5.624 +
   5.625 +.nvtooltip .footer {
   5.626 +    padding: 3px;
   5.627 +    text-align: center;
   5.628 +}
   5.629 +
   5.630 +.nvtooltip-pending-removal {
   5.631 +    pointer-events: none;
   5.632 +    display: none;
   5.633 +}
   5.634 +
   5.635 +
   5.636 +/****
   5.637 +Interactive Layer
   5.638 +*/
   5.639 +.nvd3 .nv-interactiveGuideLine {
   5.640 +    pointer-events:none;
   5.641 +}
   5.642 +.nvd3 line.nv-guideline {
   5.643 +    stroke: #ccc;
   5.644 +}
   5.645 \ No newline at end of file
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/gtc/nv.d3.js	Sun Feb 19 19:45:31 2017 -0800
     6.3 @@ -0,0 +1,13298 @@
     6.4 +/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-06-15 */
     6.5 +(function(){
     6.6 +
     6.7 +// set up main nv object
     6.8 +var nv = {};
     6.9 +
    6.10 +// the major global objects under the nv namespace
    6.11 +nv.dev = false; //set false when in production
    6.12 +nv.tooltip = nv.tooltip || {}; // For the tooltip system
    6.13 +nv.utils = nv.utils || {}; // Utility subsystem
    6.14 +nv.models = nv.models || {}; //stores all the possible models/components
    6.15 +nv.charts = {}; //stores all the ready to use charts
    6.16 +nv.logs = {}; //stores some statistics and potential error messages
    6.17 +nv.dom = {}; //DOM manipulation functions
    6.18 +
    6.19 +nv.dispatch = d3.dispatch('render_start', 'render_end');
    6.20 +
    6.21 +// Function bind polyfill
    6.22 +// Needed ONLY for phantomJS as it's missing until version 2.0 which is unreleased as of this comment
    6.23 +// https://github.com/ariya/phantomjs/issues/10522
    6.24 +// http://kangax.github.io/compat-table/es5/#Function.prototype.bind
    6.25 +// phantomJS is used for running the test suite
    6.26 +if (!Function.prototype.bind) {
    6.27 +    Function.prototype.bind = function (oThis) {
    6.28 +        if (typeof this !== "function") {
    6.29 +            // closest thing possible to the ECMAScript 5 internal IsCallable function
    6.30 +            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    6.31 +        }
    6.32 +
    6.33 +        var aArgs = Array.prototype.slice.call(arguments, 1),
    6.34 +            fToBind = this,
    6.35 +            fNOP = function () {},
    6.36 +            fBound = function () {
    6.37 +                return fToBind.apply(this instanceof fNOP && oThis
    6.38 +                        ? this
    6.39 +                        : oThis,
    6.40 +                    aArgs.concat(Array.prototype.slice.call(arguments)));
    6.41 +            };
    6.42 +
    6.43 +        fNOP.prototype = this.prototype;
    6.44 +        fBound.prototype = new fNOP();
    6.45 +        return fBound;
    6.46 +    };
    6.47 +}
    6.48 +
    6.49 +//  Development render timers - disabled if dev = false
    6.50 +if (nv.dev) {
    6.51 +    nv.dispatch.on('render_start', function(e) {
    6.52 +        nv.logs.startTime = +new Date();
    6.53 +    });
    6.54 +
    6.55 +    nv.dispatch.on('render_end', function(e) {
    6.56 +        nv.logs.endTime = +new Date();
    6.57 +        nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime;
    6.58 +        nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times
    6.59 +    });
    6.60 +}
    6.61 +
    6.62 +// Logs all arguments, and returns the last so you can test things in place
    6.63 +// Note: in IE8 console.log is an object not a function, and if modernizr is used
    6.64 +// then calling Function.prototype.bind with with anything other than a function
    6.65 +// causes a TypeError to be thrown.
    6.66 +nv.log = function() {
    6.67 +    if (nv.dev && window.console && console.log && console.log.apply)
    6.68 +        console.log.apply(console, arguments);
    6.69 +    else if (nv.dev && window.console && typeof console.log == "function" && Function.prototype.bind) {
    6.70 +        var log = Function.prototype.bind.call(console.log, console);
    6.71 +        log.apply(console, arguments);
    6.72 +    }
    6.73 +    return arguments[arguments.length - 1];
    6.74 +};
    6.75 +
    6.76 +// print console warning, should be used by deprecated functions
    6.77 +nv.deprecated = function(name, info) {
    6.78 +    if (console && console.warn) {
    6.79 +        console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || '');
    6.80 +    }
    6.81 +};
    6.82 +
    6.83 +// The nv.render function is used to queue up chart rendering
    6.84 +// in non-blocking async functions.
    6.85 +// When all queued charts are done rendering, nv.dispatch.render_end is invoked.
    6.86 +nv.render = function render(step) {
    6.87 +    // number of graphs to generate in each timeout loop
    6.88 +    step = step || 1;
    6.89 +
    6.90 +    nv.render.active = true;
    6.91 +    nv.dispatch.render_start();
    6.92 +
    6.93 +    var renderLoop = function() {
    6.94 +        var chart, graph;
    6.95 +
    6.96 +        for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {
    6.97 +            chart = graph.generate();
    6.98 +            if (typeof graph.callback == typeof(Function)) graph.callback(chart);
    6.99 +        }
   6.100 +
   6.101 +        nv.render.queue.splice(0, i);
   6.102 +
   6.103 +        if (nv.render.queue.length) {
   6.104 +            setTimeout(renderLoop);
   6.105 +        }
   6.106 +        else {
   6.107 +            nv.dispatch.render_end();
   6.108 +            nv.render.active = false;
   6.109 +        }
   6.110 +    };
   6.111 +
   6.112 +    setTimeout(renderLoop);
   6.113 +};
   6.114 +
   6.115 +nv.render.active = false;
   6.116 +nv.render.queue = [];
   6.117 +
   6.118 +/*
   6.119 +Adds a chart to the async rendering queue. This method can take arguments in two forms:
   6.120 +nv.addGraph({
   6.121 +    generate: <Function>
   6.122 +    callback: <Function>
   6.123 +})
   6.124 +
   6.125 +or
   6.126 +
   6.127 +nv.addGraph(<generate Function>, <callback Function>)
   6.128 +
   6.129 +The generate function should contain code that creates the NVD3 model, sets options
   6.130 +on it, adds data to an SVG element, and invokes the chart model. The generate function
   6.131 +should return the chart model.  See examples/lineChart.html for a usage example.
   6.132 +
   6.133 +The callback function is optional, and it is called when the generate function completes.
   6.134 +*/
   6.135 +nv.addGraph = function(obj) {
   6.136 +    if (typeof arguments[0] === typeof(Function)) {
   6.137 +        obj = {generate: arguments[0], callback: arguments[1]};
   6.138 +    }
   6.139 +
   6.140 +    nv.render.queue.push(obj);
   6.141 +
   6.142 +    if (!nv.render.active) {
   6.143 +        nv.render();
   6.144 +    }
   6.145 +};
   6.146 +
   6.147 +// Node/CommonJS exports
   6.148 +if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') {
   6.149 +  module.exports = nv;
   6.150 +}
   6.151 +
   6.152 +if (typeof(window) !== 'undefined') {
   6.153 +  window.nv = nv;
   6.154 +}
   6.155 +/* Facade for queueing DOM write operations
   6.156 + * with Fastdom (https://github.com/wilsonpage/fastdom)
   6.157 + * if available.
   6.158 + * This could easily be extended to support alternate
   6.159 + * implementations in the future.
   6.160 + */
   6.161 +nv.dom.write = function(callback) {
   6.162 +	if (window.fastdom !== undefined) {
   6.163 +		return fastdom.write(callback);
   6.164 +	}
   6.165 +	return callback();
   6.166 +};
   6.167 +
   6.168 +/* Facade for queueing DOM read operations
   6.169 + * with Fastdom (https://github.com/wilsonpage/fastdom)
   6.170 + * if available.
   6.171 + * This could easily be extended to support alternate
   6.172 + * implementations in the future.
   6.173 + */
   6.174 +nv.dom.read = function(callback) {
   6.175 +	if (window.fastdom !== undefined) {
   6.176 +		return fastdom.read(callback);
   6.177 +	}
   6.178 +	return callback();
   6.179 +};/* Utility class to handle creation of an interactive layer.
   6.180 + This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch
   6.181 + containing the X-coordinate. It can also render a vertical line where the mouse is located.
   6.182 +
   6.183 + dispatch.elementMousemove is the important event to latch onto.  It is fired whenever the mouse moves over
   6.184 + the rectangle. The dispatch is given one object which contains the mouseX/Y location.
   6.185 + It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale.
   6.186 + */
   6.187 +nv.interactiveGuideline = function() {
   6.188 +    "use strict";
   6.189 +
   6.190 +    var tooltip = nv.models.tooltip();
   6.191 +    tooltip.duration(0).hideDelay(0)._isInteractiveLayer(true).hidden(false);
   6.192 +
   6.193 +    //Public settings
   6.194 +    var width = null;
   6.195 +    var height = null;
   6.196 +
   6.197 +    //Please pass in the bounding chart's top and left margins
   6.198 +    //This is important for calculating the correct mouseX/Y positions.
   6.199 +    var margin = {left: 0, top: 0}
   6.200 +        , xScale = d3.scale.linear()
   6.201 +        , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick')
   6.202 +        , showGuideLine = true;
   6.203 +    //Must pass in the bounding chart's <svg> container.
   6.204 +    //The mousemove event is attached to this container.
   6.205 +    var svgContainer = null;
   6.206 +
   6.207 +    // check if IE by looking for activeX
   6.208 +    var isMSIE = "ActiveXObject" in window;
   6.209 +
   6.210 +
   6.211 +    function layer(selection) {
   6.212 +        selection.each(function(data) {
   6.213 +            var container = d3.select(this);
   6.214 +            var availableWidth = (width || 960), availableHeight = (height || 400);
   6.215 +            var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer")
   6.216 +                .data([data]);
   6.217 +            var wrapEnter = wrap.enter()
   6.218 +                .append("g").attr("class", " nv-wrap nv-interactiveLineLayer");
   6.219 +            wrapEnter.append("g").attr("class","nv-interactiveGuideLine");
   6.220 +
   6.221 +            if (!svgContainer) {
   6.222 +                return;
   6.223 +            }
   6.224 +
   6.225 +            function mouseHandler() {
   6.226 +                var d3mouse = d3.mouse(this);
   6.227 +                var mouseX = d3mouse[0];
   6.228 +                var mouseY = d3mouse[1];
   6.229 +                var subtractMargin = true;
   6.230 +                var mouseOutAnyReason = false;
   6.231 +                if (isMSIE) {
   6.232 +                    /*
   6.233 +                     D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.
   6.234 +                     d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving
   6.235 +                     over a rect in IE 10.
   6.236 +                     However, d3.event.offsetX/Y also returns the mouse coordinates
   6.237 +                     relative to the triggering <rect>. So we use offsetX/Y on IE.
   6.238 +                     */
   6.239 +                    mouseX = d3.event.offsetX;
   6.240 +                    mouseY = d3.event.offsetY;
   6.241 +
   6.242 +                    /*
   6.243 +                     On IE, if you attach a mouse event listener to the <svg> container,
   6.244 +                     it will actually trigger it for all the child elements (like <path>, <circle>, etc).
   6.245 +                     When this happens on IE, the offsetX/Y is set to where ever the child element
   6.246 +                     is located.
   6.247 +                     As a result, we do NOT need to subtract margins to figure out the mouse X/Y
   6.248 +                     position under this scenario. Removing the line below *will* cause
   6.249 +                     the interactive layer to not work right on IE.
   6.250 +                     */
   6.251 +                    if(d3.event.target.tagName !== "svg") {
   6.252 +                        subtractMargin = false;
   6.253 +                    }
   6.254 +
   6.255 +                    if (d3.event.target.className.baseVal.match("nv-legend")) {
   6.256 +                        mouseOutAnyReason = true;
   6.257 +                    }
   6.258 +
   6.259 +                }
   6.260 +
   6.261 +                if(subtractMargin) {
   6.262 +                    mouseX -= margin.left;
   6.263 +                    mouseY -= margin.top;
   6.264 +                }
   6.265 +
   6.266 +                /* If mouseX/Y is outside of the chart's bounds,
   6.267 +                 trigger a mouseOut event.
   6.268 +                 */
   6.269 +                if (mouseX < 0 || mouseY < 0
   6.270 +                    || mouseX > availableWidth || mouseY > availableHeight
   6.271 +                    || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined)
   6.272 +                    || mouseOutAnyReason
   6.273 +                    ) {
   6.274 +
   6.275 +                    if (isMSIE) {
   6.276 +                        if (d3.event.relatedTarget
   6.277 +                            && d3.event.relatedTarget.ownerSVGElement === undefined
   6.278 +                            && (d3.event.relatedTarget.className === undefined
   6.279 +                                || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) {
   6.280 +
   6.281 +                            return;
   6.282 +                        }
   6.283 +                    }
   6.284 +                    dispatch.elementMouseout({
   6.285 +                        mouseX: mouseX,
   6.286 +                        mouseY: mouseY
   6.287 +                    });
   6.288 +                    layer.renderGuideLine(null); //hide the guideline
   6.289 +                    tooltip.hidden(true);
   6.290 +                    return;
   6.291 +                } else {
   6.292 +                    tooltip.hidden(false);
   6.293 +                }
   6.294 +
   6.295 +                var pointXValue = xScale.invert(mouseX);
   6.296 +                dispatch.elementMousemove({
   6.297 +                    mouseX: mouseX,
   6.298 +                    mouseY: mouseY,
   6.299 +                    pointXValue: pointXValue
   6.300 +                });
   6.301 +
   6.302 +                //If user double clicks the layer, fire a elementDblclick
   6.303 +                if (d3.event.type === "dblclick") {
   6.304 +                    dispatch.elementDblclick({
   6.305 +                        mouseX: mouseX,
   6.306 +                        mouseY: mouseY,
   6.307 +                        pointXValue: pointXValue
   6.308 +                    });
   6.309 +                }
   6.310 +
   6.311 +                // if user single clicks the layer, fire elementClick
   6.312 +                if (d3.event.type === 'click') {
   6.313 +                    dispatch.elementClick({
   6.314 +                        mouseX: mouseX,
   6.315 +                        mouseY: mouseY,
   6.316 +                        pointXValue: pointXValue
   6.317 +                    });
   6.318 +                }
   6.319 +            }
   6.320 +
   6.321 +            svgContainer
   6.322 +                .on("touchmove",mouseHandler)
   6.323 +                .on("mousemove",mouseHandler, true)
   6.324 +                .on("mouseout" ,mouseHandler,true)
   6.325 +                .on("dblclick" ,mouseHandler)
   6.326 +                .on("click", mouseHandler)
   6.327 +            ;
   6.328 +
   6.329 +            layer.guideLine = null;
   6.330 +            //Draws a vertical guideline at the given X postion.
   6.331 +            layer.renderGuideLine = function(x) {
   6.332 +                if (!showGuideLine) return;
   6.333 +                if (layer.guideLine && layer.guideLine.attr("x1") === x) return;
   6.334 +                nv.dom.write(function() {
   6.335 +                    var line = wrap.select(".nv-interactiveGuideLine")
   6.336 +                        .selectAll("line")
   6.337 +                        .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String);
   6.338 +                    line.enter()
   6.339 +                        .append("line")
   6.340 +                        .attr("class", "nv-guideline")
   6.341 +                        .attr("x1", function(d) { return d;})
   6.342 +                        .attr("x2", function(d) { return d;})
   6.343 +                        .attr("y1", availableHeight)
   6.344 +                        .attr("y2",0);
   6.345 +                    line.exit().remove();
   6.346 +                });
   6.347 +            }
   6.348 +        });
   6.349 +    }
   6.350 +
   6.351 +    layer.dispatch = dispatch;
   6.352 +    layer.tooltip = tooltip;
   6.353 +
   6.354 +    layer.margin = function(_) {
   6.355 +        if (!arguments.length) return margin;
   6.356 +        margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
   6.357 +        margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
   6.358 +        return layer;
   6.359 +    };
   6.360 +
   6.361 +    layer.width = function(_) {
   6.362 +        if (!arguments.length) return width;
   6.363 +        width = _;
   6.364 +        return layer;
   6.365 +    };
   6.366 +
   6.367 +    layer.height = function(_) {
   6.368 +        if (!arguments.length) return height;
   6.369 +        height = _;
   6.370 +        return layer;
   6.371 +    };
   6.372 +
   6.373 +    layer.xScale = function(_) {
   6.374 +        if (!arguments.length) return xScale;
   6.375 +        xScale = _;
   6.376 +        return layer;
   6.377 +    };
   6.378 +
   6.379 +    layer.showGuideLine = function(_) {
   6.380 +        if (!arguments.length) return showGuideLine;
   6.381 +        showGuideLine = _;
   6.382 +        return layer;
   6.383 +    };
   6.384 +
   6.385 +    layer.svgContainer = function(_) {
   6.386 +        if (!arguments.length) return svgContainer;
   6.387 +        svgContainer = _;
   6.388 +        return layer;
   6.389 +    };
   6.390 +
   6.391 +    return layer;
   6.392 +};
   6.393 +
   6.394 +/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted.
   6.395 + This is different from normal bisectLeft; this function finds the nearest index to insert the search value.
   6.396 +
   6.397 + For instance, lets say your array is [1,2,3,5,10,30], and you search for 28.
   6.398 + Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10.  But interactiveBisect will return 5
   6.399 + because 28 is closer to 30 than 10.
   6.400 +
   6.401 + Unit tests can be found in: interactiveBisectTest.html
   6.402 +
   6.403 + Has the following known issues:
   6.404 + * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order.
   6.405 + * Won't work if there are duplicate x coordinate values.
   6.406 + */
   6.407 +nv.interactiveBisect = function (values, searchVal, xAccessor) {
   6.408 +    "use strict";
   6.409 +    if (! (values instanceof Array)) {
   6.410 +        return null;
   6.411 +    }
   6.412 +    var _xAccessor;
   6.413 +    if (typeof xAccessor !== 'function') {
   6.414 +        _xAccessor = function(d) {
   6.415 +            return d.x;
   6.416 +        }
   6.417 +    } else {
   6.418 +        _xAccessor = xAccessor;
   6.419 +    }
   6.420 +    var _cmp = function(d, v) {
   6.421 +        // Accessors are no longer passed the index of the element along with
   6.422 +        // the element itself when invoked by d3.bisector.
   6.423 +        //
   6.424 +        // Starting at D3 v3.4.4, d3.bisector() started inspecting the
   6.425 +        // function passed to determine if it should consider it an accessor
   6.426 +        // or a comparator. This meant that accessors that take two arguments
   6.427 +        // (expecting an index as the second parameter) are treated as
   6.428 +        // comparators where the second argument is the search value against
   6.429 +        // which the first argument is compared.
   6.430 +        return _xAccessor(d) - v;
   6.431 +    };
   6.432 +
   6.433 +    var bisect = d3.bisector(_cmp).left;
   6.434 +    var index = d3.max([0, bisect(values,searchVal) - 1]);
   6.435 +    var currentValue = _xAccessor(values[index]);
   6.436 +
   6.437 +    if (typeof currentValue === 'undefined') {
   6.438 +        currentValue = index;
   6.439 +    }
   6.440 +
   6.441 +    if (currentValue === searchVal) {
   6.442 +        return index; //found exact match
   6.443 +    }
   6.444 +
   6.445 +    var nextIndex = d3.min([index+1, values.length - 1]);
   6.446 +    var nextValue = _xAccessor(values[nextIndex]);
   6.447 +
   6.448 +    if (typeof nextValue === 'undefined') {
   6.449 +        nextValue = nextIndex;
   6.450 +    }
   6.451 +
   6.452 +    if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal)) {
   6.453 +        return index;
   6.454 +    } else {
   6.455 +        return nextIndex
   6.456 +    }
   6.457 +};
   6.458 +
   6.459 +/*
   6.460 + Returns the index in the array "values" that is closest to searchVal.
   6.461 + Only returns an index if searchVal is within some "threshold".
   6.462 + Otherwise, returns null.
   6.463 + */
   6.464 +nv.nearestValueIndex = function (values, searchVal, threshold) {
   6.465 +    "use strict";
   6.466 +    var yDistMax = Infinity, indexToHighlight = null;
   6.467 +    values.forEach(function(d,i) {
   6.468 +        var delta = Math.abs(searchVal - d);
   6.469 +        if ( d != null && delta <= yDistMax && delta < threshold) {
   6.470 +            yDistMax = delta;
   6.471 +            indexToHighlight = i;
   6.472 +        }
   6.473 +    });
   6.474 +    return indexToHighlight;
   6.475 +};
   6.476 +/* Tooltip rendering model for nvd3 charts.
   6.477 + window.nv.models.tooltip is the updated,new way to render tooltips.
   6.478 +
   6.479 + window.nv.tooltip.show is the old tooltip code.
   6.480 + window.nv.tooltip.* also has various helper methods.
   6.481 + */
   6.482 +(function() {
   6.483 +    "use strict";
   6.484 +
   6.485 +    /* Model which can be instantiated to handle tooltip rendering.
   6.486 +     Example usage:
   6.487 +     var tip = nv.models.tooltip().gravity('w').distance(23)
   6.488 +     .data(myDataObject);
   6.489 +
   6.490 +     tip();    //just invoke the returned function to render tooltip.
   6.491 +     */
   6.492 +    nv.models.tooltip = function() {
   6.493 +
   6.494 +        /*
   6.495 +        Tooltip data. If data is given in the proper format, a consistent tooltip is generated.
   6.496 +        Example Format of data:
   6.497 +        {
   6.498 +            key: "Date",
   6.499 +            value: "August 2009",
   6.500 +            series: [
   6.501 +                {key: "Series 1", value: "Value 1", color: "#000"},
   6.502 +                {key: "Series 2", value: "Value 2", color: "#00f"}
   6.503 +            ]
   6.504 +        }
   6.505 +        */
   6.506 +        var data = null;
   6.507 +        var gravity = 'w'   //Can be 'n','s','e','w'. Determines how tooltip is positioned.
   6.508 +            ,   distance = 25   //Distance to offset tooltip from the mouse location.
   6.509 +            ,   snapDistance = 0   //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
   6.510 +            ,   fixedTop = null //If not null, this fixes the top position of the tooltip.
   6.511 +            ,   classes = null  //Attaches additional CSS classes to the tooltip DIV that is created.
   6.512 +            ,   chartContainer = null   //Parent dom element of the SVG that holds the chart.
   6.513 +            ,   hidden = true  // start off hidden, toggle with hide/show functions below
   6.514 +            ,   hideDelay = 400  // delay before the tooltip hides after calling hide()
   6.515 +            ,   tooltip = null // d3 select of tooltipElem below
   6.516 +            ,   tooltipElem = null  //actual DOM element representing the tooltip.
   6.517 +            ,   position = {left: null, top: null}   //Relative position of the tooltip inside chartContainer.
   6.518 +            ,   offset = {left: 0, top: 0}   //Offset of tooltip against the pointer
   6.519 +            ,   enabled = true  //True -> tooltips are rendered. False -> don't render tooltips.
   6.520 +            ,   duration = 100 // duration for tooltip movement
   6.521 +            ,   headerEnabled = true
   6.522 +        ;
   6.523 +
   6.524 +        // set to true by interactive layer to adjust tooltip positions
   6.525 +        // eventually we should probably fix interactive layer to get the position better.
   6.526 +        // for now this is needed if you want to set chartContainer for normal tooltips, else it "fixes" it to broken
   6.527 +        var isInteractiveLayer = false;
   6.528 +
   6.529 +        //Generates a unique id when you create a new tooltip() object
   6.530 +        var id = "nvtooltip-" + Math.floor(Math.random() * 100000);
   6.531 +
   6.532 +        //CSS class to specify whether element should not have mouse events.
   6.533 +        var  nvPointerEventsClass = "nv-pointer-events-none";
   6.534 +
   6.535 +        //Format function for the tooltip values column
   6.536 +        var valueFormatter = function(d,i) {
   6.537 +            return d;
   6.538 +        };
   6.539 +
   6.540 +        //Format function for the tooltip header value.
   6.541 +        var headerFormatter = function(d) {
   6.542 +            return d;
   6.543 +        };
   6.544 +
   6.545 +        var keyFormatter = function(d, i) {
   6.546 +            return d;
   6.547 +        };
   6.548 +
   6.549 +        //By default, the tooltip model renders a beautiful table inside a DIV.
   6.550 +        //You can override this function if a custom tooltip is desired.
   6.551 +        var contentGenerator = function(d) {
   6.552 +            if (d === null) {
   6.553 +                return '';
   6.554 +            }
   6.555 +
   6.556 +            var table = d3.select(document.createElement("table"));
   6.557 +            if (headerEnabled) {
   6.558 +                var theadEnter = table.selectAll("thead")
   6.559 +                    .data([d])
   6.560 +                    .enter().append("thead");
   6.561 +
   6.562 +                theadEnter.append("tr")
   6.563 +                    .append("td")
   6.564 +                    .attr("colspan", 3)
   6.565 +                    .append("strong")
   6.566 +                    .classed("x-value", true)
   6.567 +                    .html(headerFormatter(d.value));
   6.568 +            }
   6.569 +
   6.570 +            var tbodyEnter = table.selectAll("tbody")
   6.571 +                .data([d])
   6.572 +                .enter().append("tbody");
   6.573 +
   6.574 +            var trowEnter = tbodyEnter.selectAll("tr")
   6.575 +                    .data(function(p) { return p.series})
   6.576 +                    .enter()
   6.577 +                    .append("tr")
   6.578 +                    .classed("highlight", function(p) { return p.highlight});
   6.579 +
   6.580 +            trowEnter.append("td")
   6.581 +                .classed("legend-color-guide",true)
   6.582 +                .append("div")
   6.583 +                .style("background-color", function(p) { return p.color});
   6.584 +
   6.585 +            trowEnter.append("td")
   6.586 +                .classed("key",true)
   6.587 +                .html(function(p, i) {return keyFormatter(p.key, i)});
   6.588 +
   6.589 +            trowEnter.append("td")
   6.590 +                .classed("value",true)
   6.591 +                .html(function(p, i) { return valueFormatter(p.value, i) });
   6.592 +
   6.593 +
   6.594 +            trowEnter.selectAll("td").each(function(p) {
   6.595 +                if (p.highlight) {
   6.596 +                    var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]);
   6.597 +                    var opacity = 0.6;
   6.598 +                    d3.select(this)
   6.599 +                        .style("border-bottom-color", opacityScale(opacity))
   6.600 +                        .style("border-top-color", opacityScale(opacity))
   6.601 +                    ;
   6.602 +                }
   6.603 +            });
   6.604 +
   6.605 +            var html = table.node().outerHTML;
   6.606 +            if (d.footer !== undefined)
   6.607 +                html += "<div class='footer'>" + d.footer + "</div>";
   6.608 +            return html;
   6.609 +
   6.610 +        };
   6.611 +
   6.612 +        var dataSeriesExists = function(d) {
   6.613 +            if (d && d.series) {
   6.614 +                if (d.series instanceof Array) {
   6.615 +                    return !!d.series.length;
   6.616 +                }
   6.617 +                // if object, it's okay just convert to array of the object
   6.618 +                if (d.series instanceof Object) {
   6.619 +                    d.series = [d.series];
   6.620 +                    return true;
   6.621 +                }
   6.622 +            }
   6.623 +            return false;
   6.624 +        };
   6.625 +
   6.626 +        var calcTooltipPosition = function(pos) {
   6.627 +            if (!tooltipElem) return;
   6.628 +
   6.629 +            nv.dom.read(function() {
   6.630 +                var height = parseInt(tooltipElem.offsetHeight, 10),
   6.631 +                    width = parseInt(tooltipElem.offsetWidth, 10),
   6.632 +                    windowWidth = nv.utils.windowSize().width,
   6.633 +                    windowHeight = nv.utils.windowSize().height,
   6.634 +                    scrollTop = window.pageYOffset,
   6.635 +                    scrollLeft = window.pageXOffset,
   6.636 +                    left, top;
   6.637 +
   6.638 +                windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16;
   6.639 +                windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16;
   6.640 +
   6.641 +
   6.642 +                //Helper functions to find the total offsets of a given DOM element.
   6.643 +                //Looks up the entire ancestry of an element, up to the first relatively positioned element.
   6.644 +                var tooltipTop = function ( Elem ) {
   6.645 +                    var offsetTop = top;
   6.646 +                    do {
   6.647 +                        if( !isNaN( Elem.offsetTop ) ) {
   6.648 +                            offsetTop += (Elem.offsetTop);
   6.649 +                        }
   6.650 +                        Elem = Elem.offsetParent;
   6.651 +                    } while( Elem );
   6.652 +                    return offsetTop;
   6.653 +                };
   6.654 +                var tooltipLeft = function ( Elem ) {
   6.655 +                    var offsetLeft = left;
   6.656 +                    do {
   6.657 +                        if( !isNaN( Elem.offsetLeft ) ) {
   6.658 +                            offsetLeft += (Elem.offsetLeft);
   6.659 +                        }
   6.660 +                        Elem = Elem.offsetParent;
   6.661 +                    } while( Elem );
   6.662 +                    return offsetLeft;
   6.663 +                };
   6.664 +
   6.665 +                // calculate position based on gravity
   6.666 +                var tLeft, tTop;
   6.667 +                switch (gravity) {
   6.668 +                    case 'e':
   6.669 +                        left = pos[0] - width - distance;
   6.670 +                        top = pos[1] - (height / 2);
   6.671 +                        tLeft = tooltipLeft(tooltipElem);
   6.672 +                        tTop = tooltipTop(tooltipElem);
   6.673 +                        if (tLeft < scrollLeft) left = pos[0] + distance > scrollLeft ? pos[0] + distance : scrollLeft - tLeft + left;
   6.674 +                        if (tTop < scrollTop) top = scrollTop - tTop + top;
   6.675 +                        if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
   6.676 +                        break;
   6.677 +                    case 'w':
   6.678 +                        left = pos[0] + distance;
   6.679 +                        top = pos[1] - (height / 2);
   6.680 +                        tLeft = tooltipLeft(tooltipElem);
   6.681 +                        tTop = tooltipTop(tooltipElem);
   6.682 +                        if (tLeft + width > windowWidth) left = pos[0] - width - distance;
   6.683 +                        if (tTop < scrollTop) top = scrollTop + 5;
   6.684 +                        if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
   6.685 +                        break;
   6.686 +                    case 'n':
   6.687 +                        left = pos[0] - (width / 2) - 5;
   6.688 +                        top = pos[1] + distance;
   6.689 +                        tLeft = tooltipLeft(tooltipElem);
   6.690 +                        tTop = tooltipTop(tooltipElem);
   6.691 +                        if (tLeft < scrollLeft) left = scrollLeft + 5;
   6.692 +                        if (tLeft + width > windowWidth) left = left - width/2 + 5;
   6.693 +                        if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
   6.694 +                        break;
   6.695 +                    case 's':
   6.696 +                        left = pos[0] - (width / 2);
   6.697 +                        top = pos[1] - height - distance;
   6.698 +                        tLeft = tooltipLeft(tooltipElem);
   6.699 +                        tTop = tooltipTop(tooltipElem);
   6.700 +                        if (tLeft < scrollLeft) left = scrollLeft + 5;
   6.701 +                        if (tLeft + width > windowWidth) left = left - width/2 + 5;
   6.702 +                        if (scrollTop > tTop) top = scrollTop;
   6.703 +                        break;
   6.704 +                    case 'none':
   6.705 +                        left = pos[0];
   6.706 +                        top = pos[1] - distance;
   6.707 +                        tLeft = tooltipLeft(tooltipElem);
   6.708 +                        tTop = tooltipTop(tooltipElem);
   6.709 +                        break;
   6.710 +                }
   6.711 +                
   6.712 +                // adjust tooltip offsets
   6.713 +                left -= offset.left;
   6.714 +                top -= offset.top;
   6.715 +
   6.716 +                // using tooltip.style('transform') returns values un-usable for tween
   6.717 +                var box = tooltipElem.getBoundingClientRect();
   6.718 +                var scrollTop  = window.pageYOffset || document.documentElement.scrollTop;
   6.719 +                var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
   6.720 +                var old_translate = 'translate(' + (box.left + scrollLeft) + 'px, ' + (box.top + scrollTop) + 'px)';
   6.721 +                var new_translate = 'translate(' + left + 'px, ' + top + 'px)';
   6.722 +                var translateInterpolator = d3.interpolateString(old_translate, new_translate);
   6.723 +
   6.724 +                var is_hidden = tooltip.style('opacity') < 0.1;
   6.725 +
   6.726 +                // delay hiding a bit to avoid flickering
   6.727 +                if (hidden) {
   6.728 +                    tooltip
   6.729 +                        .transition()
   6.730 +                        .delay(hideDelay)
   6.731 +                        .duration(0)
   6.732 +                        .style('opacity', 0);
   6.733 +                } else {
   6.734 +                    tooltip
   6.735 +                        .interrupt() // cancel running transitions
   6.736 +                        .transition()
   6.737 +                        .duration(is_hidden ? 0 : duration)
   6.738 +                        // using tween since some versions of d3 can't auto-tween a translate on a div
   6.739 +                        .styleTween('transform', function (d) {
   6.740 +                            return translateInterpolator;
   6.741 +                        }, 'important')
   6.742 +                        // Safari has its own `-webkit-transform` and does not support `transform` 
   6.743 +                        // transform tooltip without transition only in Safari
   6.744 +                        .style('-webkit-transform', new_translate)
   6.745 +                        .style('opacity', 1);
   6.746 +                }
   6.747 +
   6.748 +
   6.749 +
   6.750 +            });
   6.751 +        };
   6.752 +
   6.753 +        //In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed.
   6.754 +        function convertViewBoxRatio() {
   6.755 +            if (chartContainer) {
   6.756 +                var svg = d3.select(chartContainer);
   6.757 +                if (svg.node().tagName !== "svg") {
   6.758 +                    svg = svg.select("svg");
   6.759 +                }
   6.760 +                var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
   6.761 +                if (viewBox) {
   6.762 +                    viewBox = viewBox.split(' ');
   6.763 +                    var ratio = parseInt(svg.style('width'), 10) / viewBox[2];
   6.764 +
   6.765 +                    position.left = position.left * ratio;
   6.766 +                    position.top  = position.top * ratio;
   6.767 +                }
   6.768 +            }
   6.769 +        }
   6.770 +
   6.771 +        //Creates new tooltip container, or uses existing one on DOM.
   6.772 +        function initTooltip() {
   6.773 +            if (!tooltip) {
   6.774 +                var body;
   6.775 +                if (chartContainer) {
   6.776 +                    body = chartContainer;
   6.777 +                } else {
   6.778 +                    body = document.body;
   6.779 +                }
   6.780 +                //Create new tooltip div if it doesn't exist on DOM.
   6.781 +                tooltip = d3.select(body).append("div")
   6.782 +                    .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip"))
   6.783 +                    .attr("id", id);
   6.784 +                tooltip.style("top", 0).style("left", 0);
   6.785 +                tooltip.style('opacity', 0);
   6.786 +                tooltip.selectAll("div, table, td, tr").classed(nvPointerEventsClass, true);
   6.787 +                tooltip.classed(nvPointerEventsClass, true);
   6.788 +                tooltipElem = tooltip.node();
   6.789 +            }
   6.790 +        }
   6.791 +
   6.792 +        //Draw the tooltip onto the DOM.
   6.793 +        function nvtooltip() {
   6.794 +            if (!enabled) return;
   6.795 +            if (!dataSeriesExists(data)) return;
   6.796 +
   6.797 +            convertViewBoxRatio();
   6.798 +
   6.799 +            var left = position.left;
   6.800 +            var top = (fixedTop !== null) ? fixedTop : position.top;
   6.801 +
   6.802 +            nv.dom.write(function () {
   6.803 +                initTooltip();
   6.804 +                // generate data and set it into tooltip
   6.805 +                // Bonus - If you override contentGenerator and return falsey you can use something like
   6.806 +                //         React or Knockout to bind the data for your tooltip
   6.807 +                var newContent = contentGenerator(data);
   6.808 +                if (newContent) {
   6.809 +                    tooltipElem.innerHTML = newContent;
   6.810 +                }
   6.811 +
   6.812 +                if (chartContainer && isInteractiveLayer) {
   6.813 +                    nv.dom.read(function() {
   6.814 +                        var svgComp = chartContainer.getElementsByTagName("svg")[0];
   6.815 +                        var svgOffset = {left:0,top:0};
   6.816 +                        if (svgComp) {
   6.817 +                            var svgBound = svgComp.getBoundingClientRect();
   6.818 +                            var chartBound = chartContainer.getBoundingClientRect();
   6.819 +                            var svgBoundTop = svgBound.top;
   6.820 +
   6.821 +                            //Defensive code. Sometimes, svgBoundTop can be a really negative
   6.822 +                            //  number, like -134254. That's a bug.
   6.823 +                            //  If such a number is found, use zero instead. FireFox bug only
   6.824 +                            if (svgBoundTop < 0) {
   6.825 +                                var containerBound = chartContainer.getBoundingClientRect();
   6.826 +                                svgBoundTop = (Math.abs(svgBoundTop) > containerBound.height) ? 0 : svgBoundTop;
   6.827 +                            }
   6.828 +                            svgOffset.top = Math.abs(svgBoundTop - chartBound.top);
   6.829 +                            svgOffset.left = Math.abs(svgBound.left - chartBound.left);
   6.830 +                        }
   6.831 +                        //If the parent container is an overflow <div> with scrollbars, subtract the scroll offsets.
   6.832 +                        //You need to also add any offset between the <svg> element and its containing <div>
   6.833 +                        //Finally, add any offset of the containing <div> on the whole page.
   6.834 +                        left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft;
   6.835 +                        top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop;
   6.836 +
   6.837 +                        if (snapDistance && snapDistance > 0) {
   6.838 +                            top = Math.floor(top/snapDistance) * snapDistance;
   6.839 +                        }
   6.840 +                        calcTooltipPosition([left,top]);
   6.841 +                    });
   6.842 +                } else {
   6.843 +                    calcTooltipPosition([left,top]);
   6.844 +                }
   6.845 +            });
   6.846 +
   6.847 +            return nvtooltip;
   6.848 +        }
   6.849 +
   6.850 +        nvtooltip.nvPointerEventsClass = nvPointerEventsClass;
   6.851 +        nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip);
   6.852 +
   6.853 +        nvtooltip._options = Object.create({}, {
   6.854 +            // simple read/write options
   6.855 +            duration: {get: function(){return duration;}, set: function(_){duration=_;}},
   6.856 +            gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}},
   6.857 +            distance: {get: function(){return distance;}, set: function(_){distance=_;}},
   6.858 +            snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}},
   6.859 +            classes: {get: function(){return classes;}, set: function(_){classes=_;}},
   6.860 +            chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}},
   6.861 +            fixedTop: {get: function(){return fixedTop;}, set: function(_){fixedTop=_;}},
   6.862 +            enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}},
   6.863 +            hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}},
   6.864 +            contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}},
   6.865 +            valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}},
   6.866 +            headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}},
   6.867 +            keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
   6.868 +            headerEnabled:   {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}},
   6.869 +
   6.870 +            // internal use only, set by interactive layer to adjust position.
   6.871 +            _isInteractiveLayer: {get: function(){return isInteractiveLayer;}, set: function(_){isInteractiveLayer=!!_;}},
   6.872 +
   6.873 +            // options with extra logic
   6.874 +            position: {get: function(){return position;}, set: function(_){
   6.875 +                position.left = _.left !== undefined ? _.left : position.left;
   6.876 +                position.top  = _.top  !== undefined ? _.top  : position.top;
   6.877 +            }},
   6.878 +            offset: {get: function(){return offset;}, set: function(_){
   6.879 +                offset.left = _.left !== undefined ? _.left : offset.left;
   6.880 +                offset.top  = _.top  !== undefined ? _.top  : offset.top;
   6.881 +            }},
   6.882 +            hidden: {get: function(){return hidden;}, set: function(_){
   6.883 +                if (hidden != _) {
   6.884 +                    hidden = !!_;
   6.885 +                    nvtooltip();
   6.886 +                }
   6.887 +            }},
   6.888 +            data: {get: function(){return data;}, set: function(_){
   6.889 +                // if showing a single data point, adjust data format with that
   6.890 +                if (_.point) {
   6.891 +                    _.value = _.point.x;
   6.892 +                    _.series = _.series || {};
   6.893 +                    _.series.value = _.point.y;
   6.894 +                    _.series.color = _.point.color || _.series.color;
   6.895 +                }
   6.896 +                data = _;
   6.897 +            }},
   6.898 +
   6.899 +            // read only properties
   6.900 +            tooltipElem: {get: function(){return tooltipElem;}, set: function(_){}},
   6.901 +            id: {get: function(){return id;}, set: function(_){}}
   6.902 +        });
   6.903 +
   6.904 +        nv.utils.initOptions(nvtooltip);
   6.905 +        return nvtooltip;
   6.906 +    };
   6.907 +
   6.908 +})();
   6.909 +
   6.910 +
   6.911 +/*
   6.912 +Gets the browser window size
   6.913 +
   6.914 +Returns object with height and width properties
   6.915 + */
   6.916 +nv.utils.windowSize = function() {
   6.917 +    // Sane defaults
   6.918 +    var size = {width: 640, height: 480};
   6.919 +
   6.920 +    // Most recent browsers use
   6.921 +    if (window.innerWidth && window.innerHeight) {
   6.922 +        size.width = window.innerWidth;
   6.923 +        size.height = window.innerHeight;
   6.924 +        return (size);
   6.925 +    }
   6.926 +
   6.927 +    // IE can use depending on mode it is in
   6.928 +    if (document.compatMode=='CSS1Compat' &&
   6.929 +        document.documentElement &&
   6.930 +        document.documentElement.offsetWidth ) {
   6.931 +
   6.932 +        size.width = document.documentElement.offsetWidth;
   6.933 +        size.height = document.documentElement.offsetHeight;
   6.934 +        return (size);
   6.935 +    }
   6.936 +
   6.937 +    // Earlier IE uses Doc.body
   6.938 +    if (document.body && document.body.offsetWidth) {
   6.939 +        size.width = document.body.offsetWidth;
   6.940 +        size.height = document.body.offsetHeight;
   6.941 +        return (size);
   6.942 +    }
   6.943 +
   6.944 +    return (size);
   6.945 +};
   6.946 +
   6.947 +/*
   6.948 +Binds callback function to run when window is resized
   6.949 + */
   6.950 +nv.utils.windowResize = function(handler) {
   6.951 +    if (window.addEventListener) {
   6.952 +        window.addEventListener('resize', handler);
   6.953 +    } else {
   6.954 +        nv.log("ERROR: Failed to bind to window.resize with: ", handler);
   6.955 +    }
   6.956 +    // return object with clear function to remove the single added callback.
   6.957 +    return {
   6.958 +        callback: handler,
   6.959 +        clear: function() {
   6.960 +            window.removeEventListener('resize', handler);
   6.961 +        }
   6.962 +    }
   6.963 +};
   6.964 +
   6.965 +
   6.966 +/*
   6.967 +Backwards compatible way to implement more d3-like coloring of graphs.
   6.968 +Can take in nothing, an array, or a function/scale
   6.969 +To use a normal scale, get the range and pass that because we must be able
   6.970 +to take two arguments and use the index to keep backward compatibility
   6.971 +*/
   6.972 +nv.utils.getColor = function(color) {
   6.973 +    //if you pass in nothing, get default colors back
   6.974 +    if (color === undefined) {
   6.975 +        return nv.utils.defaultColor();
   6.976 +
   6.977 +    //if passed an array, turn it into a color scale
   6.978 +    // use isArray, instanceof fails if d3 range is created in an iframe
   6.979 +    } else if(Array.isArray(color)) {
   6.980 +        var color_scale = d3.scale.ordinal().range(color);
   6.981 +        return function(d, i) {
   6.982 +            var key = i === undefined ? d : i;
   6.983 +            return d.color || color_scale(key);
   6.984 +        };
   6.985 +
   6.986 +    //if passed a function or scale, return it, or whatever it may be
   6.987 +    //external libs, such as angularjs-nvd3-directives use this
   6.988 +    } else {
   6.989 +        //can't really help it if someone passes rubbish as color
   6.990 +        return color;
   6.991 +    }
   6.992 +};
   6.993 +
   6.994 +
   6.995 +/*
   6.996 +Default color chooser uses a color scale of 20 colors from D3
   6.997 + https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors
   6.998 + */
   6.999 +nv.utils.defaultColor = function() {
  6.1000 +    // get range of the scale so we'll turn it into our own function.
  6.1001 +    return nv.utils.getColor(d3.scale.category20().range());
  6.1002 +};
  6.1003 +
  6.1004 +
  6.1005 +/*
  6.1006 +Returns a color function that takes the result of 'getKey' for each series and
  6.1007 +looks for a corresponding color from the dictionary
  6.1008 +*/
  6.1009 +nv.utils.customTheme = function(dictionary, getKey, defaultColors) {
  6.1010 +    // use default series.key if getKey is undefined
  6.1011 +    getKey = getKey || function(series) { return series.key };
  6.1012 +    defaultColors = defaultColors || d3.scale.category20().range();
  6.1013 +
  6.1014 +    // start at end of default color list and walk back to index 0
  6.1015 +    var defIndex = defaultColors.length;
  6.1016 +
  6.1017 +    return function(series, index) {
  6.1018 +        var key = getKey(series);
  6.1019 +        if (typeof dictionary[key] === 'function') {
  6.1020 +            return dictionary[key]();
  6.1021 +        } else if (dictionary[key] !== undefined) {
  6.1022 +            return dictionary[key];
  6.1023 +        } else {
  6.1024 +            // no match in dictionary, use a default color
  6.1025 +            if (!defIndex) {
  6.1026 +                // used all the default colors, start over
  6.1027 +                defIndex = defaultColors.length;
  6.1028 +            }
  6.1029 +            defIndex = defIndex - 1;
  6.1030 +            return defaultColors[defIndex];
  6.1031 +        }
  6.1032 +    };
  6.1033 +};
  6.1034 +
  6.1035 +
  6.1036 +/*
  6.1037 +From the PJAX example on d3js.org, while this is not really directly needed
  6.1038 +it's a very cool method for doing pjax, I may expand upon it a little bit,
  6.1039 +open to suggestions on anything that may be useful
  6.1040 +*/
  6.1041 +nv.utils.pjax = function(links, content) {
  6.1042 +
  6.1043 +    var load = function(href) {
  6.1044 +        d3.html(href, function(fragment) {
  6.1045 +            var target = d3.select(content).node();
  6.1046 +            target.parentNode.replaceChild(
  6.1047 +                d3.select(fragment).select(content).node(),
  6.1048 +                target);
  6.1049 +            nv.utils.pjax(links, content);
  6.1050 +        });
  6.1051 +    };
  6.1052 +
  6.1053 +    d3.selectAll(links).on("click", function() {
  6.1054 +        history.pushState(this.href, this.textContent, this.href);
  6.1055 +        load(this.href);
  6.1056 +        d3.event.preventDefault();
  6.1057 +    });
  6.1058 +
  6.1059 +    d3.select(window).on("popstate", function() {
  6.1060 +        if (d3.event.state) {
  6.1061 +            load(d3.event.state);
  6.1062 +        }
  6.1063 +    });
  6.1064 +};
  6.1065 +
  6.1066 +
  6.1067 +/*
  6.1068 +For when we want to approximate the width in pixels for an SVG:text element.
  6.1069 +Most common instance is when the element is in a display:none; container.
  6.1070 +Forumla is : text.length * font-size * constant_factor
  6.1071 +*/
  6.1072 +nv.utils.calcApproxTextWidth = function (svgTextElem) {
  6.1073 +    if (typeof svgTextElem.style === 'function'
  6.1074 +        && typeof svgTextElem.text === 'function') {
  6.1075 +
  6.1076 +        var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""), 10);
  6.1077 +        var textLength = svgTextElem.text().length;
  6.1078 +        return textLength * fontSize * 0.5;
  6.1079 +    }
  6.1080 +    return 0;
  6.1081 +};
  6.1082 +
  6.1083 +
  6.1084 +/*
  6.1085 +Numbers that are undefined, null or NaN, convert them to zeros.
  6.1086 +*/
  6.1087 +nv.utils.NaNtoZero = function(n) {
  6.1088 +    if (typeof n !== 'number'
  6.1089 +        || isNaN(n)
  6.1090 +        || n === null
  6.1091 +        || n === Infinity
  6.1092 +        || n === -Infinity) {
  6.1093 +
  6.1094 +        return 0;
  6.1095 +    }
  6.1096 +    return n;
  6.1097 +};
  6.1098 +
  6.1099 +/*
  6.1100 +Add a way to watch for d3 transition ends to d3
  6.1101 +*/
  6.1102 +d3.selection.prototype.watchTransition = function(renderWatch){
  6.1103 +    var args = [this].concat([].slice.call(arguments, 1));
  6.1104 +    return renderWatch.transition.apply(renderWatch, args);
  6.1105 +};
  6.1106 +
  6.1107 +
  6.1108 +/*
  6.1109 +Helper object to watch when d3 has rendered something
  6.1110 +*/
  6.1111 +nv.utils.renderWatch = function(dispatch, duration) {
  6.1112 +    if (!(this instanceof nv.utils.renderWatch)) {
  6.1113 +        return new nv.utils.renderWatch(dispatch, duration);
  6.1114 +    }
  6.1115 +
  6.1116 +    var _duration = duration !== undefined ? duration : 250;
  6.1117 +    var renderStack = [];
  6.1118 +    var self = this;
  6.1119 +
  6.1120 +    this.models = function(models) {
  6.1121 +        models = [].slice.call(arguments, 0);
  6.1122 +        models.forEach(function(model){
  6.1123 +            model.__rendered = false;
  6.1124 +            (function(m){
  6.1125 +                m.dispatch.on('renderEnd', function(arg){
  6.1126 +                    m.__rendered = true;
  6.1127 +                    self.renderEnd('model');
  6.1128 +                });
  6.1129 +            })(model);
  6.1130 +
  6.1131 +            if (renderStack.indexOf(model) < 0) {
  6.1132 +                renderStack.push(model);
  6.1133 +            }
  6.1134 +        });
  6.1135 +    return this;
  6.1136 +    };
  6.1137 +
  6.1138 +    this.reset = function(duration) {
  6.1139 +        if (duration !== undefined) {
  6.1140 +            _duration = duration;
  6.1141 +        }
  6.1142 +        renderStack = [];
  6.1143 +    };
  6.1144 +
  6.1145 +    this.transition = function(selection, args, duration) {
  6.1146 +        args = arguments.length > 1 ? [].slice.call(arguments, 1) : [];
  6.1147 +
  6.1148 +        if (args.length > 1) {
  6.1149 +            duration = args.pop();
  6.1150 +        } else {
  6.1151 +            duration = _duration !== undefined ? _duration : 250;
  6.1152 +        }
  6.1153 +        selection.__rendered = false;
  6.1154 +
  6.1155 +        if (renderStack.indexOf(selection) < 0) {
  6.1156 +            renderStack.push(selection);
  6.1157 +        }
  6.1158 +
  6.1159 +        if (duration === 0) {
  6.1160 +            selection.__rendered = true;
  6.1161 +            selection.delay = function() { return this; };
  6.1162 +            selection.duration = function() { return this; };
  6.1163 +            return selection;
  6.1164 +        } else {
  6.1165 +            if (selection.length === 0) {
  6.1166 +                selection.__rendered = true;
  6.1167 +            } else if (selection.every( function(d){ return !d.length; } )) {
  6.1168 +                selection.__rendered = true;
  6.1169 +            } else {
  6.1170 +                selection.__rendered = false;
  6.1171 +            }
  6.1172 +
  6.1173 +            var n = 0;
  6.1174 +            return selection
  6.1175 +                .transition()
  6.1176 +                .duration(duration)
  6.1177 +                .each(function(){ ++n; })
  6.1178 +                .each('end', function(d, i) {
  6.1179 +                    if (--n === 0) {
  6.1180 +                        selection.__rendered = true;
  6.1181 +                        self.renderEnd.apply(this, args);
  6.1182 +                    }
  6.1183 +                });
  6.1184 +        }
  6.1185 +    };
  6.1186 +
  6.1187 +    this.renderEnd = function() {
  6.1188 +        if (renderStack.every( function(d){ return d.__rendered; } )) {
  6.1189 +            renderStack.forEach( function(d){ d.__rendered = false; });
  6.1190 +            dispatch.renderEnd.apply(this, arguments);
  6.1191 +        }
  6.1192 +    }
  6.1193 +
  6.1194 +};
  6.1195 +
  6.1196 +
  6.1197 +/*
  6.1198 +Takes multiple objects and combines them into the first one (dst)
  6.1199 +example:  nv.utils.deepExtend({a: 1}, {a: 2, b: 3}, {c: 4});
  6.1200 +gives:  {a: 2, b: 3, c: 4}
  6.1201 +*/
  6.1202 +nv.utils.deepExtend = function(dst){
  6.1203 +    var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : [];
  6.1204 +    sources.forEach(function(source) {
  6.1205 +        for (var key in source) {
  6.1206 +            var isArray = dst[key] instanceof Array;
  6.1207 +            var isObject = typeof dst[key] === 'object';
  6.1208 +            var srcObj = typeof source[key] === 'object';
  6.1209 +
  6.1210 +            if (isObject && !isArray && srcObj) {
  6.1211 +                nv.utils.deepExtend(dst[key], source[key]);
  6.1212 +            } else {
  6.1213 +                dst[key] = source[key];
  6.1214 +            }
  6.1215 +        }
  6.1216 +    });
  6.1217 +};
  6.1218 +
  6.1219 +
  6.1220 +/*
  6.1221 +state utility object, used to track d3 states in the models
  6.1222 +*/
  6.1223 +nv.utils.state = function(){
  6.1224 +    if (!(this instanceof nv.utils.state)) {
  6.1225 +        return new nv.utils.state();
  6.1226 +    }
  6.1227 +    var state = {};
  6.1228 +    var _self = this;
  6.1229 +    var _setState = function(){};
  6.1230 +    var _getState = function(){ return {}; };
  6.1231 +    var init = null;
  6.1232 +    var changed = null;
  6.1233 +
  6.1234 +    this.dispatch = d3.dispatch('change', 'set');
  6.1235 +
  6.1236 +    this.dispatch.on('set', function(state){
  6.1237 +        _setState(state, true);
  6.1238 +    });
  6.1239 +
  6.1240 +    this.getter = function(fn){
  6.1241 +        _getState = fn;
  6.1242 +        return this;
  6.1243 +    };
  6.1244 +
  6.1245 +    this.setter = function(fn, callback) {
  6.1246 +        if (!callback) {
  6.1247 +            callback = function(){};
  6.1248 +        }
  6.1249 +        _setState = function(state, update){
  6.1250 +            fn(state);
  6.1251 +            if (update) {
  6.1252 +                callback();
  6.1253 +            }
  6.1254 +        };
  6.1255 +        return this;
  6.1256 +    };
  6.1257 +
  6.1258 +    this.init = function(state){
  6.1259 +        init = init || {};
  6.1260 +        nv.utils.deepExtend(init, state);
  6.1261 +    };
  6.1262 +
  6.1263 +    var _set = function(){
  6.1264 +        var settings = _getState();
  6.1265 +
  6.1266 +        if (JSON.stringify(settings) === JSON.stringify(state)) {
  6.1267 +            return false;
  6.1268 +        }
  6.1269 +
  6.1270 +        for (var key in settings) {
  6.1271 +            if (state[key] === undefined) {
  6.1272 +                state[key] = {};
  6.1273 +            }
  6.1274 +            state[key] = settings[key];
  6.1275 +            changed = true;
  6.1276 +        }
  6.1277 +        return true;
  6.1278 +    };
  6.1279 +
  6.1280 +    this.update = function(){
  6.1281 +        if (init) {
  6.1282 +            _setState(init, false);
  6.1283 +            init = null;
  6.1284 +        }
  6.1285 +        if (_set.call(this)) {
  6.1286 +            this.dispatch.change(state);
  6.1287 +        }
  6.1288 +    };
  6.1289 +
  6.1290 +};
  6.1291 +
  6.1292 +
  6.1293 +/*
  6.1294 +Snippet of code you can insert into each nv.models.* to give you the ability to
  6.1295 +do things like:
  6.1296 +chart.options({
  6.1297 +  showXAxis: true,
  6.1298 +  tooltips: true
  6.1299 +});
  6.1300 +
  6.1301 +To enable in the chart:
  6.1302 +chart.options = nv.utils.optionsFunc.bind(chart);
  6.1303 +*/
  6.1304 +nv.utils.optionsFunc = function(args) {
  6.1305 +    if (args) {
  6.1306 +        d3.map(args).forEach((function(key,value) {
  6.1307 +            if (typeof this[key] === "function") {
  6.1308 +                this[key](value);
  6.1309 +            }
  6.1310 +        }).bind(this));
  6.1311 +    }
  6.1312 +    return this;
  6.1313 +};
  6.1314 +
  6.1315 +
  6.1316 +/*
  6.1317 +numTicks:  requested number of ticks
  6.1318 +data:  the chart data
  6.1319 +
  6.1320 +returns the number of ticks to actually use on X axis, based on chart data
  6.1321 +to avoid duplicate ticks with the same value
  6.1322 +*/
  6.1323 +nv.utils.calcTicksX = function(numTicks, data) {
  6.1324 +    // find max number of values from all data streams
  6.1325 +    var numValues = 1;
  6.1326 +    var i = 0;
  6.1327 +    for (i; i < data.length; i += 1) {
  6.1328 +        var stream_len = data[i] && data[i].values ? data[i].values.length : 0;
  6.1329 +        numValues = stream_len > numValues ? stream_len : numValues;
  6.1330 +    }
  6.1331 +    nv.log("Requested number of ticks: ", numTicks);
  6.1332 +    nv.log("Calculated max values to be: ", numValues);
  6.1333 +    // make sure we don't have more ticks than values to avoid duplicates
  6.1334 +    numTicks = numTicks > numValues ? numTicks = numValues - 1 : numTicks;
  6.1335 +    // make sure we have at least one tick
  6.1336 +    numTicks = numTicks < 1 ? 1 : numTicks;
  6.1337 +    // make sure it's an integer
  6.1338 +    numTicks = Math.floor(numTicks);
  6.1339 +    nv.log("Calculating tick count as: ", numTicks);
  6.1340 +    return numTicks;
  6.1341 +};
  6.1342 +
  6.1343 +
  6.1344 +/*
  6.1345 +returns number of ticks to actually use on Y axis, based on chart data
  6.1346 +*/
  6.1347 +nv.utils.calcTicksY = function(numTicks, data) {
  6.1348 +    // currently uses the same logic but we can adjust here if needed later
  6.1349 +    return nv.utils.calcTicksX(numTicks, data);
  6.1350 +};
  6.1351 +
  6.1352 +
  6.1353 +/*
  6.1354 +Add a particular option from an options object onto chart
  6.1355 +Options exposed on a chart are a getter/setter function that returns chart
  6.1356 +on set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b');
  6.1357 +
  6.1358 +option objects should be generated via Object.create() to provide
  6.1359 +the option of manipulating data via get/set functions.
  6.1360 +*/
  6.1361 +nv.utils.initOption = function(chart, name) {
  6.1362 +    // if it's a call option, just call it directly, otherwise do get/set
  6.1363 +    if (chart._calls && chart._calls[name]) {
  6.1364 +        chart[name] = chart._calls[name];
  6.1365 +    } else {
  6.1366 +        chart[name] = function (_) {
  6.1367 +            if (!arguments.length) return chart._options[name];
  6.1368 +            chart._overrides[name] = true;
  6.1369 +            chart._options[name] = _;
  6.1370 +            return chart;
  6.1371 +        };
  6.1372 +        // calling the option as _option will ignore if set by option already
  6.1373 +        // so nvd3 can set options internally but the stop if set manually
  6.1374 +        chart['_' + name] = function(_) {
  6.1375 +            if (!arguments.length) return chart._options[name];
  6.1376 +            if (!chart._overrides[name]) {
  6.1377 +                chart._options[name] = _;
  6.1378 +            }
  6.1379 +            return chart;
  6.1380 +        }
  6.1381 +    }
  6.1382 +};
  6.1383 +
  6.1384 +
  6.1385 +/*
  6.1386 +Add all options in an options object to the chart
  6.1387 +*/
  6.1388 +nv.utils.initOptions = function(chart) {
  6.1389 +    chart._overrides = chart._overrides || {};
  6.1390 +    var ops = Object.getOwnPropertyNames(chart._options || {});
  6.1391 +    var calls = Object.getOwnPropertyNames(chart._calls || {});
  6.1392 +    ops = ops.concat(calls);
  6.1393 +    for (var i in ops) {
  6.1394 +        nv.utils.initOption(chart, ops[i]);
  6.1395 +    }
  6.1396 +};
  6.1397 +
  6.1398 +
  6.1399 +/*
  6.1400 +Inherit options from a D3 object
  6.1401 +d3.rebind makes calling the function on target actually call it on source
  6.1402 +Also use _d3options so we can track what we inherit for documentation and chained inheritance
  6.1403 +*/
  6.1404 +nv.utils.inheritOptionsD3 = function(target, d3_source, oplist) {
  6.1405 +    target._d3options = oplist.concat(target._d3options || []);
  6.1406 +    oplist.unshift(d3_source);
  6.1407 +    oplist.unshift(target);
  6.1408 +    d3.rebind.apply(this, oplist);
  6.1409 +};
  6.1410 +
  6.1411 +
  6.1412 +/*
  6.1413 +Remove duplicates from an array
  6.1414 +*/
  6.1415 +nv.utils.arrayUnique = function(a) {
  6.1416 +    return a.sort().filter(function(item, pos) {
  6.1417 +        return !pos || item != a[pos - 1];
  6.1418 +    });
  6.1419 +};
  6.1420 +
  6.1421 +
  6.1422 +/*
  6.1423 +Keeps a list of custom symbols to draw from in addition to d3.svg.symbol
  6.1424 +Necessary since d3 doesn't let you extend its list -_-
  6.1425 +Add new symbols by doing nv.utils.symbols.set('name', function(size){...});
  6.1426 +*/
  6.1427 +nv.utils.symbolMap = d3.map();
  6.1428 +
  6.1429 +
  6.1430 +/*
  6.1431 +Replaces d3.svg.symbol so that we can look both there and our own map
  6.1432 + */
  6.1433 +nv.utils.symbol = function() {
  6.1434 +    var type,
  6.1435 +        size = 64;
  6.1436 +    function symbol(d,i) {
  6.1437 +        var t = type.call(this,d,i);
  6.1438 +        var s = size.call(this,d,i);
  6.1439 +        if (d3.svg.symbolTypes.indexOf(t) !== -1) {
  6.1440 +            return d3.svg.symbol().type(t).size(s)();
  6.1441 +        } else {
  6.1442 +            return nv.utils.symbolMap.get(t)(s);
  6.1443 +        }
  6.1444 +    }
  6.1445 +    symbol.type = function(_) {
  6.1446 +        if (!arguments.length) return type;
  6.1447 +        type = d3.functor(_);
  6.1448 +        return symbol;
  6.1449 +    };
  6.1450 +    symbol.size = function(_) {
  6.1451 +        if (!arguments.length) return size;
  6.1452 +        size = d3.functor(_);
  6.1453 +        return symbol;
  6.1454 +    };
  6.1455 +    return symbol;
  6.1456 +};
  6.1457 +
  6.1458 +
  6.1459 +/*
  6.1460 +Inherit option getter/setter functions from source to target
  6.1461 +d3.rebind makes calling the function on target actually call it on source
  6.1462 +Also track via _inherited and _d3options so we can track what we inherit
  6.1463 +for documentation generation purposes and chained inheritance
  6.1464 +*/
  6.1465 +nv.utils.inheritOptions = function(target, source) {
  6.1466 +    // inherit all the things
  6.1467 +    var ops = Object.getOwnPropertyNames(source._options || {});
  6.1468 +    var calls = Object.getOwnPropertyNames(source._calls || {});
  6.1469 +    var inherited = source._inherited || [];
  6.1470 +    var d3ops = source._d3options || [];
  6.1471 +    var args = ops.concat(calls).concat(inherited).concat(d3ops);
  6.1472 +    args.unshift(source);
  6.1473 +    args.unshift(target);
  6.1474 +    d3.rebind.apply(this, args);
  6.1475 +    // pass along the lists to keep track of them, don't allow duplicates
  6.1476 +    target._inherited = nv.utils.arrayUnique(ops.concat(calls).concat(inherited).concat(ops).concat(target._inherited || []));
  6.1477 +    target._d3options = nv.utils.arrayUnique(d3ops.concat(target._d3options || []));
  6.1478 +};
  6.1479 +
  6.1480 +
  6.1481 +/*
  6.1482 +Runs common initialize code on the svg before the chart builds
  6.1483 +*/
  6.1484 +nv.utils.initSVG = function(svg) {
  6.1485 +    svg.classed({'nvd3-svg':true});
  6.1486 +};
  6.1487 +
  6.1488 +
  6.1489 +/*
  6.1490 +Sanitize and provide default for the container height.
  6.1491 +*/
  6.1492 +nv.utils.sanitizeHeight = function(height, container) {
  6.1493 +    return (height || parseInt(container.style('height'), 10) || 400);
  6.1494 +};
  6.1495 +
  6.1496 +
  6.1497 +/*
  6.1498 +Sanitize and provide default for the container width.
  6.1499 +*/
  6.1500 +nv.utils.sanitizeWidth = function(width, container) {
  6.1501 +    return (width || parseInt(container.style('width'), 10) || 960);
  6.1502 +};
  6.1503 +
  6.1504 +
  6.1505 +/*
  6.1506 +Calculate the available height for a chart.
  6.1507 +*/
  6.1508 +nv.utils.availableHeight = function(height, container, margin) {
  6.1509 +    return nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom;
  6.1510 +};
  6.1511 +
  6.1512 +/*
  6.1513 +Calculate the available width for a chart.
  6.1514 +*/
  6.1515 +nv.utils.availableWidth = function(width, container, margin) {
  6.1516 +    return nv.utils.sanitizeWidth(width, container) - margin.left - margin.right;
  6.1517 +};
  6.1518 +
  6.1519 +/*
  6.1520 +Clear any rendered chart components and display a chart's 'noData' message
  6.1521 +*/
  6.1522 +nv.utils.noData = function(chart, container) {
  6.1523 +    var opt = chart.options(),
  6.1524 +        margin = opt.margin(),
  6.1525 +        noData = opt.noData(),
  6.1526 +        data = (noData == null) ? ["No Data Available."] : [noData],
  6.1527 +        height = nv.utils.availableHeight(opt.height(), container, margin),
  6.1528 +        width = nv.utils.availableWidth(opt.width(), container, margin),
  6.1529 +        x = margin.left + width/2,
  6.1530 +        y = margin.top + height/2;
  6.1531 +
  6.1532 +    //Remove any previously created chart components
  6.1533 +    container.selectAll('g').remove();
  6.1534 +
  6.1535 +    var noDataText = container.selectAll('.nv-noData').data(data);
  6.1536 +
  6.1537 +    noDataText.enter().append('text')
  6.1538 +        .attr('class', 'nvd3 nv-noData')
  6.1539 +        .attr('dy', '-.7em')
  6.1540 +        .style('text-anchor', 'middle');
  6.1541 +
  6.1542 +    noDataText
  6.1543 +        .attr('x', x)
  6.1544 +        .attr('y', y)
  6.1545 +        .text(function(t){ return t; });
  6.1546 +};
  6.1547 +
  6.1548 +nv.models.axis = function() {
  6.1549 +    "use strict";
  6.1550 +
  6.1551 +    //============================================================
  6.1552 +    // Public Variables with Default Settings
  6.1553 +    //------------------------------------------------------------
  6.1554 +
  6.1555 +    var axis = d3.svg.axis();
  6.1556 +    var scale = d3.scale.linear();
  6.1557 +
  6.1558 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.1559 +        , width = 75 //only used for tickLabel currently
  6.1560 +        , height = 60 //only used for tickLabel currently
  6.1561 +        , axisLabelText = null
  6.1562 +        , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes
  6.1563 +        , rotateLabels = 0
  6.1564 +        , rotateYLabel = true
  6.1565 +        , staggerLabels = false
  6.1566 +        , isOrdinal = false
  6.1567 +        , ticks = null
  6.1568 +        , axisLabelDistance = 0
  6.1569 +        , duration = 250
  6.1570 +        , dispatch = d3.dispatch('renderEnd')
  6.1571 +        ;
  6.1572 +    axis
  6.1573 +        .scale(scale)
  6.1574 +        .orient('bottom')
  6.1575 +        .tickFormat(function(d) { return d })
  6.1576 +    ;
  6.1577 +
  6.1578 +    //============================================================
  6.1579 +    // Private Variables
  6.1580 +    //------------------------------------------------------------
  6.1581 +
  6.1582 +    var scale0;
  6.1583 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.1584 +
  6.1585 +    function chart(selection) {
  6.1586 +        renderWatch.reset();
  6.1587 +        selection.each(function(data) {
  6.1588 +            var container = d3.select(this);
  6.1589 +            nv.utils.initSVG(container);
  6.1590 +
  6.1591 +            // Setup containers and skeleton of chart
  6.1592 +            var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]);
  6.1593 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis');
  6.1594 +            var gEnter = wrapEnter.append('g');
  6.1595 +            var g = wrap.select('g');
  6.1596 +
  6.1597 +            if (ticks !== null)
  6.1598 +                axis.ticks(ticks);
  6.1599 +            else if (axis.orient() == 'top' || axis.orient() == 'bottom')
  6.1600 +                axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);
  6.1601 +
  6.1602 +            //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component
  6.1603 +            g.watchTransition(renderWatch, 'axis').call(axis);
  6.1604 +
  6.1605 +            scale0 = scale0 || axis.scale();
  6.1606 +
  6.1607 +            var fmt = axis.tickFormat();
  6.1608 +            if (fmt == null) {
  6.1609 +                fmt = scale0.tickFormat();
  6.1610 +            }
  6.1611 +
  6.1612 +            var axisLabel = g.selectAll('text.nv-axislabel')
  6.1613 +                .data([axisLabelText || null]);
  6.1614 +            axisLabel.exit().remove();
  6.1615 +
  6.1616 +            var xLabelMargin;
  6.1617 +            var axisMaxMin;
  6.1618 +            var w;
  6.1619 +            switch (axis.orient()) {
  6.1620 +                case 'top':
  6.1621 +                    axisLabel.enter().append('text').attr('class', 'nv-axislabel');
  6.1622 +                    if (scale.range().length < 2) {
  6.1623 +                        w = 0;
  6.1624 +                    } else if (scale.range().length === 2) {
  6.1625 +                        w = scale.range()[1];
  6.1626 +                    } else {
  6.1627 +                        w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);
  6.1628 +                    }
  6.1629 +                    axisLabel
  6.1630 +                        .attr('text-anchor', 'middle')
  6.1631 +                        .attr('y', 0)
  6.1632 +                        .attr('x', w/2);
  6.1633 +                    if (showMaxMin) {
  6.1634 +                        axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
  6.1635 +                            .data(scale.domain());
  6.1636 +                        axisMaxMin.enter().append('g').attr('class',function(d,i){
  6.1637 +                                return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')
  6.1638 +                        }).append('text');
  6.1639 +                        axisMaxMin.exit().remove();
  6.1640 +                        axisMaxMin
  6.1641 +                            .attr('transform', function(d,i) {
  6.1642 +                                return 'translate(' + nv.utils.NaNtoZero(scale(d)) + ',0)'
  6.1643 +                            })
  6.1644 +                            .select('text')
  6.1645 +                            .attr('dy', '-0.5em')
  6.1646 +                            .attr('y', -axis.tickPadding())
  6.1647 +                            .attr('text-anchor', 'middle')
  6.1648 +                            .text(function(d,i) {
  6.1649 +                                var v = fmt(d);
  6.1650 +                                return ('' + v).match('NaN') ? '' : v;
  6.1651 +                            });
  6.1652 +                        axisMaxMin.watchTransition(renderWatch, 'min-max top')
  6.1653 +                            .attr('transform', function(d,i) {
  6.1654 +                                return 'translate(' + nv.utils.NaNtoZero(scale.range()[i]) + ',0)'
  6.1655 +                            });
  6.1656 +                    }
  6.1657 +                    break;
  6.1658 +                case 'bottom':
  6.1659 +                    xLabelMargin = axisLabelDistance + 36;
  6.1660 +                    var maxTextWidth = 30;
  6.1661 +                    var textHeight = 0;
  6.1662 +                    var xTicks = g.selectAll('g').select("text");
  6.1663 +                    var rotateLabelsRule = '';
  6.1664 +                    if (rotateLabels%360) {
  6.1665 +                        //Calculate the longest xTick width
  6.1666 +                        xTicks.each(function(d,i){
  6.1667 +                            var box = this.getBoundingClientRect();
  6.1668 +                            var width = box.width;
  6.1669 +                            textHeight = box.height;
  6.1670 +                            if(width > maxTextWidth) maxTextWidth = width;
  6.1671 +                        });
  6.1672 +                        rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')';
  6.1673 +                        //Convert to radians before calculating sin. Add 30 to margin for healthy padding.
  6.1674 +                        var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180));
  6.1675 +                        xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30;
  6.1676 +                        //Rotate all xTicks
  6.1677 +                        xTicks
  6.1678 +                            .attr('transform', rotateLabelsRule)
  6.1679 +                            .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
  6.1680 +                    }
  6.1681 +                    axisLabel.enter().append('text').attr('class', 'nv-axislabel');
  6.1682 +                    if (scale.range().length < 2) {
  6.1683 +                        w = 0;
  6.1684 +                    } else if (scale.range().length === 2) {
  6.1685 +                        w = scale.range()[1];
  6.1686 +                    } else {
  6.1687 +                        w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);
  6.1688 +                    }
  6.1689 +                    axisLabel
  6.1690 +                        .attr('text-anchor', 'middle')
  6.1691 +                        .attr('y', xLabelMargin)
  6.1692 +                        .attr('x', w/2);
  6.1693 +                    if (showMaxMin) {
  6.1694 +                        //if (showMaxMin && !isOrdinal) {
  6.1695 +                        axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
  6.1696 +                            //.data(scale.domain())
  6.1697 +                            .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);
  6.1698 +                        axisMaxMin.enter().append('g').attr('class',function(d,i){
  6.1699 +                                return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')
  6.1700 +                        }).append('text');
  6.1701 +                        axisMaxMin.exit().remove();
  6.1702 +                        axisMaxMin
  6.1703 +                            .attr('transform', function(d,i) {
  6.1704 +                                return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'
  6.1705 +                            })
  6.1706 +                            .select('text')
  6.1707 +                            .attr('dy', '.71em')
  6.1708 +                            .attr('y', axis.tickPadding())
  6.1709 +                            .attr('transform', rotateLabelsRule)
  6.1710 +                            .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')
  6.1711 +                            .text(function(d,i) {
  6.1712 +                                var v = fmt(d);
  6.1713 +                                return ('' + v).match('NaN') ? '' : v;
  6.1714 +                            });
  6.1715 +                        axisMaxMin.watchTransition(renderWatch, 'min-max bottom')
  6.1716 +                            .attr('transform', function(d,i) {
  6.1717 +                                return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'
  6.1718 +                            });
  6.1719 +                    }
  6.1720 +                    if (staggerLabels)
  6.1721 +                        xTicks
  6.1722 +                            .attr('transform', function(d,i) {
  6.1723 +                                return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')'
  6.1724 +                            });
  6.1725 +
  6.1726 +                    break;
  6.1727 +                case 'right':
  6.1728 +                    axisLabel.enter().append('text').attr('class', 'nv-axislabel');
  6.1729 +                    axisLabel
  6.1730 +                        .style('text-anchor', rotateYLabel ? 'middle' : 'begin')
  6.1731 +                        .attr('transform', rotateYLabel ? 'rotate(90)' : '')
  6.1732 +                        .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
  6.1733 +                        .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding());
  6.1734 +                    if (showMaxMin) {
  6.1735 +                        axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
  6.1736 +                            .data(scale.domain());
  6.1737 +                       	axisMaxMin.enter().append('g').attr('class',function(d,i){
  6.1738 +                                return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')
  6.1739 +                        }).append('text')
  6.1740 +                            .style('opacity', 0);
  6.1741 +                        axisMaxMin.exit().remove();
  6.1742 +                        axisMaxMin
  6.1743 +                            .attr('transform', function(d,i) {
  6.1744 +                                return 'translate(0,' + nv.utils.NaNtoZero(scale(d)) + ')'
  6.1745 +                            })
  6.1746 +                            .select('text')
  6.1747 +                            .attr('dy', '.32em')
  6.1748 +                            .attr('y', 0)
  6.1749 +                            .attr('x', axis.tickPadding())
  6.1750 +                            .style('text-anchor', 'start')
  6.1751 +                            .text(function(d, i) {
  6.1752 +                                var v = fmt(d);
  6.1753 +                                return ('' + v).match('NaN') ? '' : v;
  6.1754 +                            });
  6.1755 +                        axisMaxMin.watchTransition(renderWatch, 'min-max right')
  6.1756 +                            .attr('transform', function(d,i) {
  6.1757 +                                return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'
  6.1758 +                            })
  6.1759 +                            .select('text')
  6.1760 +                            .style('opacity', 1);
  6.1761 +                    }
  6.1762 +                    break;
  6.1763 +                case 'left':
  6.1764 +                    /*
  6.1765 +                     //For dynamically placing the label. Can be used with dynamically-sized chart axis margins
  6.1766 +                     var yTicks = g.selectAll('g').select("text");
  6.1767 +                     yTicks.each(function(d,i){
  6.1768 +                     var labelPadding = this.getBoundingClientRect().width + axis.tickPadding() + 16;
  6.1769 +                     if(labelPadding > width) width = labelPadding;
  6.1770 +                     });
  6.1771 +                     */
  6.1772 +                    axisLabel.enter().append('text').attr('class', 'nv-axislabel');
  6.1773 +                    axisLabel
  6.1774 +                        .style('text-anchor', rotateYLabel ? 'middle' : 'end')
  6.1775 +                        .attr('transform', rotateYLabel ? 'rotate(-90)' : '')
  6.1776 +                        .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10)
  6.1777 +                        .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding());
  6.1778 +                    if (showMaxMin) {
  6.1779 +                        axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
  6.1780 +                            .data(scale.domain());
  6.1781 +                        axisMaxMin.enter().append('g').attr('class',function(d,i){
  6.1782 +                                return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')
  6.1783 +                        }).append('text')
  6.1784 +                            .style('opacity', 0);
  6.1785 +                        axisMaxMin.exit().remove();
  6.1786 +                        axisMaxMin
  6.1787 +                            .attr('transform', function(d,i) {
  6.1788 +                                return 'translate(0,' + nv.utils.NaNtoZero(scale0(d)) + ')'
  6.1789 +                            })
  6.1790 +                            .select('text')
  6.1791 +                            .attr('dy', '.32em')
  6.1792 +                            .attr('y', 0)
  6.1793 +                            .attr('x', -axis.tickPadding())
  6.1794 +                            .attr('text-anchor', 'end')
  6.1795 +                            .text(function(d,i) {
  6.1796 +                                var v = fmt(d);
  6.1797 +                                return ('' + v).match('NaN') ? '' : v;
  6.1798 +                            });
  6.1799 +                        axisMaxMin.watchTransition(renderWatch, 'min-max right')
  6.1800 +                            .attr('transform', function(d,i) {
  6.1801 +                                return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'
  6.1802 +                            })
  6.1803 +                            .select('text')
  6.1804 +                            .style('opacity', 1);
  6.1805 +                    }
  6.1806 +                    break;
  6.1807 +            }
  6.1808 +            axisLabel.text(function(d) { return d });
  6.1809 +
  6.1810 +            if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {
  6.1811 +                //check if max and min overlap other values, if so, hide the values that overlap
  6.1812 +                g.selectAll('g') // the g's wrapping each tick
  6.1813 +                    .each(function(d,i) {
  6.1814 +                        d3.select(this).select('text').attr('opacity', 1);
  6.1815 +                        if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!
  6.1816 +                            if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
  6.1817 +                                d3.select(this).attr('opacity', 0);
  6.1818 +
  6.1819 +                            d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!
  6.1820 +                        }
  6.1821 +                    });
  6.1822 +
  6.1823 +                //if Max and Min = 0 only show min, Issue #281
  6.1824 +                if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0) {
  6.1825 +                    wrap.selectAll('g.nv-axisMaxMin').style('opacity', function (d, i) {
  6.1826 +                        return !i ? 1 : 0
  6.1827 +                    });
  6.1828 +                }
  6.1829 +            }
  6.1830 +
  6.1831 +            if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {
  6.1832 +                var maxMinRange = [];
  6.1833 +                wrap.selectAll('g.nv-axisMaxMin')
  6.1834 +                    .each(function(d,i) {
  6.1835 +                        try {
  6.1836 +                            if (i) // i== 1, max position
  6.1837 +                                maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4);  //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
  6.1838 +                            else // i==0, min position
  6.1839 +                                maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4)
  6.1840 +                        }catch (err) {
  6.1841 +                            if (i) // i== 1, max position
  6.1842 +                                maxMinRange.push(scale(d) - 4);  //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
  6.1843 +                            else // i==0, min position
  6.1844 +                                maxMinRange.push(scale(d) + 4);
  6.1845 +                        }
  6.1846 +                    });
  6.1847 +                // the g's wrapping each tick
  6.1848 +                g.selectAll('g').each(function(d, i) {
  6.1849 +                    if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) {
  6.1850 +                        if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
  6.1851 +                            d3.select(this).remove();
  6.1852 +                        else
  6.1853 +                            d3.select(this).select('text').remove(); // Don't remove the ZERO line!!
  6.1854 +                    }
  6.1855 +                });
  6.1856 +            }
  6.1857 +
  6.1858 +            //Highlight zero tick line
  6.1859 +            g.selectAll('.tick')
  6.1860 +                .filter(function (d) {
  6.1861 +                    /*
  6.1862 +                    The filter needs to return only ticks at or near zero.
  6.1863 +                    Numbers like 0.00001 need to count as zero as well,
  6.1864 +                    and the arithmetic trick below solves that.
  6.1865 +                    */
  6.1866 +                    return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined)
  6.1867 +                }) 
  6.1868 +                .classed('zero', true);
  6.1869 +            
  6.1870 +            //store old scales for use in transitions on update
  6.1871 +            scale0 = scale.copy();
  6.1872 +
  6.1873 +        });
  6.1874 +
  6.1875 +        renderWatch.renderEnd('axis immediate');
  6.1876 +        return chart;
  6.1877 +    }
  6.1878 +
  6.1879 +    //============================================================
  6.1880 +    // Expose Public Variables
  6.1881 +    //------------------------------------------------------------
  6.1882 +
  6.1883 +    // expose chart's sub-components
  6.1884 +    chart.axis = axis;
  6.1885 +    chart.dispatch = dispatch;
  6.1886 +
  6.1887 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.1888 +    chart._options = Object.create({}, {
  6.1889 +        // simple options, just get/set the necessary values
  6.1890 +        axisLabelDistance: {get: function(){return axisLabelDistance;}, set: function(_){axisLabelDistance=_;}},
  6.1891 +        staggerLabels:     {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
  6.1892 +        rotateLabels:      {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},
  6.1893 +        rotateYLabel:      {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}},
  6.1894 +        showMaxMin:        {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}},
  6.1895 +        axisLabel:         {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}},
  6.1896 +        height:            {get: function(){return height;}, set: function(_){height=_;}},
  6.1897 +        ticks:             {get: function(){return ticks;}, set: function(_){ticks=_;}},
  6.1898 +        width:             {get: function(){return width;}, set: function(_){width=_;}},
  6.1899 +
  6.1900 +        // options that require extra logic in the setter
  6.1901 +        margin: {get: function(){return margin;}, set: function(_){
  6.1902 +            margin.top    = _.top !== undefined    ? _.top    : margin.top;
  6.1903 +            margin.right  = _.right !== undefined  ? _.right  : margin.right;
  6.1904 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.1905 +            margin.left   = _.left !== undefined   ? _.left   : margin.left;
  6.1906 +        }},
  6.1907 +        duration: {get: function(){return duration;}, set: function(_){
  6.1908 +            duration=_;
  6.1909 +            renderWatch.reset(duration);
  6.1910 +        }},
  6.1911 +        scale: {get: function(){return scale;}, set: function(_){
  6.1912 +            scale = _;
  6.1913 +            axis.scale(scale);
  6.1914 +            isOrdinal = typeof scale.rangeBands === 'function';
  6.1915 +            nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);
  6.1916 +        }}
  6.1917 +    });
  6.1918 +
  6.1919 +    nv.utils.initOptions(chart);
  6.1920 +    nv.utils.inheritOptionsD3(chart, axis, ['orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat']);
  6.1921 +    nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);
  6.1922 +
  6.1923 +    return chart;
  6.1924 +};
  6.1925 +nv.models.boxPlot = function() {
  6.1926 +    "use strict";
  6.1927 +
  6.1928 +    //============================================================
  6.1929 +    // Public Variables with Default Settings
  6.1930 +    //------------------------------------------------------------
  6.1931 +
  6.1932 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.1933 +        , width = 960
  6.1934 +        , height = 500
  6.1935 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.1936 +        , x = d3.scale.ordinal()
  6.1937 +        , y = d3.scale.linear()
  6.1938 +        , getX = function(d) { return d.x }
  6.1939 +        , getY = function(d) { return d.y }
  6.1940 +        , color = nv.utils.defaultColor()
  6.1941 +        , container = null
  6.1942 +        , xDomain
  6.1943 +        , yDomain
  6.1944 +        , xRange
  6.1945 +        , yRange
  6.1946 +        , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
  6.1947 +        , duration = 250
  6.1948 +        , maxBoxWidth = null
  6.1949 +        ;
  6.1950 +
  6.1951 +    //============================================================
  6.1952 +    // Private Variables
  6.1953 +    //------------------------------------------------------------
  6.1954 +
  6.1955 +    var x0, y0;
  6.1956 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.1957 +
  6.1958 +    function chart(selection) {
  6.1959 +        renderWatch.reset();
  6.1960 +        selection.each(function(data) {
  6.1961 +            var availableWidth = width - margin.left - margin.right,
  6.1962 +                availableHeight = height - margin.top - margin.bottom;
  6.1963 +
  6.1964 +            container = d3.select(this);
  6.1965 +            nv.utils.initSVG(container);
  6.1966 +
  6.1967 +            // Setup Scales
  6.1968 +            x   .domain(xDomain || data.map(function(d,i) { return getX(d,i); }))
  6.1969 +                .rangeBands(xRange || [0, availableWidth], .1);
  6.1970 +
  6.1971 +            // if we know yDomain, no need to calculate
  6.1972 +            var yData = []
  6.1973 +            if (!yDomain) {
  6.1974 +                // (y-range is based on quartiles, whiskers and outliers)
  6.1975 +
  6.1976 +                // lower values
  6.1977 +                var yMin = d3.min(data.map(function(d) {
  6.1978 +                    var min_arr = [];
  6.1979 +
  6.1980 +                    min_arr.push(d.values.Q1);
  6.1981 +                    if (d.values.hasOwnProperty('whisker_low') && d.values.whisker_low !== null) { min_arr.push(d.values.whisker_low); }
  6.1982 +                    if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { min_arr = min_arr.concat(d.values.outliers); }
  6.1983 +
  6.1984 +                    return d3.min(min_arr);
  6.1985 +                }));
  6.1986 +
  6.1987 +                // upper values
  6.1988 +                var yMax = d3.max(data.map(function(d) {
  6.1989 +                    var max_arr = [];
  6.1990 +
  6.1991 +                    max_arr.push(d.values.Q3);
  6.1992 +                    if (d.values.hasOwnProperty('whisker_high') && d.values.whisker_high !== null) { max_arr.push(d.values.whisker_high); }
  6.1993 +                    if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { max_arr = max_arr.concat(d.values.outliers); }
  6.1994 +
  6.1995 +                    return d3.max(max_arr);
  6.1996 +                }));
  6.1997 +
  6.1998 +                yData = [ yMin, yMax ] ;
  6.1999 +            }
  6.2000 +
  6.2001 +            y.domain(yDomain || yData);
  6.2002 +            y.range(yRange || [availableHeight, 0]);
  6.2003 +
  6.2004 +            //store old scales if they exist
  6.2005 +            x0 = x0 || x;
  6.2006 +            y0 = y0 || y.copy().range([y(0),y(0)]);
  6.2007 +
  6.2008 +            // Setup containers and skeleton of chart
  6.2009 +            var wrap = container.selectAll('g.nv-wrap').data([data]);
  6.2010 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap');
  6.2011 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.2012 +
  6.2013 +            var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d });
  6.2014 +            var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6);
  6.2015 +            boxplots
  6.2016 +                .attr('class', 'nv-boxplot')
  6.2017 +                .attr('transform', function(d,i,j) { return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; })
  6.2018 +                .classed('hover', function(d) { return d.hover });
  6.2019 +            boxplots
  6.2020 +                .watchTransition(renderWatch, 'nv-boxplot: boxplots')
  6.2021 +                .style('stroke-opacity', 1)
  6.2022 +                .style('fill-opacity', .75)
  6.2023 +                .delay(function(d,i) { return i * duration / data.length })
  6.2024 +                .attr('transform', function(d,i) {
  6.2025 +                    return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)';
  6.2026 +                });
  6.2027 +            boxplots.exit().remove();
  6.2028 +
  6.2029 +            // ----- add the SVG elements for each boxPlot -----
  6.2030 +
  6.2031 +            // conditionally append whisker lines
  6.2032 +            boxEnter.each(function(d,i) {
  6.2033 +              var box = d3.select(this);
  6.2034 +
  6.2035 +              ['low', 'high'].forEach(function(key) {
  6.2036 +                if (d.values.hasOwnProperty('whisker_' + key) && d.values['whisker_' + key] !== null) {
  6.2037 +                  box.append('line')
  6.2038 +                    .style('stroke', (d.color) ? d.color : color(d,i))
  6.2039 +                    .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key);
  6.2040 +
  6.2041 +                  box.append('line')
  6.2042 +                    .style('stroke', (d.color) ? d.color : color(d,i))
  6.2043 +                    .attr('class', 'nv-boxplot-tick nv-boxplot-' + key);
  6.2044 +                }
  6.2045 +              });
  6.2046 +            });
  6.2047 +
  6.2048 +            // outliers
  6.2049 +            // TODO: support custom colors here
  6.2050 +            var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) {
  6.2051 +                if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { return d.values.outliers; }
  6.2052 +                else { return []; }
  6.2053 +            });
  6.2054 +            outliers.enter().append('circle')
  6.2055 +                .style('fill', function(d,i,j) { return color(d,j) }).style('stroke', function(d,i,j) { return color(d,j) })
  6.2056 +                .on('mouseover', function(d,i,j) {
  6.2057 +                    d3.select(this).classed('hover', true);
  6.2058 +                    dispatch.elementMouseover({
  6.2059 +                        series: { key: d, color: color(d,j) },
  6.2060 +                        e: d3.event
  6.2061 +                    });
  6.2062 +                })
  6.2063 +                .on('mouseout', function(d,i,j) {
  6.2064 +                    d3.select(this).classed('hover', false);
  6.2065 +                    dispatch.elementMouseout({
  6.2066 +                        series: { key: d, color: color(d,j) },
  6.2067 +                        e: d3.event
  6.2068 +                    });
  6.2069 +                })
  6.2070 +                .on('mousemove', function(d,i) {
  6.2071 +                    dispatch.elementMousemove({e: d3.event});
  6.2072 +                });
  6.2073 +
  6.2074 +            outliers.attr('class', 'nv-boxplot-outlier');
  6.2075 +            outliers
  6.2076 +              .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier')
  6.2077 +                .attr('cx', x.rangeBand() * .45)
  6.2078 +                .attr('cy', function(d,i,j) { return y(d); })
  6.2079 +                .attr('r', '3');
  6.2080 +            outliers.exit().remove();
  6.2081 +
  6.2082 +            var box_width = function() { return (maxBoxWidth === null ? x.rangeBand() * .9 : Math.min(75, x.rangeBand() * .9)); };
  6.2083 +            var box_left  = function() { return x.rangeBand() * .45 - box_width()/2; };
  6.2084 +            var box_right = function() { return x.rangeBand() * .45 + box_width()/2; };
  6.2085 +
  6.2086 +            // update whisker lines and ticks
  6.2087 +            ['low', 'high'].forEach(function(key) {
  6.2088 +              var endpoint = (key === 'low') ? 'Q1' : 'Q3';
  6.2089 +
  6.2090 +              boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key)
  6.2091 +                .watchTransition(renderWatch, 'nv-boxplot: boxplots')
  6.2092 +                  .attr('x1', x.rangeBand() * .45 )
  6.2093 +                  .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); })
  6.2094 +                  .attr('x2', x.rangeBand() * .45 )
  6.2095 +                  .attr('y2', function(d,i) { return y(d.values[endpoint]); });
  6.2096 +
  6.2097 +              boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key)
  6.2098 +                .watchTransition(renderWatch, 'nv-boxplot: boxplots')
  6.2099 +                  .attr('x1', box_left )
  6.2100 +                  .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); })
  6.2101 +                  .attr('x2', box_right )
  6.2102 +                  .attr('y2', function(d,i) { return y(d.values['whisker_' + key]); });
  6.2103 +            });
  6.2104 +
  6.2105 +            ['low', 'high'].forEach(function(key) {
  6.2106 +              boxEnter.selectAll('.nv-boxplot-' + key)
  6.2107 +                .on('mouseover', function(d,i,j) {
  6.2108 +                    d3.select(this).classed('hover', true);
  6.2109 +                    dispatch.elementMouseover({
  6.2110 +                        series: { key: d.values['whisker_' + key], color: color(d,j) },
  6.2111 +                        e: d3.event
  6.2112 +                    });
  6.2113 +                })
  6.2114 +                .on('mouseout', function(d,i,j) {
  6.2115 +                    d3.select(this).classed('hover', false);
  6.2116 +                    dispatch.elementMouseout({
  6.2117 +                        series: { key: d.values['whisker_' + key], color: color(d,j) },
  6.2118 +                        e: d3.event
  6.2119 +                    });
  6.2120 +                })
  6.2121 +                .on('mousemove', function(d,i) {
  6.2122 +                    dispatch.elementMousemove({e: d3.event});
  6.2123 +                });
  6.2124 +            });
  6.2125 +
  6.2126 +            // boxes
  6.2127 +            boxEnter.append('rect')
  6.2128 +                .attr('class', 'nv-boxplot-box')
  6.2129 +                // tooltip events
  6.2130 +                .on('mouseover', function(d,i) {
  6.2131 +                    d3.select(this).classed('hover', true);
  6.2132 +                    dispatch.elementMouseover({
  6.2133 +                        key: d.label,
  6.2134 +                        value: d.label,
  6.2135 +                        series: [
  6.2136 +                            { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) },
  6.2137 +                            { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) },
  6.2138 +                            { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) }
  6.2139 +                        ],
  6.2140 +                        data: d,
  6.2141 +                        index: i,
  6.2142 +                        e: d3.event
  6.2143 +                    });
  6.2144 +                })
  6.2145 +                .on('mouseout', function(d,i) {
  6.2146 +                    d3.select(this).classed('hover', false);
  6.2147 +                    dispatch.elementMouseout({
  6.2148 +                        key: d.label,
  6.2149 +                        value: d.label,
  6.2150 +                        series: [
  6.2151 +                            { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) },
  6.2152 +                            { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) },
  6.2153 +                            { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) }
  6.2154 +                        ],
  6.2155 +                        data: d,
  6.2156 +                        index: i,
  6.2157 +                        e: d3.event
  6.2158 +                    });
  6.2159 +                })
  6.2160 +                .on('mousemove', function(d,i) {
  6.2161 +                    dispatch.elementMousemove({e: d3.event});
  6.2162 +                });
  6.2163 +
  6.2164 +            // box transitions
  6.2165 +            boxplots.select('rect.nv-boxplot-box')
  6.2166 +              .watchTransition(renderWatch, 'nv-boxplot: boxes')
  6.2167 +                .attr('y', function(d,i) { return y(d.values.Q3); })
  6.2168 +                .attr('width', box_width)
  6.2169 +                .attr('x', box_left )
  6.2170 +
  6.2171 +                .attr('height', function(d,i) { return Math.abs(y(d.values.Q3) - y(d.values.Q1)) || 1 })
  6.2172 +                .style('fill', function(d,i) { return d.color || color(d,i) })
  6.2173 +                .style('stroke', function(d,i) { return d.color || color(d,i) });
  6.2174 +
  6.2175 +            // median line
  6.2176 +            boxEnter.append('line').attr('class', 'nv-boxplot-median');
  6.2177 +
  6.2178 +            boxplots.select('line.nv-boxplot-median')
  6.2179 +              .watchTransition(renderWatch, 'nv-boxplot: boxplots line')
  6.2180 +                .attr('x1', box_left)
  6.2181 +                .attr('y1', function(d,i) { return y(d.values.Q2); })
  6.2182 +                .attr('x2', box_right)
  6.2183 +                .attr('y2', function(d,i) { return y(d.values.Q2); });
  6.2184 +
  6.2185 +            //store old scales for use in transitions on update
  6.2186 +            x0 = x.copy();
  6.2187 +            y0 = y.copy();
  6.2188 +        });
  6.2189 +
  6.2190 +        renderWatch.renderEnd('nv-boxplot immediate');
  6.2191 +        return chart;
  6.2192 +    }
  6.2193 +
  6.2194 +    //============================================================
  6.2195 +    // Expose Public Variables
  6.2196 +    //------------------------------------------------------------
  6.2197 +
  6.2198 +    chart.dispatch = dispatch;
  6.2199 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.2200 +
  6.2201 +    chart._options = Object.create({}, {
  6.2202 +        // simple options, just get/set the necessary values
  6.2203 +        width:   {get: function(){return width;}, set: function(_){width=_;}},
  6.2204 +        height:  {get: function(){return height;}, set: function(_){height=_;}},
  6.2205 +        maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}},
  6.2206 +        x:       {get: function(){return getX;}, set: function(_){getX=_;}},
  6.2207 +        y:       {get: function(){return getY;}, set: function(_){getY=_;}},
  6.2208 +        xScale:  {get: function(){return x;}, set: function(_){x=_;}},
  6.2209 +        yScale:  {get: function(){return y;}, set: function(_){y=_;}},
  6.2210 +        xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.2211 +        yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.2212 +        xRange:  {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.2213 +        yRange:  {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.2214 +        id:          {get: function(){return id;}, set: function(_){id=_;}},
  6.2215 +        // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},
  6.2216 +
  6.2217 +        // options that require extra logic in the setter
  6.2218 +        margin: {get: function(){return margin;}, set: function(_){
  6.2219 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.2220 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.2221 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.2222 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.2223 +        }},
  6.2224 +        color:  {get: function(){return color;}, set: function(_){
  6.2225 +            color = nv.utils.getColor(_);
  6.2226 +        }},
  6.2227 +        duration: {get: function(){return duration;}, set: function(_){
  6.2228 +            duration = _;
  6.2229 +            renderWatch.reset(duration);
  6.2230 +        }}
  6.2231 +    });
  6.2232 +
  6.2233 +    nv.utils.initOptions(chart);
  6.2234 +
  6.2235 +    return chart;
  6.2236 +};
  6.2237 +nv.models.boxPlotChart = function() {
  6.2238 +    "use strict";
  6.2239 +
  6.2240 +    //============================================================
  6.2241 +    // Public Variables with Default Settings
  6.2242 +    //------------------------------------------------------------
  6.2243 +
  6.2244 +    var boxplot = nv.models.boxPlot()
  6.2245 +        , xAxis = nv.models.axis()
  6.2246 +        , yAxis = nv.models.axis()
  6.2247 +        ;
  6.2248 +
  6.2249 +    var margin = {top: 15, right: 10, bottom: 50, left: 60}
  6.2250 +        , width = null
  6.2251 +        , height = null
  6.2252 +        , color = nv.utils.getColor()
  6.2253 +        , showXAxis = true
  6.2254 +        , showYAxis = true
  6.2255 +        , rightAlignYAxis = false
  6.2256 +        , staggerLabels = false
  6.2257 +        , tooltip = nv.models.tooltip()
  6.2258 +        , x
  6.2259 +        , y
  6.2260 +        , noData = "No Data Available."
  6.2261 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate', 'renderEnd')
  6.2262 +        , duration = 250
  6.2263 +        ;
  6.2264 +
  6.2265 +    xAxis
  6.2266 +        .orient('bottom')
  6.2267 +        .showMaxMin(false)
  6.2268 +        .tickFormat(function(d) { return d })
  6.2269 +    ;
  6.2270 +    yAxis
  6.2271 +        .orient((rightAlignYAxis) ? 'right' : 'left')
  6.2272 +        .tickFormat(d3.format(',.1f'))
  6.2273 +    ;
  6.2274 +    
  6.2275 +    tooltip.duration(0);
  6.2276 +
  6.2277 +    //============================================================
  6.2278 +    // Private Variables
  6.2279 +    //------------------------------------------------------------
  6.2280 +
  6.2281 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.2282 +
  6.2283 +    function chart(selection) {
  6.2284 +        renderWatch.reset();
  6.2285 +        renderWatch.models(boxplot);
  6.2286 +        if (showXAxis) renderWatch.models(xAxis);
  6.2287 +        if (showYAxis) renderWatch.models(yAxis);
  6.2288 +
  6.2289 +        selection.each(function(data) {
  6.2290 +            var container = d3.select(this),
  6.2291 +                that = this;
  6.2292 +            nv.utils.initSVG(container);
  6.2293 +            var availableWidth = (width  || parseInt(container.style('width')) || 960)
  6.2294 +                    - margin.left - margin.right,
  6.2295 +                availableHeight = (height || parseInt(container.style('height')) || 400)
  6.2296 +                    - margin.top - margin.bottom;
  6.2297 +
  6.2298 +            chart.update = function() {
  6.2299 +                dispatch.beforeUpdate();
  6.2300 +                container.transition().duration(duration).call(chart);
  6.2301 +            };
  6.2302 +            chart.container = this;
  6.2303 +
  6.2304 +            // Display No Data message if there's nothing to show. (quartiles required at minimum)
  6.2305 +            if (!data || !data.length || 
  6.2306 +                    !data.filter(function(d) { return d.values.hasOwnProperty("Q1") && d.values.hasOwnProperty("Q2") && d.values.hasOwnProperty("Q3"); }).length) {
  6.2307 +                var noDataText = container.selectAll('.nv-noData').data([noData]);
  6.2308 +
  6.2309 +                noDataText.enter().append('text')
  6.2310 +                    .attr('class', 'nvd3 nv-noData')
  6.2311 +                    .attr('dy', '-.7em')
  6.2312 +                    .style('text-anchor', 'middle');
  6.2313 +
  6.2314 +                noDataText
  6.2315 +                    .attr('x', margin.left + availableWidth / 2)
  6.2316 +                    .attr('y', margin.top + availableHeight / 2)
  6.2317 +                    .text(function(d) { return d });
  6.2318 +
  6.2319 +                return chart;
  6.2320 +            } else {
  6.2321 +                container.selectAll('.nv-noData').remove();
  6.2322 +            }
  6.2323 +
  6.2324 +            // Setup Scales
  6.2325 +            x = boxplot.xScale();
  6.2326 +            y = boxplot.yScale().clamp(true);
  6.2327 +
  6.2328 +            // Setup containers and skeleton of chart
  6.2329 +            var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]);
  6.2330 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g');
  6.2331 +            var defsEnter = gEnter.append('defs');
  6.2332 +            var g = wrap.select('g');
  6.2333 +
  6.2334 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.2335 +            gEnter.append('g').attr('class', 'nv-y nv-axis')
  6.2336 +                .append('g').attr('class', 'nv-zeroLine')
  6.2337 +                .append('line');
  6.2338 +
  6.2339 +            gEnter.append('g').attr('class', 'nv-barsWrap');
  6.2340 +
  6.2341 +            g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.2342 +
  6.2343 +            if (rightAlignYAxis) {
  6.2344 +                g.select(".nv-y.nv-axis")
  6.2345 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.2346 +            }
  6.2347 +
  6.2348 +            // Main Chart Component(s)
  6.2349 +            boxplot
  6.2350 +                .width(availableWidth)
  6.2351 +                .height(availableHeight);
  6.2352 +
  6.2353 +            var barsWrap = g.select('.nv-barsWrap')
  6.2354 +                .datum(data.filter(function(d) { return !d.disabled }))
  6.2355 +
  6.2356 +            barsWrap.transition().call(boxplot);
  6.2357 +
  6.2358 +
  6.2359 +            defsEnter.append('clipPath')
  6.2360 +                .attr('id', 'nv-x-label-clip-' + boxplot.id())
  6.2361 +                .append('rect');
  6.2362 +
  6.2363 +            g.select('#nv-x-label-clip-' + boxplot.id() + ' rect')
  6.2364 +                .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))
  6.2365 +                .attr('height', 16)
  6.2366 +                .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));
  6.2367 +
  6.2368 +            // Setup Axes
  6.2369 +            if (showXAxis) {
  6.2370 +                xAxis
  6.2371 +                    .scale(x)
  6.2372 +                    .ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.2373 +                    .tickSize(-availableHeight, 0);
  6.2374 +
  6.2375 +                g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')');
  6.2376 +                g.select('.nv-x.nv-axis').call(xAxis);
  6.2377 +
  6.2378 +                var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
  6.2379 +                if (staggerLabels) {
  6.2380 +                    xTicks
  6.2381 +                        .selectAll('text')
  6.2382 +                        .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
  6.2383 +                }
  6.2384 +            }
  6.2385 +
  6.2386 +            if (showYAxis) {
  6.2387 +                yAxis
  6.2388 +                    .scale(y)
  6.2389 +                    .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data
  6.2390 +                    .tickSize( -availableWidth, 0);
  6.2391 +
  6.2392 +                g.select('.nv-y.nv-axis').call(yAxis);
  6.2393 +            }
  6.2394 +
  6.2395 +            // Zero line
  6.2396 +            g.select(".nv-zeroLine line")
  6.2397 +                .attr("x1",0)
  6.2398 +                .attr("x2",availableWidth)
  6.2399 +                .attr("y1", y(0))
  6.2400 +                .attr("y2", y(0))
  6.2401 +            ;
  6.2402 +
  6.2403 +            //============================================================
  6.2404 +            // Event Handling/Dispatching (in chart's scope)
  6.2405 +            //------------------------------------------------------------
  6.2406 +        });
  6.2407 +
  6.2408 +        renderWatch.renderEnd('nv-boxplot chart immediate');
  6.2409 +        return chart;
  6.2410 +    }
  6.2411 +
  6.2412 +    //============================================================
  6.2413 +    // Event Handling/Dispatching (out of chart's scope)
  6.2414 +    //------------------------------------------------------------
  6.2415 +
  6.2416 +    boxplot.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.2417 +        tooltip.data(evt).hidden(false);
  6.2418 +    });
  6.2419 +
  6.2420 +    boxplot.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.2421 +        tooltip.data(evt).hidden(true);
  6.2422 +    });
  6.2423 +
  6.2424 +    boxplot.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.2425 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.2426 +    });
  6.2427 +
  6.2428 +    //============================================================
  6.2429 +    // Expose Public Variables
  6.2430 +    //------------------------------------------------------------
  6.2431 +
  6.2432 +    chart.dispatch = dispatch;
  6.2433 +    chart.boxplot = boxplot;
  6.2434 +    chart.xAxis = xAxis;
  6.2435 +    chart.yAxis = yAxis;
  6.2436 +    chart.tooltip = tooltip;
  6.2437 +
  6.2438 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.2439 +
  6.2440 +    chart._options = Object.create({}, {
  6.2441 +        // simple options, just get/set the necessary values
  6.2442 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.2443 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.2444 +        staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
  6.2445 +        showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.2446 +        showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.2447 +        tooltips:    {get: function(){return tooltips;}, set: function(_){tooltips=_;}},
  6.2448 +        tooltipContent:    {get: function(){return tooltip;}, set: function(_){tooltip=_;}},
  6.2449 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.2450 +
  6.2451 +        // options that require extra logic in the setter
  6.2452 +        margin: {get: function(){return margin;}, set: function(_){
  6.2453 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.2454 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.2455 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.2456 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.2457 +        }},
  6.2458 +        duration: {get: function(){return duration;}, set: function(_){
  6.2459 +            duration = _;
  6.2460 +            renderWatch.reset(duration);
  6.2461 +            boxplot.duration(duration);
  6.2462 +            xAxis.duration(duration);
  6.2463 +            yAxis.duration(duration);
  6.2464 +        }},
  6.2465 +        color:  {get: function(){return color;}, set: function(_){
  6.2466 +            color = nv.utils.getColor(_);
  6.2467 +            boxplot.color(color);
  6.2468 +        }},
  6.2469 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.2470 +            rightAlignYAxis = _;
  6.2471 +            yAxis.orient( (_) ? 'right' : 'left');
  6.2472 +        }}
  6.2473 +    });
  6.2474 +
  6.2475 +    nv.utils.inheritOptions(chart, boxplot);
  6.2476 +    nv.utils.initOptions(chart);
  6.2477 +
  6.2478 +    return chart;
  6.2479 +}
  6.2480 +// Chart design based on the recommendations of Stephen Few. Implementation
  6.2481 +// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
  6.2482 +// http://projects.instantcognition.com/protovis/bulletchart/
  6.2483 +
  6.2484 +nv.models.bullet = function() {
  6.2485 +    "use strict";
  6.2486 +
  6.2487 +    //============================================================
  6.2488 +    // Public Variables with Default Settings
  6.2489 +    //------------------------------------------------------------
  6.2490 +
  6.2491 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.2492 +        , orient = 'left' // TODO top & bottom
  6.2493 +        , reverse = false
  6.2494 +        , ranges = function(d) { return d.ranges }
  6.2495 +        , markers = function(d) { return d.markers ? d.markers : [0] }
  6.2496 +        , measures = function(d) { return d.measures }
  6.2497 +        , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }
  6.2498 +        , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : []  }
  6.2499 +        , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : []  }
  6.2500 +        , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
  6.2501 +        , width = 380
  6.2502 +        , height = 30
  6.2503 +        , container = null
  6.2504 +        , tickFormat = null
  6.2505 +        , color = nv.utils.getColor(['#1f77b4'])
  6.2506 +        , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove')
  6.2507 +        ;
  6.2508 +
  6.2509 +    function chart(selection) {
  6.2510 +        selection.each(function(d, i) {
  6.2511 +            var availableWidth = width - margin.left - margin.right,
  6.2512 +                availableHeight = height - margin.top - margin.bottom;
  6.2513 +
  6.2514 +            container = d3.select(this);
  6.2515 +            nv.utils.initSVG(container);
  6.2516 +
  6.2517 +            var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
  6.2518 +                markerz = markers.call(this, d, i).slice().sort(d3.descending),
  6.2519 +                measurez = measures.call(this, d, i).slice().sort(d3.descending),
  6.2520 +                rangeLabelz = rangeLabels.call(this, d, i).slice(),
  6.2521 +                markerLabelz = markerLabels.call(this, d, i).slice(),
  6.2522 +                measureLabelz = measureLabels.call(this, d, i).slice();
  6.2523 +
  6.2524 +            // Setup Scales
  6.2525 +            // Compute the new x-scale.
  6.2526 +            var x1 = d3.scale.linear()
  6.2527 +                .domain( d3.extent(d3.merge([forceX, rangez])) )
  6.2528 +                .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
  6.2529 +
  6.2530 +            // Retrieve the old x-scale, if this is an update.
  6.2531 +            var x0 = this.__chart__ || d3.scale.linear()
  6.2532 +                .domain([0, Infinity])
  6.2533 +                .range(x1.range());
  6.2534 +
  6.2535 +            // Stash the new scale.
  6.2536 +            this.__chart__ = x1;
  6.2537 +
  6.2538 +            var rangeMin = d3.min(rangez), //rangez[2]
  6.2539 +                rangeMax = d3.max(rangez), //rangez[0]
  6.2540 +                rangeAvg = rangez[1];
  6.2541 +
  6.2542 +            // Setup containers and skeleton of chart
  6.2543 +            var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]);
  6.2544 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet');
  6.2545 +            var gEnter = wrapEnter.append('g');
  6.2546 +            var g = wrap.select('g');
  6.2547 +
  6.2548 +            gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');
  6.2549 +            gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg');
  6.2550 +            gEnter.append('rect').attr('class', 'nv-range nv-rangeMin');
  6.2551 +            gEnter.append('rect').attr('class', 'nv-measure');
  6.2552 +
  6.2553 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.2554 +
  6.2555 +            var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
  6.2556 +                w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
  6.2557 +            var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },
  6.2558 +                xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };
  6.2559 +
  6.2560 +            g.select('rect.nv-rangeMax')
  6.2561 +                .attr('height', availableHeight)
  6.2562 +                .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))
  6.2563 +                .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))
  6.2564 +                .datum(rangeMax > 0 ? rangeMax : rangeMin)
  6.2565 +
  6.2566 +            g.select('rect.nv-rangeAvg')
  6.2567 +                .attr('height', availableHeight)
  6.2568 +                .attr('width', w1(rangeAvg))
  6.2569 +                .attr('x', xp1(rangeAvg))
  6.2570 +                .datum(rangeAvg)
  6.2571 +
  6.2572 +            g.select('rect.nv-rangeMin')
  6.2573 +                .attr('height', availableHeight)
  6.2574 +                .attr('width', w1(rangeMax))
  6.2575 +                .attr('x', xp1(rangeMax))
  6.2576 +                .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))
  6.2577 +                .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))
  6.2578 +                .datum(rangeMax > 0 ? rangeMin : rangeMax)
  6.2579 +
  6.2580 +            g.select('rect.nv-measure')
  6.2581 +                .style('fill', color)
  6.2582 +                .attr('height', availableHeight / 3)
  6.2583 +                .attr('y', availableHeight / 3)
  6.2584 +                .attr('width', measurez < 0 ?
  6.2585 +                    x1(0) - x1(measurez[0])
  6.2586 +                    : x1(measurez[0]) - x1(0))
  6.2587 +                .attr('x', xp1(measurez))
  6.2588 +                .on('mouseover', function() {
  6.2589 +                    dispatch.elementMouseover({
  6.2590 +                        value: measurez[0],
  6.2591 +                        label: measureLabelz[0] || 'Current',
  6.2592 +                        color: d3.select(this).style("fill")
  6.2593 +                    })
  6.2594 +                })
  6.2595 +                .on('mousemove', function() {
  6.2596 +                    dispatch.elementMousemove({
  6.2597 +                        value: measurez[0],
  6.2598 +                        label: measureLabelz[0] || 'Current',
  6.2599 +                        color: d3.select(this).style("fill")
  6.2600 +                    })
  6.2601 +                })
  6.2602 +                .on('mouseout', function() {
  6.2603 +                    dispatch.elementMouseout({
  6.2604 +                        value: measurez[0],
  6.2605 +                        label: measureLabelz[0] || 'Current',
  6.2606 +                        color: d3.select(this).style("fill")
  6.2607 +                    })
  6.2608 +                });
  6.2609 +
  6.2610 +            var h3 =  availableHeight / 6;
  6.2611 +
  6.2612 +            var markerData = markerz.map( function(marker, index) {
  6.2613 +                return {value: marker, label: markerLabelz[index]}
  6.2614 +            });
  6.2615 +            gEnter
  6.2616 +              .selectAll("path.nv-markerTriangle")
  6.2617 +              .data(markerData)
  6.2618 +              .enter()
  6.2619 +              .append('path')
  6.2620 +              .attr('class', 'nv-markerTriangle')
  6.2621 +              .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' })
  6.2622 +              .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')
  6.2623 +              .on('mouseover', function(d) {
  6.2624 +                dispatch.elementMouseover({
  6.2625 +                  value: d.value,
  6.2626 +                  label: d.label || 'Previous',
  6.2627 +                  color: d3.select(this).style("fill"),
  6.2628 +                  pos: [x1(d.value), availableHeight/2]
  6.2629 +                })
  6.2630 +
  6.2631 +              })
  6.2632 +              .on('mousemove', function(d) {
  6.2633 +                  dispatch.elementMousemove({
  6.2634 +                      value: d.value,
  6.2635 +                      label: d.label || 'Previous',
  6.2636 +                      color: d3.select(this).style("fill")
  6.2637 +                  })
  6.2638 +              })
  6.2639 +              .on('mouseout', function(d, i) {
  6.2640 +                  dispatch.elementMouseout({
  6.2641 +                      value: d.value,
  6.2642 +                      label: d.label || 'Previous',
  6.2643 +                      color: d3.select(this).style("fill")
  6.2644 +                  })
  6.2645 +              });
  6.2646 +
  6.2647 +            wrap.selectAll('.nv-range')
  6.2648 +                .on('mouseover', function(d,i) {
  6.2649 +                    var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");
  6.2650 +                    dispatch.elementMouseover({
  6.2651 +                        value: d,
  6.2652 +                        label: label,
  6.2653 +                        color: d3.select(this).style("fill")
  6.2654 +                    })
  6.2655 +                })
  6.2656 +                .on('mousemove', function() {
  6.2657 +                    dispatch.elementMousemove({
  6.2658 +                        value: measurez[0],
  6.2659 +                        label: measureLabelz[0] || 'Previous',
  6.2660 +                        color: d3.select(this).style("fill")
  6.2661 +                    })
  6.2662 +                })
  6.2663 +                .on('mouseout', function(d,i) {
  6.2664 +                    var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");
  6.2665 +                    dispatch.elementMouseout({
  6.2666 +                        value: d,
  6.2667 +                        label: label,
  6.2668 +                        color: d3.select(this).style("fill")
  6.2669 +                    })
  6.2670 +                });
  6.2671 +        });
  6.2672 +
  6.2673 +        return chart;
  6.2674 +    }
  6.2675 +
  6.2676 +    //============================================================
  6.2677 +    // Expose Public Variables
  6.2678 +    //------------------------------------------------------------
  6.2679 +
  6.2680 +    chart.dispatch = dispatch;
  6.2681 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.2682 +
  6.2683 +    chart._options = Object.create({}, {
  6.2684 +        // simple options, just get/set the necessary values
  6.2685 +        ranges:      {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good)
  6.2686 +        markers:     {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal)
  6.2687 +        measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast)
  6.2688 +        forceX:      {get: function(){return forceX;}, set: function(_){forceX=_;}},
  6.2689 +        width:    {get: function(){return width;}, set: function(_){width=_;}},
  6.2690 +        height:    {get: function(){return height;}, set: function(_){height=_;}},
  6.2691 +        tickFormat:    {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}},
  6.2692 +
  6.2693 +        // options that require extra logic in the setter
  6.2694 +        margin: {get: function(){return margin;}, set: function(_){
  6.2695 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.2696 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.2697 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.2698 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.2699 +        }},
  6.2700 +        orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom
  6.2701 +            orient = _;
  6.2702 +            reverse = orient == 'right' || orient == 'bottom';
  6.2703 +        }},
  6.2704 +        color:  {get: function(){return color;}, set: function(_){
  6.2705 +            color = nv.utils.getColor(_);
  6.2706 +        }}
  6.2707 +    });
  6.2708 +
  6.2709 +    nv.utils.initOptions(chart);
  6.2710 +    return chart;
  6.2711 +};
  6.2712 +
  6.2713 +
  6.2714 +
  6.2715 +// Chart design based on the recommendations of Stephen Few. Implementation
  6.2716 +// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
  6.2717 +// http://projects.instantcognition.com/protovis/bulletchart/
  6.2718 +nv.models.bulletChart = function() {
  6.2719 +    "use strict";
  6.2720 +
  6.2721 +    //============================================================
  6.2722 +    // Public Variables with Default Settings
  6.2723 +    //------------------------------------------------------------
  6.2724 +
  6.2725 +    var bullet = nv.models.bullet();
  6.2726 +    var tooltip = nv.models.tooltip();
  6.2727 +
  6.2728 +    var orient = 'left' // TODO top & bottom
  6.2729 +        , reverse = false
  6.2730 +        , margin = {top: 5, right: 40, bottom: 20, left: 120}
  6.2731 +        , ranges = function(d) { return d.ranges }
  6.2732 +        , markers = function(d) { return d.markers ? d.markers : [0] }
  6.2733 +        , measures = function(d) { return d.measures }
  6.2734 +        , width = null
  6.2735 +        , height = 55
  6.2736 +        , tickFormat = null
  6.2737 +	, ticks = null
  6.2738 +        , noData = null
  6.2739 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
  6.2740 +        ;
  6.2741 +
  6.2742 +    tooltip.duration(0).headerEnabled(false);
  6.2743 +
  6.2744 +    function chart(selection) {
  6.2745 +        selection.each(function(d, i) {
  6.2746 +            var container = d3.select(this);
  6.2747 +            nv.utils.initSVG(container);
  6.2748 +
  6.2749 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.2750 +                availableHeight = height - margin.top - margin.bottom,
  6.2751 +                that = this;
  6.2752 +
  6.2753 +            chart.update = function() { chart(selection) };
  6.2754 +            chart.container = this;
  6.2755 +
  6.2756 +            // Display No Data message if there's nothing to show.
  6.2757 +            if (!d || !ranges.call(this, d, i)) {
  6.2758 +                nv.utils.noData(chart, container)
  6.2759 +                return chart;
  6.2760 +            } else {
  6.2761 +                container.selectAll('.nv-noData').remove();
  6.2762 +            }
  6.2763 +
  6.2764 +            var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
  6.2765 +                markerz = markers.call(this, d, i).slice().sort(d3.descending),
  6.2766 +                measurez = measures.call(this, d, i).slice().sort(d3.descending);
  6.2767 +
  6.2768 +            // Setup containers and skeleton of chart
  6.2769 +            var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]);
  6.2770 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');
  6.2771 +            var gEnter = wrapEnter.append('g');
  6.2772 +            var g = wrap.select('g');
  6.2773 +
  6.2774 +            gEnter.append('g').attr('class', 'nv-bulletWrap');
  6.2775 +            gEnter.append('g').attr('class', 'nv-titles');
  6.2776 +
  6.2777 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.2778 +
  6.2779 +            // Compute the new x-scale.
  6.2780 +            var x1 = d3.scale.linear()
  6.2781 +                .domain([0, Math.max(rangez[0], markerz[0], measurez[0])])  // TODO: need to allow forceX and forceY, and xDomain, yDomain
  6.2782 +                .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
  6.2783 +
  6.2784 +            // Retrieve the old x-scale, if this is an update.
  6.2785 +            var x0 = this.__chart__ || d3.scale.linear()
  6.2786 +                .domain([0, Infinity])
  6.2787 +                .range(x1.range());
  6.2788 +
  6.2789 +            // Stash the new scale.
  6.2790 +            this.__chart__ = x1;
  6.2791 +
  6.2792 +            var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
  6.2793 +                w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
  6.2794 +
  6.2795 +            var title = gEnter.select('.nv-titles').append('g')
  6.2796 +                .attr('text-anchor', 'end')
  6.2797 +                .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');
  6.2798 +            title.append('text')
  6.2799 +                .attr('class', 'nv-title')
  6.2800 +                .text(function(d) { return d.title; });
  6.2801 +
  6.2802 +            title.append('text')
  6.2803 +                .attr('class', 'nv-subtitle')
  6.2804 +                .attr('dy', '1em')
  6.2805 +                .text(function(d) { return d.subtitle; });
  6.2806 +
  6.2807 +            bullet
  6.2808 +                .width(availableWidth)
  6.2809 +                .height(availableHeight)
  6.2810 +
  6.2811 +            var bulletWrap = g.select('.nv-bulletWrap');
  6.2812 +            d3.transition(bulletWrap).call(bullet);
  6.2813 +
  6.2814 +            // Compute the tick format.
  6.2815 +            var format = tickFormat || x1.tickFormat( availableWidth / 100 );
  6.2816 +
  6.2817 +            // Update the tick groups.
  6.2818 +            var tick = g.selectAll('g.nv-tick')
  6.2819 +                .data(x1.ticks( ticks ? ticks : (availableWidth / 50) ), function(d) {
  6.2820 +                    return this.textContent || format(d);
  6.2821 +                });
  6.2822 +
  6.2823 +            // Initialize the ticks with the old scale, x0.
  6.2824 +            var tickEnter = tick.enter().append('g')
  6.2825 +                .attr('class', 'nv-tick')
  6.2826 +                .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' })
  6.2827 +                .style('opacity', 1e-6);
  6.2828 +
  6.2829 +            tickEnter.append('line')
  6.2830 +                .attr('y1', availableHeight)
  6.2831 +                .attr('y2', availableHeight * 7 / 6);
  6.2832 +
  6.2833 +            tickEnter.append('text')
  6.2834 +                .attr('text-anchor', 'middle')
  6.2835 +                .attr('dy', '1em')
  6.2836 +                .attr('y', availableHeight * 7 / 6)
  6.2837 +                .text(format);
  6.2838 +
  6.2839 +            // Transition the updating ticks to the new scale, x1.
  6.2840 +            var tickUpdate = d3.transition(tick)
  6.2841 +                .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
  6.2842 +                .style('opacity', 1);
  6.2843 +
  6.2844 +            tickUpdate.select('line')
  6.2845 +                .attr('y1', availableHeight)
  6.2846 +                .attr('y2', availableHeight * 7 / 6);
  6.2847 +
  6.2848 +            tickUpdate.select('text')
  6.2849 +                .attr('y', availableHeight * 7 / 6);
  6.2850 +
  6.2851 +            // Transition the exiting ticks to the new scale, x1.
  6.2852 +            d3.transition(tick.exit())
  6.2853 +                .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })
  6.2854 +                .style('opacity', 1e-6)
  6.2855 +                .remove();
  6.2856 +        });
  6.2857 +
  6.2858 +        d3.timer.flush();
  6.2859 +        return chart;
  6.2860 +    }
  6.2861 +
  6.2862 +    //============================================================
  6.2863 +    // Event Handling/Dispatching (out of chart's scope)
  6.2864 +    //------------------------------------------------------------
  6.2865 +
  6.2866 +    bullet.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.2867 +        evt['series'] = {
  6.2868 +            key: evt.label,
  6.2869 +            value: evt.value,
  6.2870 +            color: evt.color
  6.2871 +        };
  6.2872 +        tooltip.data(evt).hidden(false);
  6.2873 +    });
  6.2874 +
  6.2875 +    bullet.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.2876 +        tooltip.hidden(true);
  6.2877 +    });
  6.2878 +
  6.2879 +    bullet.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.2880 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.2881 +    });
  6.2882 +
  6.2883 +    //============================================================
  6.2884 +    // Expose Public Variables
  6.2885 +    //------------------------------------------------------------
  6.2886 +
  6.2887 +    chart.bullet = bullet;
  6.2888 +    chart.dispatch = dispatch;
  6.2889 +    chart.tooltip = tooltip;
  6.2890 +
  6.2891 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.2892 +
  6.2893 +    chart._options = Object.create({}, {
  6.2894 +        // simple options, just get/set the necessary values
  6.2895 +        ranges:      {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good)
  6.2896 +        markers:     {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal)
  6.2897 +        measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast)
  6.2898 +        width:    {get: function(){return width;}, set: function(_){width=_;}},
  6.2899 +        height:    {get: function(){return height;}, set: function(_){height=_;}},
  6.2900 +        tickFormat:    {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}},
  6.2901 +        ticks:    {get: function(){return ticks;}, set: function(_){ticks=_;}},
  6.2902 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.2903 +
  6.2904 +        // deprecated options
  6.2905 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.2906 +            // deprecated after 1.7.1
  6.2907 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.2908 +            tooltip.enabled(!!_);
  6.2909 +        }},
  6.2910 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.2911 +            // deprecated after 1.7.1
  6.2912 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.2913 +            tooltip.contentGenerator(_);
  6.2914 +        }},
  6.2915 +
  6.2916 +        // options that require extra logic in the setter
  6.2917 +        margin: {get: function(){return margin;}, set: function(_){
  6.2918 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.2919 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.2920 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.2921 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.2922 +        }},
  6.2923 +        orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom
  6.2924 +            orient = _;
  6.2925 +            reverse = orient == 'right' || orient == 'bottom';
  6.2926 +        }}
  6.2927 +    });
  6.2928 +
  6.2929 +    nv.utils.inheritOptions(chart, bullet);
  6.2930 +    nv.utils.initOptions(chart);
  6.2931 +
  6.2932 +    return chart;
  6.2933 +};
  6.2934 +
  6.2935 +
  6.2936 +
  6.2937 +nv.models.candlestickBar = function() {
  6.2938 +    "use strict";
  6.2939 +
  6.2940 +    //============================================================
  6.2941 +    // Public Variables with Default Settings
  6.2942 +    //------------------------------------------------------------
  6.2943 +
  6.2944 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.2945 +        , width = null
  6.2946 +        , height = null
  6.2947 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.2948 +        , container
  6.2949 +        , x = d3.scale.linear()
  6.2950 +        , y = d3.scale.linear()
  6.2951 +        , getX = function(d) { return d.x }
  6.2952 +        , getY = function(d) { return d.y }
  6.2953 +        , getOpen = function(d) { return d.open }
  6.2954 +        , getClose = function(d) { return d.close }
  6.2955 +        , getHigh = function(d) { return d.high }
  6.2956 +        , getLow = function(d) { return d.low }
  6.2957 +        , forceX = []
  6.2958 +        , forceY = []
  6.2959 +        , padData     = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
  6.2960 +        , clipEdge = true
  6.2961 +        , color = nv.utils.defaultColor()
  6.2962 +        , interactive = false
  6.2963 +        , xDomain
  6.2964 +        , yDomain
  6.2965 +        , xRange
  6.2966 +        , yRange
  6.2967 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove')
  6.2968 +        ;
  6.2969 +
  6.2970 +    //============================================================
  6.2971 +    // Private Variables
  6.2972 +    //------------------------------------------------------------
  6.2973 +
  6.2974 +    function chart(selection) {
  6.2975 +        selection.each(function(data) {
  6.2976 +            container = d3.select(this);
  6.2977 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.2978 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.2979 +
  6.2980 +            nv.utils.initSVG(container);
  6.2981 +
  6.2982 +            // Width of the candlestick bars.
  6.2983 +            var barWidth = (availableWidth / data[0].values.length) * .45;
  6.2984 +
  6.2985 +            // Setup Scales
  6.2986 +            x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
  6.2987 +
  6.2988 +            if (padData)
  6.2989 +                x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5)  / data[0].values.length ]);
  6.2990 +            else
  6.2991 +                x.range(xRange || [5 + barWidth / 2, availableWidth - barWidth / 2 - 5]);
  6.2992 +
  6.2993 +            y.domain(yDomain || [
  6.2994 +                    d3.min(data[0].values.map(getLow).concat(forceY)),
  6.2995 +                    d3.max(data[0].values.map(getHigh).concat(forceY))
  6.2996 +                ]
  6.2997 +            ).range(yRange || [availableHeight, 0]);
  6.2998 +
  6.2999 +            // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
  6.3000 +            if (x.domain()[0] === x.domain()[1])
  6.3001 +                x.domain()[0] ?
  6.3002 +                    x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
  6.3003 +                    : x.domain([-1,1]);
  6.3004 +
  6.3005 +            if (y.domain()[0] === y.domain()[1])
  6.3006 +                y.domain()[0] ?
  6.3007 +                    y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
  6.3008 +                    : y.domain([-1,1]);
  6.3009 +
  6.3010 +            // Setup containers and skeleton of chart
  6.3011 +            var wrap = d3.select(this).selectAll('g.nv-wrap.nv-candlestickBar').data([data[0].values]);
  6.3012 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-candlestickBar');
  6.3013 +            var defsEnter = wrapEnter.append('defs');
  6.3014 +            var gEnter = wrapEnter.append('g');
  6.3015 +            var g = wrap.select('g');
  6.3016 +
  6.3017 +            gEnter.append('g').attr('class', 'nv-ticks');
  6.3018 +
  6.3019 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.3020 +
  6.3021 +            container
  6.3022 +                .on('click', function(d,i) {
  6.3023 +                    dispatch.chartClick({
  6.3024 +                        data: d,
  6.3025 +                        index: i,
  6.3026 +                        pos: d3.event,
  6.3027 +                        id: id
  6.3028 +                    });
  6.3029 +                });
  6.3030 +
  6.3031 +            defsEnter.append('clipPath')
  6.3032 +                .attr('id', 'nv-chart-clip-path-' + id)
  6.3033 +                .append('rect');
  6.3034 +
  6.3035 +            wrap.select('#nv-chart-clip-path-' + id + ' rect')
  6.3036 +                .attr('width', availableWidth)
  6.3037 +                .attr('height', availableHeight);
  6.3038 +
  6.3039 +            g   .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
  6.3040 +
  6.3041 +            var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')
  6.3042 +                .data(function(d) { return d });
  6.3043 +            ticks.exit().remove();
  6.3044 +
  6.3045 +            // The colors are currently controlled by CSS.
  6.3046 +            var tickGroups = ticks.enter().append('g')
  6.3047 +                .attr('class', function(d, i, j) { return (getOpen(d, i) > getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i});
  6.3048 +
  6.3049 +            var lines = tickGroups.append('line')
  6.3050 +                .attr('class', 'nv-candlestick-lines')
  6.3051 +                .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })
  6.3052 +                .attr('x1', 0)
  6.3053 +                .attr('y1', function(d, i) { return y(getHigh(d, i)); })
  6.3054 +                .attr('x2', 0)
  6.3055 +                .attr('y2', function(d, i) { return y(getLow(d, i)); });
  6.3056 +
  6.3057 +            var rects = tickGroups.append('rect')
  6.3058 +                .attr('class', 'nv-candlestick-rects nv-bars')
  6.3059 +                .attr('transform', function(d, i) {
  6.3060 +                    return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','
  6.3061 +                    + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))
  6.3062 +                    + ')';
  6.3063 +                })
  6.3064 +                .attr('x', 0)
  6.3065 +                .attr('y', 0)
  6.3066 +                .attr('width', barWidth)
  6.3067 +                .attr('height', function(d, i) {
  6.3068 +                    var open = getOpen(d, i);
  6.3069 +                    var close = getClose(d, i);
  6.3070 +                    return open > close ? y(close) - y(open) : y(open) - y(close);
  6.3071 +                });
  6.3072 +
  6.3073 +            container.selectAll('.nv-candlestick-lines').transition()
  6.3074 +                .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })
  6.3075 +                .attr('x1', 0)
  6.3076 +                .attr('y1', function(d, i) { return y(getHigh(d, i)); })
  6.3077 +                .attr('x2', 0)
  6.3078 +                .attr('y2', function(d, i) { return y(getLow(d, i)); });
  6.3079 +
  6.3080 +            container.selectAll('.nv-candlestick-rects').transition()
  6.3081 +                .attr('transform', function(d, i) {
  6.3082 +                    return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','
  6.3083 +                    + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))
  6.3084 +                    + ')';
  6.3085 +                })
  6.3086 +                .attr('x', 0)
  6.3087 +                .attr('y', 0)
  6.3088 +                .attr('width', barWidth)
  6.3089 +                .attr('height', function(d, i) {
  6.3090 +                    var open = getOpen(d, i);
  6.3091 +                    var close = getClose(d, i);
  6.3092 +                    return open > close ? y(close) - y(open) : y(open) - y(close);
  6.3093 +                });
  6.3094 +        });
  6.3095 +
  6.3096 +        return chart;
  6.3097 +    }
  6.3098 +
  6.3099 +
  6.3100 +    //Create methods to allow outside functions to highlight a specific bar.
  6.3101 +    chart.highlightPoint = function(pointIndex, isHoverOver) {
  6.3102 +        chart.clearHighlights();
  6.3103 +        container.select(".nv-candlestickBar .nv-tick-0-" + pointIndex)
  6.3104 +            .classed("hover", isHoverOver)
  6.3105 +        ;
  6.3106 +    };
  6.3107 +
  6.3108 +    chart.clearHighlights = function() {
  6.3109 +        container.select(".nv-candlestickBar .nv-tick.hover")
  6.3110 +            .classed("hover", false)
  6.3111 +        ;
  6.3112 +    };
  6.3113 +
  6.3114 +    //============================================================
  6.3115 +    // Expose Public Variables
  6.3116 +    //------------------------------------------------------------
  6.3117 +
  6.3118 +    chart.dispatch = dispatch;
  6.3119 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.3120 +
  6.3121 +    chart._options = Object.create({}, {
  6.3122 +        // simple options, just get/set the necessary values
  6.3123 +        width:    {get: function(){return width;}, set: function(_){width=_;}},
  6.3124 +        height:   {get: function(){return height;}, set: function(_){height=_;}},
  6.3125 +        xScale:   {get: function(){return x;}, set: function(_){x=_;}},
  6.3126 +        yScale:   {get: function(){return y;}, set: function(_){y=_;}},
  6.3127 +        xDomain:  {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.3128 +        yDomain:  {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.3129 +        xRange:   {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.3130 +        yRange:   {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.3131 +        forceX:   {get: function(){return forceX;}, set: function(_){forceX=_;}},
  6.3132 +        forceY:   {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.3133 +        padData:  {get: function(){return padData;}, set: function(_){padData=_;}},
  6.3134 +        clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
  6.3135 +        id:       {get: function(){return id;}, set: function(_){id=_;}},
  6.3136 +        interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
  6.3137 +
  6.3138 +        x:     {get: function(){return getX;}, set: function(_){getX=_;}},
  6.3139 +        y:     {get: function(){return getY;}, set: function(_){getY=_;}},
  6.3140 +        open:  {get: function(){return getOpen();}, set: function(_){getOpen=_;}},
  6.3141 +        close: {get: function(){return getClose();}, set: function(_){getClose=_;}},
  6.3142 +        high:  {get: function(){return getHigh;}, set: function(_){getHigh=_;}},
  6.3143 +        low:   {get: function(){return getLow;}, set: function(_){getLow=_;}},
  6.3144 +
  6.3145 +        // options that require extra logic in the setter
  6.3146 +        margin: {get: function(){return margin;}, set: function(_){
  6.3147 +            margin.top    = _.top    != undefined ? _.top    : margin.top;
  6.3148 +            margin.right  = _.right  != undefined ? _.right  : margin.right;
  6.3149 +            margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
  6.3150 +            margin.left   = _.left   != undefined ? _.left   : margin.left;
  6.3151 +        }},
  6.3152 +        color:  {get: function(){return color;}, set: function(_){
  6.3153 +            color = nv.utils.getColor(_);
  6.3154 +        }}
  6.3155 +    });
  6.3156 +
  6.3157 +    nv.utils.initOptions(chart);
  6.3158 +    return chart;
  6.3159 +};
  6.3160 +
  6.3161 +nv.models.cumulativeLineChart = function() {
  6.3162 +    "use strict";
  6.3163 +
  6.3164 +    //============================================================
  6.3165 +    // Public Variables with Default Settings
  6.3166 +    //------------------------------------------------------------
  6.3167 +
  6.3168 +    var lines = nv.models.line()
  6.3169 +        , xAxis = nv.models.axis()
  6.3170 +        , yAxis = nv.models.axis()
  6.3171 +        , legend = nv.models.legend()
  6.3172 +        , controls = nv.models.legend()
  6.3173 +        , interactiveLayer = nv.interactiveGuideline()
  6.3174 +        , tooltip = nv.models.tooltip()
  6.3175 +        ;
  6.3176 +
  6.3177 +    var margin = {top: 30, right: 30, bottom: 50, left: 60}
  6.3178 +        , color = nv.utils.defaultColor()
  6.3179 +        , width = null
  6.3180 +        , height = null
  6.3181 +        , showLegend = true
  6.3182 +        , showXAxis = true
  6.3183 +        , showYAxis = true
  6.3184 +        , rightAlignYAxis = false
  6.3185 +        , showControls = true
  6.3186 +        , useInteractiveGuideline = false
  6.3187 +        , rescaleY = true
  6.3188 +        , x //can be accessed via chart.xScale()
  6.3189 +        , y //can be accessed via chart.yScale()
  6.3190 +        , id = lines.id()
  6.3191 +        , state = nv.utils.state()
  6.3192 +        , defaultState = null
  6.3193 +        , noData = null
  6.3194 +        , average = function(d) { return d.average }
  6.3195 +        , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
  6.3196 +        , transitionDuration = 250
  6.3197 +        , duration = 250
  6.3198 +        , noErrorCheck = false  //if set to TRUE, will bypass an error check in the indexify function.
  6.3199 +        ;
  6.3200 +
  6.3201 +    state.index = 0;
  6.3202 +    state.rescaleY = rescaleY;
  6.3203 +
  6.3204 +    xAxis.orient('bottom').tickPadding(7);
  6.3205 +    yAxis.orient((rightAlignYAxis) ? 'right' : 'left');
  6.3206 +
  6.3207 +    tooltip.valueFormatter(function(d, i) {
  6.3208 +        return yAxis.tickFormat()(d, i);
  6.3209 +    }).headerFormatter(function(d, i) {
  6.3210 +        return xAxis.tickFormat()(d, i);
  6.3211 +    });
  6.3212 +
  6.3213 +    controls.updateState(false);
  6.3214 +
  6.3215 +    //============================================================
  6.3216 +    // Private Variables
  6.3217 +    //------------------------------------------------------------
  6.3218 +
  6.3219 +    var dx = d3.scale.linear()
  6.3220 +        , index = {i: 0, x: 0}
  6.3221 +        , renderWatch = nv.utils.renderWatch(dispatch, duration)
  6.3222 +        ;
  6.3223 +
  6.3224 +    var stateGetter = function(data) {
  6.3225 +        return function(){
  6.3226 +            return {
  6.3227 +                active: data.map(function(d) { return !d.disabled }),
  6.3228 +                index: index.i,
  6.3229 +                rescaleY: rescaleY
  6.3230 +            };
  6.3231 +        }
  6.3232 +    };
  6.3233 +
  6.3234 +    var stateSetter = function(data) {
  6.3235 +        return function(state) {
  6.3236 +            if (state.index !== undefined)
  6.3237 +                index.i = state.index;
  6.3238 +            if (state.rescaleY !== undefined)
  6.3239 +                rescaleY = state.rescaleY;
  6.3240 +            if (state.active !== undefined)
  6.3241 +                data.forEach(function(series,i) {
  6.3242 +                    series.disabled = !state.active[i];
  6.3243 +                });
  6.3244 +        }
  6.3245 +    };
  6.3246 +
  6.3247 +    function chart(selection) {
  6.3248 +        renderWatch.reset();
  6.3249 +        renderWatch.models(lines);
  6.3250 +        if (showXAxis) renderWatch.models(xAxis);
  6.3251 +        if (showYAxis) renderWatch.models(yAxis);
  6.3252 +        selection.each(function(data) {
  6.3253 +            var container = d3.select(this);
  6.3254 +            nv.utils.initSVG(container);
  6.3255 +            container.classed('nv-chart-' + id, true);
  6.3256 +            var that = this;
  6.3257 +
  6.3258 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.3259 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.3260 +
  6.3261 +            chart.update = function() {
  6.3262 +                if (duration === 0)
  6.3263 +                    container.call(chart);
  6.3264 +                else
  6.3265 +                    container.transition().duration(duration).call(chart)
  6.3266 +            };
  6.3267 +            chart.container = this;
  6.3268 +
  6.3269 +            state
  6.3270 +                .setter(stateSetter(data), chart.update)
  6.3271 +                .getter(stateGetter(data))
  6.3272 +                .update();
  6.3273 +
  6.3274 +            // DEPRECATED set state.disableddisabled
  6.3275 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.3276 +
  6.3277 +            if (!defaultState) {
  6.3278 +                var key;
  6.3279 +                defaultState = {};
  6.3280 +                for (key in state) {
  6.3281 +                    if (state[key] instanceof Array)
  6.3282 +                        defaultState[key] = state[key].slice(0);
  6.3283 +                    else
  6.3284 +                        defaultState[key] = state[key];
  6.3285 +                }
  6.3286 +            }
  6.3287 +
  6.3288 +            var indexDrag = d3.behavior.drag()
  6.3289 +                .on('dragstart', dragStart)
  6.3290 +                .on('drag', dragMove)
  6.3291 +                .on('dragend', dragEnd);
  6.3292 +
  6.3293 +
  6.3294 +            function dragStart(d,i) {
  6.3295 +                d3.select(chart.container)
  6.3296 +                    .style('cursor', 'ew-resize');
  6.3297 +            }
  6.3298 +
  6.3299 +            function dragMove(d,i) {
  6.3300 +                index.x = d3.event.x;
  6.3301 +                index.i = Math.round(dx.invert(index.x));
  6.3302 +                updateZero();
  6.3303 +            }
  6.3304 +
  6.3305 +            function dragEnd(d,i) {
  6.3306 +                d3.select(chart.container)
  6.3307 +                    .style('cursor', 'auto');
  6.3308 +
  6.3309 +                // update state and send stateChange with new index
  6.3310 +                state.index = index.i;
  6.3311 +                dispatch.stateChange(state);
  6.3312 +            }
  6.3313 +
  6.3314 +            // Display No Data message if there's nothing to show.
  6.3315 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.3316 +                nv.utils.noData(chart, container)
  6.3317 +                return chart;
  6.3318 +            } else {
  6.3319 +                container.selectAll('.nv-noData').remove();
  6.3320 +            }
  6.3321 +
  6.3322 +            // Setup Scales
  6.3323 +            x = lines.xScale();
  6.3324 +            y = lines.yScale();
  6.3325 +
  6.3326 +            if (!rescaleY) {
  6.3327 +                var seriesDomains = data
  6.3328 +                    .filter(function(series) { return !series.disabled })
  6.3329 +                    .map(function(series,i) {
  6.3330 +                        var initialDomain = d3.extent(series.values, lines.y());
  6.3331 +
  6.3332 +                        //account for series being disabled when losing 95% or more
  6.3333 +                        if (initialDomain[0] < -.95) initialDomain[0] = -.95;
  6.3334 +
  6.3335 +                        return [
  6.3336 +                                (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
  6.3337 +                                (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
  6.3338 +                        ];
  6.3339 +                    });
  6.3340 +
  6.3341 +                var completeDomain = [
  6.3342 +                    d3.min(seriesDomains, function(d) { return d[0] }),
  6.3343 +                    d3.max(seriesDomains, function(d) { return d[1] })
  6.3344 +                ];
  6.3345 +
  6.3346 +                lines.yDomain(completeDomain);
  6.3347 +            } else {
  6.3348 +                lines.yDomain(null);
  6.3349 +            }
  6.3350 +
  6.3351 +            dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length
  6.3352 +                .range([0, availableWidth])
  6.3353 +                .clamp(true);
  6.3354 +
  6.3355 +            var data = indexify(index.i, data);
  6.3356 +
  6.3357 +            // Setup containers and skeleton of chart
  6.3358 +            var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";
  6.3359 +            var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
  6.3360 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
  6.3361 +            var g = wrap.select('g');
  6.3362 +
  6.3363 +            gEnter.append('g').attr('class', 'nv-interactive');
  6.3364 +            gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none");
  6.3365 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
  6.3366 +            gEnter.append('g').attr('class', 'nv-background');
  6.3367 +            gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents);
  6.3368 +            gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none");
  6.3369 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.3370 +            gEnter.append('g').attr('class', 'nv-controlsWrap');
  6.3371 +
  6.3372 +            // Legend
  6.3373 +            if (showLegend) {
  6.3374 +                legend.width(availableWidth);
  6.3375 +
  6.3376 +                g.select('.nv-legendWrap')
  6.3377 +                    .datum(data)
  6.3378 +                    .call(legend);
  6.3379 +
  6.3380 +                if ( margin.top != legend.height()) {
  6.3381 +                    margin.top = legend.height();
  6.3382 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.3383 +                }
  6.3384 +
  6.3385 +                g.select('.nv-legendWrap')
  6.3386 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.3387 +            }
  6.3388 +
  6.3389 +            // Controls
  6.3390 +            if (showControls) {
  6.3391 +                var controlsData = [
  6.3392 +                    { key: 'Re-scale y-axis', disabled: !rescaleY }
  6.3393 +                ];
  6.3394 +
  6.3395 +                controls
  6.3396 +                    .width(140)
  6.3397 +                    .color(['#444', '#444', '#444'])
  6.3398 +                    .rightAlign(false)
  6.3399 +                    .margin({top: 5, right: 0, bottom: 5, left: 20})
  6.3400 +                ;
  6.3401 +
  6.3402 +                g.select('.nv-controlsWrap')
  6.3403 +                    .datum(controlsData)
  6.3404 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.3405 +                    .call(controls);
  6.3406 +            }
  6.3407 +
  6.3408 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.3409 +
  6.3410 +            if (rightAlignYAxis) {
  6.3411 +                g.select(".nv-y.nv-axis")
  6.3412 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.3413 +            }
  6.3414 +
  6.3415 +            // Show error if series goes below 100%
  6.3416 +            var tempDisabled = data.filter(function(d) { return d.tempDisabled });
  6.3417 +
  6.3418 +            wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
  6.3419 +            if (tempDisabled.length) {
  6.3420 +                wrap.append('text').attr('class', 'tempDisabled')
  6.3421 +                    .attr('x', availableWidth / 2)
  6.3422 +                    .attr('y', '-.71em')
  6.3423 +                    .style('text-anchor', 'end')
  6.3424 +                    .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
  6.3425 +            }
  6.3426 +
  6.3427 +            //Set up interactive layer
  6.3428 +            if (useInteractiveGuideline) {
  6.3429 +                interactiveLayer
  6.3430 +                    .width(availableWidth)
  6.3431 +                    .height(availableHeight)
  6.3432 +                    .margin({left:margin.left,top:margin.top})
  6.3433 +                    .svgContainer(container)
  6.3434 +                    .xScale(x);
  6.3435 +                wrap.select(".nv-interactive").call(interactiveLayer);
  6.3436 +            }
  6.3437 +
  6.3438 +            gEnter.select('.nv-background')
  6.3439 +                .append('rect');
  6.3440 +
  6.3441 +            g.select('.nv-background rect')
  6.3442 +                .attr('width', availableWidth)
  6.3443 +                .attr('height', availableHeight);
  6.3444 +
  6.3445 +            lines
  6.3446 +                //.x(function(d) { return d.x })
  6.3447 +                .y(function(d) { return d.display.y })
  6.3448 +                .width(availableWidth)
  6.3449 +                .height(availableHeight)
  6.3450 +                .color(data.map(function(d,i) {
  6.3451 +                    return d.color || color(d, i);
  6.3452 +                }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
  6.3453 +
  6.3454 +            var linesWrap = g.select('.nv-linesWrap')
  6.3455 +                .datum(data.filter(function(d) { return  !d.disabled && !d.tempDisabled }));
  6.3456 +
  6.3457 +            linesWrap.call(lines);
  6.3458 +
  6.3459 +            //Store a series index number in the data array.
  6.3460 +            data.forEach(function(d,i) {
  6.3461 +                d.seriesIndex = i;
  6.3462 +            });
  6.3463 +
  6.3464 +            var avgLineData = data.filter(function(d) {
  6.3465 +                return !d.disabled && !!average(d);
  6.3466 +            });
  6.3467 +
  6.3468 +            var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
  6.3469 +                .data(avgLineData, function(d) { return d.key; });
  6.3470 +
  6.3471 +            var getAvgLineY = function(d) {
  6.3472 +                //If average lines go off the svg element, clamp them to the svg bounds.
  6.3473 +                var yVal = y(average(d));
  6.3474 +                if (yVal < 0) return 0;
  6.3475 +                if (yVal > availableHeight) return availableHeight;
  6.3476 +                return yVal;
  6.3477 +            };
  6.3478 +
  6.3479 +            avgLines.enter()
  6.3480 +                .append('line')
  6.3481 +                .style('stroke-width',2)
  6.3482 +                .style('stroke-dasharray','10,10')
  6.3483 +                .style('stroke',function (d,i) {
  6.3484 +                    return lines.color()(d,d.seriesIndex);
  6.3485 +                })
  6.3486 +                .attr('x1',0)
  6.3487 +                .attr('x2',availableWidth)
  6.3488 +                .attr('y1', getAvgLineY)
  6.3489 +                .attr('y2', getAvgLineY);
  6.3490 +
  6.3491 +            avgLines
  6.3492 +                .style('stroke-opacity',function(d){
  6.3493 +                    //If average lines go offscreen, make them transparent
  6.3494 +                    var yVal = y(average(d));
  6.3495 +                    if (yVal < 0 || yVal > availableHeight) return 0;
  6.3496 +                    return 1;
  6.3497 +                })
  6.3498 +                .attr('x1',0)
  6.3499 +                .attr('x2',availableWidth)
  6.3500 +                .attr('y1', getAvgLineY)
  6.3501 +                .attr('y2', getAvgLineY);
  6.3502 +
  6.3503 +            avgLines.exit().remove();
  6.3504 +
  6.3505 +            //Create index line
  6.3506 +            var indexLine = linesWrap.selectAll('.nv-indexLine')
  6.3507 +                .data([index]);
  6.3508 +            indexLine.enter().append('rect').attr('class', 'nv-indexLine')
  6.3509 +                .attr('width', 3)
  6.3510 +                .attr('x', -2)
  6.3511 +                .attr('fill', 'red')
  6.3512 +                .attr('fill-opacity', .5)
  6.3513 +                .style("pointer-events","all")
  6.3514 +                .call(indexDrag);
  6.3515 +
  6.3516 +            indexLine
  6.3517 +                .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })
  6.3518 +                .attr('height', availableHeight);
  6.3519 +
  6.3520 +            // Setup Axes
  6.3521 +            if (showXAxis) {
  6.3522 +                xAxis
  6.3523 +                    .scale(x)
  6.3524 +                    ._ticks( nv.utils.calcTicksX(availableWidth/70, data) )
  6.3525 +                    .tickSize(-availableHeight, 0);
  6.3526 +
  6.3527 +                g.select('.nv-x.nv-axis')
  6.3528 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')');
  6.3529 +                g.select('.nv-x.nv-axis')
  6.3530 +                    .call(xAxis);
  6.3531 +            }
  6.3532 +
  6.3533 +            if (showYAxis) {
  6.3534 +                yAxis
  6.3535 +                    .scale(y)
  6.3536 +                    ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.3537 +                    .tickSize( -availableWidth, 0);
  6.3538 +
  6.3539 +                g.select('.nv-y.nv-axis')
  6.3540 +                    .call(yAxis);
  6.3541 +            }
  6.3542 +
  6.3543 +            //============================================================
  6.3544 +            // Event Handling/Dispatching (in chart's scope)
  6.3545 +            //------------------------------------------------------------
  6.3546 +
  6.3547 +            function updateZero() {
  6.3548 +                indexLine
  6.3549 +                    .data([index]);
  6.3550 +
  6.3551 +                //When dragging the index line, turn off line transitions.
  6.3552 +                // Then turn them back on when done dragging.
  6.3553 +                var oldDuration = chart.duration();
  6.3554 +                chart.duration(0);
  6.3555 +                chart.update();
  6.3556 +                chart.duration(oldDuration);
  6.3557 +            }
  6.3558 +
  6.3559 +            g.select('.nv-background rect')
  6.3560 +                .on('click', function() {
  6.3561 +                    index.x = d3.mouse(this)[0];
  6.3562 +                    index.i = Math.round(dx.invert(index.x));
  6.3563 +
  6.3564 +                    // update state and send stateChange with new index
  6.3565 +                    state.index = index.i;
  6.3566 +                    dispatch.stateChange(state);
  6.3567 +
  6.3568 +                    updateZero();
  6.3569 +                });
  6.3570 +
  6.3571 +            lines.dispatch.on('elementClick', function(e) {
  6.3572 +                index.i = e.pointIndex;
  6.3573 +                index.x = dx(index.i);
  6.3574 +
  6.3575 +                // update state and send stateChange with new index
  6.3576 +                state.index = index.i;
  6.3577 +                dispatch.stateChange(state);
  6.3578 +
  6.3579 +                updateZero();
  6.3580 +            });
  6.3581 +
  6.3582 +            controls.dispatch.on('legendClick', function(d,i) {
  6.3583 +                d.disabled = !d.disabled;
  6.3584 +                rescaleY = !d.disabled;
  6.3585 +
  6.3586 +                state.rescaleY = rescaleY;
  6.3587 +                dispatch.stateChange(state);
  6.3588 +                chart.update();
  6.3589 +            });
  6.3590 +
  6.3591 +            legend.dispatch.on('stateChange', function(newState) {
  6.3592 +                for (var key in newState)
  6.3593 +                    state[key] = newState[key];
  6.3594 +                dispatch.stateChange(state);
  6.3595 +                chart.update();
  6.3596 +            });
  6.3597 +
  6.3598 +            interactiveLayer.dispatch.on('elementMousemove', function(e) {
  6.3599 +                lines.clearHighlights();
  6.3600 +                var singlePoint, pointIndex, pointXLocation, allData = [];
  6.3601 +
  6.3602 +                data
  6.3603 +                    .filter(function(series, i) {
  6.3604 +                        series.seriesIndex = i;
  6.3605 +                        return !series.disabled;
  6.3606 +                    })
  6.3607 +                    .forEach(function(series,i) {
  6.3608 +                        pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
  6.3609 +                        lines.highlightPoint(i, pointIndex, true);
  6.3610 +                        var point = series.values[pointIndex];
  6.3611 +                        if (typeof point === 'undefined') return;
  6.3612 +                        if (typeof singlePoint === 'undefined') singlePoint = point;
  6.3613 +                        if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
  6.3614 +                        allData.push({
  6.3615 +                            key: series.key,
  6.3616 +                            value: chart.y()(point, pointIndex),
  6.3617 +                            color: color(series,series.seriesIndex)
  6.3618 +                        });
  6.3619 +                    });
  6.3620 +
  6.3621 +                //Highlight the tooltip entry based on which point the mouse is closest to.
  6.3622 +                if (allData.length > 2) {
  6.3623 +                    var yValue = chart.yScale().invert(e.mouseY);
  6.3624 +                    var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
  6.3625 +                    var threshold = 0.03 * domainExtent;
  6.3626 +                    var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
  6.3627 +                    if (indexToHighlight !== null)
  6.3628 +                        allData[indexToHighlight].highlight = true;
  6.3629 +                }
  6.3630 +
  6.3631 +                var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);
  6.3632 +                interactiveLayer.tooltip
  6.3633 +                    .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
  6.3634 +                    .chartContainer(that.parentNode)
  6.3635 +                    .valueFormatter(function(d,i) {
  6.3636 +                        return yAxis.tickFormat()(d);
  6.3637 +                    })
  6.3638 +                    .data(
  6.3639 +                    {
  6.3640 +                        value: xValue,
  6.3641 +                        series: allData
  6.3642 +                    }
  6.3643 +                )();
  6.3644 +
  6.3645 +                interactiveLayer.renderGuideLine(pointXLocation);
  6.3646 +            });
  6.3647 +
  6.3648 +            interactiveLayer.dispatch.on("elementMouseout",function(e) {
  6.3649 +                lines.clearHighlights();
  6.3650 +            });
  6.3651 +
  6.3652 +            // Update chart from a state object passed to event handler
  6.3653 +            dispatch.on('changeState', function(e) {
  6.3654 +                if (typeof e.disabled !== 'undefined') {
  6.3655 +                    data.forEach(function(series,i) {
  6.3656 +                        series.disabled = e.disabled[i];
  6.3657 +                    });
  6.3658 +
  6.3659 +                    state.disabled = e.disabled;
  6.3660 +                }
  6.3661 +
  6.3662 +                if (typeof e.index !== 'undefined') {
  6.3663 +                    index.i = e.index;
  6.3664 +                    index.x = dx(index.i);
  6.3665 +
  6.3666 +                    state.index = e.index;
  6.3667 +
  6.3668 +                    indexLine
  6.3669 +                        .data([index]);
  6.3670 +                }
  6.3671 +
  6.3672 +                if (typeof e.rescaleY !== 'undefined') {
  6.3673 +                    rescaleY = e.rescaleY;
  6.3674 +                }
  6.3675 +
  6.3676 +                chart.update();
  6.3677 +            });
  6.3678 +
  6.3679 +        });
  6.3680 +
  6.3681 +        renderWatch.renderEnd('cumulativeLineChart immediate');
  6.3682 +
  6.3683 +        return chart;
  6.3684 +    }
  6.3685 +
  6.3686 +    //============================================================
  6.3687 +    // Event Handling/Dispatching (out of chart's scope)
  6.3688 +    //------------------------------------------------------------
  6.3689 +
  6.3690 +    lines.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.3691 +        var point = {
  6.3692 +            x: chart.x()(evt.point),
  6.3693 +            y: chart.y()(evt.point),
  6.3694 +            color: evt.point.color
  6.3695 +        };
  6.3696 +        evt.point = point;
  6.3697 +        tooltip.data(evt).position(evt.pos).hidden(false);
  6.3698 +    });
  6.3699 +
  6.3700 +    lines.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.3701 +        tooltip.hidden(true)
  6.3702 +    });
  6.3703 +
  6.3704 +    //============================================================
  6.3705 +    // Functions
  6.3706 +    //------------------------------------------------------------
  6.3707 +
  6.3708 +    var indexifyYGetter = null;
  6.3709 +    /* Normalize the data according to an index point. */
  6.3710 +    function indexify(idx, data) {
  6.3711 +        if (!indexifyYGetter) indexifyYGetter = lines.y();
  6.3712 +        return data.map(function(line, i) {
  6.3713 +            if (!line.values) {
  6.3714 +                return line;
  6.3715 +            }
  6.3716 +            var indexValue = line.values[idx];
  6.3717 +            if (indexValue == null) {
  6.3718 +                return line;
  6.3719 +            }
  6.3720 +            var v = indexifyYGetter(indexValue, idx);
  6.3721 +
  6.3722 +            //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
  6.3723 +            if (v < -.95 && !noErrorCheck) {
  6.3724 +                //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
  6.3725 +
  6.3726 +                line.tempDisabled = true;
  6.3727 +                return line;
  6.3728 +            }
  6.3729 +
  6.3730 +            line.tempDisabled = false;
  6.3731 +
  6.3732 +            line.values = line.values.map(function(point, pointIndex) {
  6.3733 +                point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / (1 + v) };
  6.3734 +                return point;
  6.3735 +            });
  6.3736 +
  6.3737 +            return line;
  6.3738 +        })
  6.3739 +    }
  6.3740 +
  6.3741 +    //============================================================
  6.3742 +    // Expose Public Variables
  6.3743 +    //------------------------------------------------------------
  6.3744 +
  6.3745 +    // expose chart's sub-components
  6.3746 +    chart.dispatch = dispatch;
  6.3747 +    chart.lines = lines;
  6.3748 +    chart.legend = legend;
  6.3749 +    chart.controls = controls;
  6.3750 +    chart.xAxis = xAxis;
  6.3751 +    chart.yAxis = yAxis;
  6.3752 +    chart.interactiveLayer = interactiveLayer;
  6.3753 +    chart.state = state;
  6.3754 +    chart.tooltip = tooltip;
  6.3755 +
  6.3756 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.3757 +
  6.3758 +    chart._options = Object.create({}, {
  6.3759 +        // simple options, just get/set the necessary values
  6.3760 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.3761 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.3762 +        rescaleY:     {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}},
  6.3763 +        showControls:     {get: function(){return showControls;}, set: function(_){showControls=_;}},
  6.3764 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.3765 +        average: {get: function(){return average;}, set: function(_){average=_;}},
  6.3766 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.3767 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.3768 +        showXAxis:    {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.3769 +        showYAxis:    {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.3770 +        noErrorCheck:    {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}},
  6.3771 +
  6.3772 +        // deprecated options
  6.3773 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.3774 +            // deprecated after 1.7.1
  6.3775 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.3776 +            tooltip.enabled(!!_);
  6.3777 +        }},
  6.3778 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.3779 +            // deprecated after 1.7.1
  6.3780 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.3781 +            tooltip.contentGenerator(_);
  6.3782 +        }},
  6.3783 +
  6.3784 +        // options that require extra logic in the setter
  6.3785 +        margin: {get: function(){return margin;}, set: function(_){
  6.3786 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.3787 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.3788 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.3789 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.3790 +        }},
  6.3791 +        color:  {get: function(){return color;}, set: function(_){
  6.3792 +            color = nv.utils.getColor(_);
  6.3793 +            legend.color(color);
  6.3794 +        }},
  6.3795 +        useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
  6.3796 +            useInteractiveGuideline = _;
  6.3797 +            if (_ === true) {
  6.3798 +                chart.interactive(false);
  6.3799 +                chart.useVoronoi(false);
  6.3800 +            }
  6.3801 +        }},
  6.3802 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.3803 +            rightAlignYAxis = _;
  6.3804 +            yAxis.orient( (_) ? 'right' : 'left');
  6.3805 +        }},
  6.3806 +        duration:    {get: function(){return duration;}, set: function(_){
  6.3807 +            duration = _;
  6.3808 +            lines.duration(duration);
  6.3809 +            xAxis.duration(duration);
  6.3810 +            yAxis.duration(duration);
  6.3811 +            renderWatch.reset(duration);
  6.3812 +        }}
  6.3813 +    });
  6.3814 +
  6.3815 +    nv.utils.inheritOptions(chart, lines);
  6.3816 +    nv.utils.initOptions(chart);
  6.3817 +
  6.3818 +    return chart;
  6.3819 +};
  6.3820 +//TODO: consider deprecating by adding necessary features to multiBar model
  6.3821 +nv.models.discreteBar = function() {
  6.3822 +    "use strict";
  6.3823 +
  6.3824 +    //============================================================
  6.3825 +    // Public Variables with Default Settings
  6.3826 +    //------------------------------------------------------------
  6.3827 +
  6.3828 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.3829 +        , width = 960
  6.3830 +        , height = 500
  6.3831 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.3832 +        , container
  6.3833 +        , x = d3.scale.ordinal()
  6.3834 +        , y = d3.scale.linear()
  6.3835 +        , getX = function(d) { return d.x }
  6.3836 +        , getY = function(d) { return d.y }
  6.3837 +        , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
  6.3838 +        , color = nv.utils.defaultColor()
  6.3839 +        , showValues = false
  6.3840 +        , valueFormat = d3.format(',.2f')
  6.3841 +        , xDomain
  6.3842 +        , yDomain
  6.3843 +        , xRange
  6.3844 +        , yRange
  6.3845 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
  6.3846 +        , rectClass = 'discreteBar'
  6.3847 +        , duration = 250
  6.3848 +        ;
  6.3849 +
  6.3850 +    //============================================================
  6.3851 +    // Private Variables
  6.3852 +    //------------------------------------------------------------
  6.3853 +
  6.3854 +    var x0, y0;
  6.3855 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.3856 +
  6.3857 +    function chart(selection) {
  6.3858 +        renderWatch.reset();
  6.3859 +        selection.each(function(data) {
  6.3860 +            var availableWidth = width - margin.left - margin.right,
  6.3861 +                availableHeight = height - margin.top - margin.bottom;
  6.3862 +
  6.3863 +            container = d3.select(this);
  6.3864 +            nv.utils.initSVG(container);
  6.3865 +
  6.3866 +            //add series index to each data point for reference
  6.3867 +            data.forEach(function(series, i) {
  6.3868 +                series.values.forEach(function(point) {
  6.3869 +                    point.series = i;
  6.3870 +                });
  6.3871 +            });
  6.3872 +
  6.3873 +            // Setup Scales
  6.3874 +            // remap and flatten the data for use in calculating the scales' domains
  6.3875 +            var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
  6.3876 +                data.map(function(d) {
  6.3877 +                    return d.values.map(function(d,i) {
  6.3878 +                        return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
  6.3879 +                    })
  6.3880 +                });
  6.3881 +
  6.3882 +            x   .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
  6.3883 +                .rangeBands(xRange || [0, availableWidth], .1);
  6.3884 +            y   .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY)));
  6.3885 +
  6.3886 +            // If showValues, pad the Y axis range to account for label height
  6.3887 +            if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]);
  6.3888 +            else y.range(yRange || [availableHeight, 0]);
  6.3889 +
  6.3890 +            //store old scales if they exist
  6.3891 +            x0 = x0 || x;
  6.3892 +            y0 = y0 || y.copy().range([y(0),y(0)]);
  6.3893 +
  6.3894 +            // Setup containers and skeleton of chart
  6.3895 +            var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]);
  6.3896 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar');
  6.3897 +            var gEnter = wrapEnter.append('g');
  6.3898 +            var g = wrap.select('g');
  6.3899 +
  6.3900 +            gEnter.append('g').attr('class', 'nv-groups');
  6.3901 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.3902 +
  6.3903 +            //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later
  6.3904 +            var groups = wrap.select('.nv-groups').selectAll('.nv-group')
  6.3905 +                .data(function(d) { return d }, function(d) { return d.key });
  6.3906 +            groups.enter().append('g')
  6.3907 +                .style('stroke-opacity', 1e-6)
  6.3908 +                .style('fill-opacity', 1e-6);
  6.3909 +            groups.exit()
  6.3910 +                .watchTransition(renderWatch, 'discreteBar: exit groups')
  6.3911 +                .style('stroke-opacity', 1e-6)
  6.3912 +                .style('fill-opacity', 1e-6)
  6.3913 +                .remove();
  6.3914 +            groups
  6.3915 +                .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
  6.3916 +                .classed('hover', function(d) { return d.hover });
  6.3917 +            groups
  6.3918 +                .watchTransition(renderWatch, 'discreteBar: groups')
  6.3919 +                .style('stroke-opacity', 1)
  6.3920 +                .style('fill-opacity', .75);
  6.3921 +
  6.3922 +            var bars = groups.selectAll('g.nv-bar')
  6.3923 +                .data(function(d) { return d.values });
  6.3924 +            bars.exit().remove();
  6.3925 +
  6.3926 +            var barsEnter = bars.enter().append('g')
  6.3927 +                .attr('transform', function(d,i,j) {
  6.3928 +                    return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'
  6.3929 +                })
  6.3930 +                .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
  6.3931 +                    d3.select(this).classed('hover', true);
  6.3932 +                    dispatch.elementMouseover({
  6.3933 +                        data: d,
  6.3934 +                        index: i,
  6.3935 +                        color: d3.select(this).style("fill")
  6.3936 +                    });
  6.3937 +                })
  6.3938 +                .on('mouseout', function(d,i) {
  6.3939 +                    d3.select(this).classed('hover', false);
  6.3940 +                    dispatch.elementMouseout({
  6.3941 +                        data: d,
  6.3942 +                        index: i,
  6.3943 +                        color: d3.select(this).style("fill")
  6.3944 +                    });
  6.3945 +                })
  6.3946 +                .on('mousemove', function(d,i) {
  6.3947 +                    dispatch.elementMousemove({
  6.3948 +                        data: d,
  6.3949 +                        index: i,
  6.3950 +                        color: d3.select(this).style("fill")
  6.3951 +                    });
  6.3952 +                })
  6.3953 +                .on('click', function(d,i) {
  6.3954 +                    dispatch.elementClick({
  6.3955 +                        data: d,
  6.3956 +                        index: i,
  6.3957 +                        color: d3.select(this).style("fill")
  6.3958 +                    });
  6.3959 +                    d3.event.stopPropagation();
  6.3960 +                })
  6.3961 +                .on('dblclick', function(d,i) {
  6.3962 +                    dispatch.elementDblClick({
  6.3963 +                        data: d,
  6.3964 +                        index: i,
  6.3965 +                        color: d3.select(this).style("fill")
  6.3966 +                    });
  6.3967 +                    d3.event.stopPropagation();
  6.3968 +                });
  6.3969 +
  6.3970 +            barsEnter.append('rect')
  6.3971 +                .attr('height', 0)
  6.3972 +                .attr('width', x.rangeBand() * .9 / data.length )
  6.3973 +
  6.3974 +            if (showValues) {
  6.3975 +                barsEnter.append('text')
  6.3976 +                    .attr('text-anchor', 'middle')
  6.3977 +                ;
  6.3978 +
  6.3979 +                bars.select('text')
  6.3980 +                    .text(function(d,i) { return valueFormat(getY(d,i)) })
  6.3981 +                    .watchTransition(renderWatch, 'discreteBar: bars text')
  6.3982 +                    .attr('x', x.rangeBand() * .9 / 2)
  6.3983 +                    .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })
  6.3984 +
  6.3985 +                ;
  6.3986 +            } else {
  6.3987 +                bars.selectAll('text').remove();
  6.3988 +            }
  6.3989 +
  6.3990 +            bars
  6.3991 +                .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' })
  6.3992 +                .style('fill', function(d,i) { return d.color || color(d,i) })
  6.3993 +                .style('stroke', function(d,i) { return d.color || color(d,i) })
  6.3994 +                .select('rect')
  6.3995 +                .attr('class', rectClass)
  6.3996 +                .watchTransition(renderWatch, 'discreteBar: bars rect')
  6.3997 +                .attr('width', x.rangeBand() * .9 / data.length);
  6.3998 +            bars.watchTransition(renderWatch, 'discreteBar: bars')
  6.3999 +                //.delay(function(d,i) { return i * 1200 / data[0].values.length })
  6.4000 +                .attr('transform', function(d,i) {
  6.4001 +                    var left = x(getX(d,i)) + x.rangeBand() * .05,
  6.4002 +                        top = getY(d,i) < 0 ?
  6.4003 +                            y(0) :
  6.4004 +                                y(0) - y(getY(d,i)) < 1 ?
  6.4005 +                            y(0) - 1 : //make 1 px positive bars show up above y=0
  6.4006 +                            y(getY(d,i));
  6.4007 +
  6.4008 +                    return 'translate(' + left + ', ' + top + ')'
  6.4009 +                })
  6.4010 +                .select('rect')
  6.4011 +                .attr('height', function(d,i) {
  6.4012 +                    return  Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1)
  6.4013 +                });
  6.4014 +
  6.4015 +
  6.4016 +            //store old scales for use in transitions on update
  6.4017 +            x0 = x.copy();
  6.4018 +            y0 = y.copy();
  6.4019 +
  6.4020 +        });
  6.4021 +
  6.4022 +        renderWatch.renderEnd('discreteBar immediate');
  6.4023 +        return chart;
  6.4024 +    }
  6.4025 +
  6.4026 +    //============================================================
  6.4027 +    // Expose Public Variables
  6.4028 +    //------------------------------------------------------------
  6.4029 +
  6.4030 +    chart.dispatch = dispatch;
  6.4031 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.4032 +
  6.4033 +    chart._options = Object.create({}, {
  6.4034 +        // simple options, just get/set the necessary values
  6.4035 +        width:   {get: function(){return width;}, set: function(_){width=_;}},
  6.4036 +        height:  {get: function(){return height;}, set: function(_){height=_;}},
  6.4037 +        forceY:  {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.4038 +        showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},
  6.4039 +        x:       {get: function(){return getX;}, set: function(_){getX=_;}},
  6.4040 +        y:       {get: function(){return getY;}, set: function(_){getY=_;}},
  6.4041 +        xScale:  {get: function(){return x;}, set: function(_){x=_;}},
  6.4042 +        yScale:  {get: function(){return y;}, set: function(_){y=_;}},
  6.4043 +        xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.4044 +        yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.4045 +        xRange:  {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.4046 +        yRange:  {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.4047 +        valueFormat:    {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
  6.4048 +        id:          {get: function(){return id;}, set: function(_){id=_;}},
  6.4049 +        rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},
  6.4050 +
  6.4051 +        // options that require extra logic in the setter
  6.4052 +        margin: {get: function(){return margin;}, set: function(_){
  6.4053 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.4054 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.4055 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.4056 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.4057 +        }},
  6.4058 +        color:  {get: function(){return color;}, set: function(_){
  6.4059 +            color = nv.utils.getColor(_);
  6.4060 +        }},
  6.4061 +        duration: {get: function(){return duration;}, set: function(_){
  6.4062 +            duration = _;
  6.4063 +            renderWatch.reset(duration);
  6.4064 +        }}
  6.4065 +    });
  6.4066 +
  6.4067 +    nv.utils.initOptions(chart);
  6.4068 +
  6.4069 +    return chart;
  6.4070 +};
  6.4071 +
  6.4072 +nv.models.discreteBarChart = function() {
  6.4073 +    "use strict";
  6.4074 +
  6.4075 +    //============================================================
  6.4076 +    // Public Variables with Default Settings
  6.4077 +    //------------------------------------------------------------
  6.4078 +
  6.4079 +    var discretebar = nv.models.discreteBar()
  6.4080 +        , xAxis = nv.models.axis()
  6.4081 +        , yAxis = nv.models.axis()
  6.4082 +        , tooltip = nv.models.tooltip()
  6.4083 +        ;
  6.4084 +
  6.4085 +    var margin = {top: 15, right: 10, bottom: 50, left: 60}
  6.4086 +        , width = null
  6.4087 +        , height = null
  6.4088 +        , color = nv.utils.getColor()
  6.4089 +        , showXAxis = true
  6.4090 +        , showYAxis = true
  6.4091 +        , rightAlignYAxis = false
  6.4092 +        , staggerLabels = false
  6.4093 +        , x
  6.4094 +        , y
  6.4095 +        , noData = null
  6.4096 +        , dispatch = d3.dispatch('beforeUpdate','renderEnd')
  6.4097 +        , duration = 250
  6.4098 +        ;
  6.4099 +
  6.4100 +    xAxis
  6.4101 +        .orient('bottom')
  6.4102 +        .showMaxMin(false)
  6.4103 +        .tickFormat(function(d) { return d })
  6.4104 +    ;
  6.4105 +    yAxis
  6.4106 +        .orient((rightAlignYAxis) ? 'right' : 'left')
  6.4107 +        .tickFormat(d3.format(',.1f'))
  6.4108 +    ;
  6.4109 +
  6.4110 +    tooltip
  6.4111 +        .duration(0)
  6.4112 +        .headerEnabled(false)
  6.4113 +        .valueFormatter(function(d, i) {
  6.4114 +            return yAxis.tickFormat()(d, i);
  6.4115 +        })
  6.4116 +        .keyFormatter(function(d, i) {
  6.4117 +            return xAxis.tickFormat()(d, i);
  6.4118 +        });
  6.4119 +
  6.4120 +    //============================================================
  6.4121 +    // Private Variables
  6.4122 +    //------------------------------------------------------------
  6.4123 +
  6.4124 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.4125 +
  6.4126 +    function chart(selection) {
  6.4127 +        renderWatch.reset();
  6.4128 +        renderWatch.models(discretebar);
  6.4129 +        if (showXAxis) renderWatch.models(xAxis);
  6.4130 +        if (showYAxis) renderWatch.models(yAxis);
  6.4131 +
  6.4132 +        selection.each(function(data) {
  6.4133 +            var container = d3.select(this),
  6.4134 +                that = this;
  6.4135 +            nv.utils.initSVG(container);
  6.4136 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.4137 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.4138 +
  6.4139 +            chart.update = function() {
  6.4140 +                dispatch.beforeUpdate();
  6.4141 +                container.transition().duration(duration).call(chart);
  6.4142 +            };
  6.4143 +            chart.container = this;
  6.4144 +
  6.4145 +            // Display No Data message if there's nothing to show.
  6.4146 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.4147 +                nv.utils.noData(chart, container);
  6.4148 +                return chart;
  6.4149 +            } else {
  6.4150 +                container.selectAll('.nv-noData').remove();
  6.4151 +            }
  6.4152 +
  6.4153 +            // Setup Scales
  6.4154 +            x = discretebar.xScale();
  6.4155 +            y = discretebar.yScale().clamp(true);
  6.4156 +
  6.4157 +            // Setup containers and skeleton of chart
  6.4158 +            var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]);
  6.4159 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g');
  6.4160 +            var defsEnter = gEnter.append('defs');
  6.4161 +            var g = wrap.select('g');
  6.4162 +
  6.4163 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.4164 +            gEnter.append('g').attr('class', 'nv-y nv-axis')
  6.4165 +                .append('g').attr('class', 'nv-zeroLine')
  6.4166 +                .append('line');
  6.4167 +
  6.4168 +            gEnter.append('g').attr('class', 'nv-barsWrap');
  6.4169 +
  6.4170 +            g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.4171 +
  6.4172 +            if (rightAlignYAxis) {
  6.4173 +                g.select(".nv-y.nv-axis")
  6.4174 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.4175 +            }
  6.4176 +
  6.4177 +            // Main Chart Component(s)
  6.4178 +            discretebar
  6.4179 +                .width(availableWidth)
  6.4180 +                .height(availableHeight);
  6.4181 +
  6.4182 +            var barsWrap = g.select('.nv-barsWrap')
  6.4183 +                .datum(data.filter(function(d) { return !d.disabled }));
  6.4184 +
  6.4185 +            barsWrap.transition().call(discretebar);
  6.4186 +
  6.4187 +
  6.4188 +            defsEnter.append('clipPath')
  6.4189 +                .attr('id', 'nv-x-label-clip-' + discretebar.id())
  6.4190 +                .append('rect');
  6.4191 +
  6.4192 +            g.select('#nv-x-label-clip-' + discretebar.id() + ' rect')
  6.4193 +                .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))
  6.4194 +                .attr('height', 16)
  6.4195 +                .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));
  6.4196 +
  6.4197 +            // Setup Axes
  6.4198 +            if (showXAxis) {
  6.4199 +                xAxis
  6.4200 +                    .scale(x)
  6.4201 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.4202 +                    .tickSize(-availableHeight, 0);
  6.4203 +
  6.4204 +                g.select('.nv-x.nv-axis')
  6.4205 +                    .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')');
  6.4206 +                g.select('.nv-x.nv-axis').call(xAxis);
  6.4207 +
  6.4208 +                var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
  6.4209 +                if (staggerLabels) {
  6.4210 +                    xTicks
  6.4211 +                        .selectAll('text')
  6.4212 +                        .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
  6.4213 +                }
  6.4214 +            }
  6.4215 +
  6.4216 +            if (showYAxis) {
  6.4217 +                yAxis
  6.4218 +                    .scale(y)
  6.4219 +                    ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.4220 +                    .tickSize( -availableWidth, 0);
  6.4221 +
  6.4222 +                g.select('.nv-y.nv-axis').call(yAxis);
  6.4223 +            }
  6.4224 +
  6.4225 +            // Zero line
  6.4226 +            g.select(".nv-zeroLine line")
  6.4227 +                .attr("x1",0)
  6.4228 +                .attr("x2",availableWidth)
  6.4229 +                .attr("y1", y(0))
  6.4230 +                .attr("y2", y(0))
  6.4231 +            ;
  6.4232 +        });
  6.4233 +
  6.4234 +        renderWatch.renderEnd('discreteBar chart immediate');
  6.4235 +        return chart;
  6.4236 +    }
  6.4237 +
  6.4238 +    //============================================================
  6.4239 +    // Event Handling/Dispatching (out of chart's scope)
  6.4240 +    //------------------------------------------------------------
  6.4241 +
  6.4242 +    discretebar.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.4243 +        evt['series'] = {
  6.4244 +            key: chart.x()(evt.data),
  6.4245 +            value: chart.y()(evt.data),
  6.4246 +            color: evt.color
  6.4247 +        };
  6.4248 +        tooltip.data(evt).hidden(false);
  6.4249 +    });
  6.4250 +
  6.4251 +    discretebar.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.4252 +        tooltip.hidden(true);
  6.4253 +    });
  6.4254 +
  6.4255 +    discretebar.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.4256 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.4257 +    });
  6.4258 +
  6.4259 +    //============================================================
  6.4260 +    // Expose Public Variables
  6.4261 +    //------------------------------------------------------------
  6.4262 +
  6.4263 +    chart.dispatch = dispatch;
  6.4264 +    chart.discretebar = discretebar;
  6.4265 +    chart.xAxis = xAxis;
  6.4266 +    chart.yAxis = yAxis;
  6.4267 +    chart.tooltip = tooltip;
  6.4268 +
  6.4269 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.4270 +
  6.4271 +    chart._options = Object.create({}, {
  6.4272 +        // simple options, just get/set the necessary values
  6.4273 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.4274 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.4275 +        staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
  6.4276 +        showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.4277 +        showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.4278 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.4279 +
  6.4280 +        // deprecated options
  6.4281 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.4282 +            // deprecated after 1.7.1
  6.4283 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.4284 +            tooltip.enabled(!!_);
  6.4285 +        }},
  6.4286 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.4287 +            // deprecated after 1.7.1
  6.4288 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.4289 +            tooltip.contentGenerator(_);
  6.4290 +        }},
  6.4291 +
  6.4292 +        // options that require extra logic in the setter
  6.4293 +        margin: {get: function(){return margin;}, set: function(_){
  6.4294 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.4295 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.4296 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.4297 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.4298 +        }},
  6.4299 +        duration: {get: function(){return duration;}, set: function(_){
  6.4300 +            duration = _;
  6.4301 +            renderWatch.reset(duration);
  6.4302 +            discretebar.duration(duration);
  6.4303 +            xAxis.duration(duration);
  6.4304 +            yAxis.duration(duration);
  6.4305 +        }},
  6.4306 +        color:  {get: function(){return color;}, set: function(_){
  6.4307 +            color = nv.utils.getColor(_);
  6.4308 +            discretebar.color(color);
  6.4309 +        }},
  6.4310 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.4311 +            rightAlignYAxis = _;
  6.4312 +            yAxis.orient( (_) ? 'right' : 'left');
  6.4313 +        }}
  6.4314 +    });
  6.4315 +
  6.4316 +    nv.utils.inheritOptions(chart, discretebar);
  6.4317 +    nv.utils.initOptions(chart);
  6.4318 +
  6.4319 +    return chart;
  6.4320 +}
  6.4321 +
  6.4322 +nv.models.distribution = function() {
  6.4323 +    "use strict";
  6.4324 +    //============================================================
  6.4325 +    // Public Variables with Default Settings
  6.4326 +    //------------------------------------------------------------
  6.4327 +
  6.4328 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.4329 +        , width = 400 //technically width or height depending on x or y....
  6.4330 +        , size = 8
  6.4331 +        , axis = 'x' // 'x' or 'y'... horizontal or vertical
  6.4332 +        , getData = function(d) { return d[axis] }  // defaults d.x or d.y
  6.4333 +        , color = nv.utils.defaultColor()
  6.4334 +        , scale = d3.scale.linear()
  6.4335 +        , domain
  6.4336 +        , duration = 250
  6.4337 +        , dispatch = d3.dispatch('renderEnd')
  6.4338 +        ;
  6.4339 +
  6.4340 +    //============================================================
  6.4341 +
  6.4342 +
  6.4343 +    //============================================================
  6.4344 +    // Private Variables
  6.4345 +    //------------------------------------------------------------
  6.4346 +
  6.4347 +    var scale0;
  6.4348 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.4349 +
  6.4350 +    //============================================================
  6.4351 +
  6.4352 +
  6.4353 +    function chart(selection) {
  6.4354 +        renderWatch.reset();
  6.4355 +        selection.each(function(data) {
  6.4356 +            var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom),
  6.4357 +                naxis = axis == 'x' ? 'y' : 'x',
  6.4358 +                container = d3.select(this);
  6.4359 +            nv.utils.initSVG(container);
  6.4360 +
  6.4361 +            //------------------------------------------------------------
  6.4362 +            // Setup Scales
  6.4363 +
  6.4364 +            scale0 = scale0 || scale;
  6.4365 +
  6.4366 +            //------------------------------------------------------------
  6.4367 +
  6.4368 +
  6.4369 +            //------------------------------------------------------------
  6.4370 +            // Setup containers and skeleton of chart
  6.4371 +
  6.4372 +            var wrap = container.selectAll('g.nv-distribution').data([data]);
  6.4373 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution');
  6.4374 +            var gEnter = wrapEnter.append('g');
  6.4375 +            var g = wrap.select('g');
  6.4376 +
  6.4377 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
  6.4378 +
  6.4379 +            //------------------------------------------------------------
  6.4380 +
  6.4381 +
  6.4382 +            var distWrap = g.selectAll('g.nv-dist')
  6.4383 +                .data(function(d) { return d }, function(d) { return d.key });
  6.4384 +
  6.4385 +            distWrap.enter().append('g');
  6.4386 +            distWrap
  6.4387 +                .attr('class', function(d,i) { return 'nv-dist nv-series-' + i })
  6.4388 +                .style('stroke', function(d,i) { return color(d, i) });
  6.4389 +
  6.4390 +            var dist = distWrap.selectAll('line.nv-dist' + axis)
  6.4391 +                .data(function(d) { return d.values })
  6.4392 +            dist.enter().append('line')
  6.4393 +                .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) })
  6.4394 +                .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) })
  6.4395 +            renderWatch.transition(distWrap.exit().selectAll('line.nv-dist' + axis), 'dist exit')
  6.4396 +                // .transition()
  6.4397 +                .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
  6.4398 +                .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
  6.4399 +                .style('stroke-opacity', 0)
  6.4400 +                .remove();
  6.4401 +            dist
  6.4402 +                .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i })
  6.4403 +                .attr(naxis + '1', 0)
  6.4404 +                .attr(naxis + '2', size);
  6.4405 +            renderWatch.transition(dist, 'dist')
  6.4406 +                // .transition()
  6.4407 +                .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
  6.4408 +                .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
  6.4409 +
  6.4410 +
  6.4411 +            scale0 = scale.copy();
  6.4412 +
  6.4413 +        });
  6.4414 +        renderWatch.renderEnd('distribution immediate');
  6.4415 +        return chart;
  6.4416 +    }
  6.4417 +
  6.4418 +
  6.4419 +    //============================================================
  6.4420 +    // Expose Public Variables
  6.4421 +    //------------------------------------------------------------
  6.4422 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.4423 +    chart.dispatch = dispatch;
  6.4424 +
  6.4425 +    chart.margin = function(_) {
  6.4426 +        if (!arguments.length) return margin;
  6.4427 +        margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
  6.4428 +        margin.right  = typeof _.right  != 'undefined' ? _.right  : margin.right;
  6.4429 +        margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
  6.4430 +        margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
  6.4431 +        return chart;
  6.4432 +    };
  6.4433 +
  6.4434 +    chart.width = function(_) {
  6.4435 +        if (!arguments.length) return width;
  6.4436 +        width = _;
  6.4437 +        return chart;
  6.4438 +    };
  6.4439 +
  6.4440 +    chart.axis = function(_) {
  6.4441 +        if (!arguments.length) return axis;
  6.4442 +        axis = _;
  6.4443 +        return chart;
  6.4444 +    };
  6.4445 +
  6.4446 +    chart.size = function(_) {
  6.4447 +        if (!arguments.length) return size;
  6.4448 +        size = _;
  6.4449 +        return chart;
  6.4450 +    };
  6.4451 +
  6.4452 +    chart.getData = function(_) {
  6.4453 +        if (!arguments.length) return getData;
  6.4454 +        getData = d3.functor(_);
  6.4455 +        return chart;
  6.4456 +    };
  6.4457 +
  6.4458 +    chart.scale = function(_) {
  6.4459 +        if (!arguments.length) return scale;
  6.4460 +        scale = _;
  6.4461 +        return chart;
  6.4462 +    };
  6.4463 +
  6.4464 +    chart.color = function(_) {
  6.4465 +        if (!arguments.length) return color;
  6.4466 +        color = nv.utils.getColor(_);
  6.4467 +        return chart;
  6.4468 +    };
  6.4469 +
  6.4470 +    chart.duration = function(_) {
  6.4471 +        if (!arguments.length) return duration;
  6.4472 +        duration = _;
  6.4473 +        renderWatch.reset(duration);
  6.4474 +        return chart;
  6.4475 +    };
  6.4476 +    //============================================================
  6.4477 +
  6.4478 +
  6.4479 +    return chart;
  6.4480 +}
  6.4481 +nv.models.furiousLegend = function() {
  6.4482 +    "use strict";
  6.4483 +
  6.4484 +    //============================================================
  6.4485 +    // Public Variables with Default Settings
  6.4486 +    //------------------------------------------------------------
  6.4487 +
  6.4488 +    var margin = {top: 5, right: 0, bottom: 5, left: 0}
  6.4489 +        , width = 400
  6.4490 +        , height = 20
  6.4491 +        , getKey = function(d) { return d.key }
  6.4492 +        , color = nv.utils.getColor()
  6.4493 +        , align = true
  6.4494 +        , padding = 28 //define how much space between legend items. - recommend 32 for furious version
  6.4495 +        , rightAlign = true
  6.4496 +        , updateState = true   //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
  6.4497 +        , radioButtonMode = false   //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)
  6.4498 +        , expanded = false
  6.4499 +        , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
  6.4500 +        , vers = 'classic' //Options are "classic" and "furious"
  6.4501 +        ;
  6.4502 +
  6.4503 +    function chart(selection) {
  6.4504 +        selection.each(function(data) {
  6.4505 +            var availableWidth = width - margin.left - margin.right,
  6.4506 +                container = d3.select(this);
  6.4507 +            nv.utils.initSVG(container);
  6.4508 +
  6.4509 +            // Setup containers and skeleton of chart
  6.4510 +            var wrap = container.selectAll('g.nv-legend').data([data]);
  6.4511 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');
  6.4512 +            var g = wrap.select('g');
  6.4513 +
  6.4514 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.4515 +
  6.4516 +            var series = g.selectAll('.nv-series')
  6.4517 +                .data(function(d) {
  6.4518 +                    if(vers != 'furious') return d;
  6.4519 +
  6.4520 +                    return d.filter(function(n) {
  6.4521 +                        return expanded ? true : !n.disengaged;
  6.4522 +                    });
  6.4523 +                });
  6.4524 +            var seriesEnter = series.enter().append('g').attr('class', 'nv-series')
  6.4525 +
  6.4526 +            var seriesShape;
  6.4527 +
  6.4528 +            if(vers == 'classic') {
  6.4529 +                seriesEnter.append('circle')
  6.4530 +                    .style('stroke-width', 2)
  6.4531 +                    .attr('class','nv-legend-symbol')
  6.4532 +                    .attr('r', 5);
  6.4533 +
  6.4534 +                seriesShape = series.select('circle');
  6.4535 +            } else if (vers == 'furious') {
  6.4536 +                seriesEnter.append('rect')
  6.4537 +                    .style('stroke-width', 2)
  6.4538 +                    .attr('class','nv-legend-symbol')
  6.4539 +                    .attr('rx', 3)
  6.4540 +                    .attr('ry', 3);
  6.4541 +
  6.4542 +                seriesShape = series.select('rect');
  6.4543 +
  6.4544 +                seriesEnter.append('g')
  6.4545 +                    .attr('class', 'nv-check-box')
  6.4546 +                    .property('innerHTML','<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>')
  6.4547 +                    .attr('transform', 'translate(-10,-8)scale(0.5)');
  6.4548 +
  6.4549 +                var seriesCheckbox = series.select('.nv-check-box');
  6.4550 +
  6.4551 +                seriesCheckbox.each(function(d,i) {
  6.4552 +                    d3.select(this).selectAll('path')
  6.4553 +                        .attr('stroke', setTextColor(d,i));
  6.4554 +                });
  6.4555 +            }
  6.4556 +
  6.4557 +            seriesEnter.append('text')
  6.4558 +                .attr('text-anchor', 'start')
  6.4559 +                .attr('class','nv-legend-text')
  6.4560 +                .attr('dy', '.32em')
  6.4561 +                .attr('dx', '8');
  6.4562 +
  6.4563 +            var seriesText = series.select('text.nv-legend-text');
  6.4564 +
  6.4565 +            series
  6.4566 +                .on('mouseover', function(d,i) {
  6.4567 +                    dispatch.legendMouseover(d,i);  //TODO: Make consistent with other event objects
  6.4568 +                })
  6.4569 +                .on('mouseout', function(d,i) {
  6.4570 +                    dispatch.legendMouseout(d,i);
  6.4571 +                })
  6.4572 +                .on('click', function(d,i) {
  6.4573 +                    dispatch.legendClick(d,i);
  6.4574 +                    // make sure we re-get data in case it was modified
  6.4575 +                    var data = series.data();
  6.4576 +                    if (updateState) {
  6.4577 +                        if(vers =='classic') {
  6.4578 +                            if (radioButtonMode) {
  6.4579 +                                //Radio button mode: set every series to disabled,
  6.4580 +                                //  and enable the clicked series.
  6.4581 +                                data.forEach(function(series) { series.disabled = true});
  6.4582 +                                d.disabled = false;
  6.4583 +                            }
  6.4584 +                            else {
  6.4585 +                                d.disabled = !d.disabled;
  6.4586 +                                if (data.every(function(series) { return series.disabled})) {
  6.4587 +                                    //the default behavior of NVD3 legends is, if every single series
  6.4588 +                                    // is disabled, turn all series' back on.
  6.4589 +                                    data.forEach(function(series) { series.disabled = false});
  6.4590 +                                }
  6.4591 +                            }
  6.4592 +                        } else if(vers == 'furious') {
  6.4593 +                            if(expanded) {
  6.4594 +                                d.disengaged = !d.disengaged;
  6.4595 +                                d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;
  6.4596 +                                d.disabled = d.disengaged || d.userDisabled;
  6.4597 +                            } else if (!expanded) {
  6.4598 +                                d.disabled = !d.disabled;
  6.4599 +                                d.userDisabled = d.disabled;
  6.4600 +                                var engaged = data.filter(function(d) { return !d.disengaged; });
  6.4601 +                                if (engaged.every(function(series) { return series.userDisabled })) {
  6.4602 +                                    //the default behavior of NVD3 legends is, if every single series
  6.4603 +                                    // is disabled, turn all series' back on.
  6.4604 +                                    data.forEach(function(series) {
  6.4605 +                                        series.disabled = series.userDisabled = false;
  6.4606 +                                    });
  6.4607 +                                }
  6.4608 +                            }
  6.4609 +                        }
  6.4610 +                        dispatch.stateChange({
  6.4611 +                            disabled: data.map(function(d) { return !!d.disabled }),
  6.4612 +                            disengaged: data.map(function(d) { return !!d.disengaged })
  6.4613 +                        });
  6.4614 +
  6.4615 +                    }
  6.4616 +                })
  6.4617 +                .on('dblclick', function(d,i) {
  6.4618 +                    if(vers == 'furious' && expanded) return;
  6.4619 +                    dispatch.legendDblclick(d,i);
  6.4620 +                    if (updateState) {
  6.4621 +                        // make sure we re-get data in case it was modified
  6.4622 +                        var data = series.data();
  6.4623 +                        //the default behavior of NVD3 legends, when double clicking one,
  6.4624 +                        // is to set all other series' to false, and make the double clicked series enabled.
  6.4625 +                        data.forEach(function(series) {
  6.4626 +                            series.disabled = true;
  6.4627 +                            if(vers == 'furious') series.userDisabled = series.disabled;
  6.4628 +                        });
  6.4629 +                        d.disabled = false;
  6.4630 +                        if(vers == 'furious') d.userDisabled = d.disabled;
  6.4631 +                        dispatch.stateChange({
  6.4632 +                            disabled: data.map(function(d) { return !!d.disabled })
  6.4633 +                        });
  6.4634 +                    }
  6.4635 +                });
  6.4636 +
  6.4637 +            series.classed('nv-disabled', function(d) { return d.userDisabled });
  6.4638 +            series.exit().remove();
  6.4639 +
  6.4640 +            seriesText
  6.4641 +                .attr('fill', setTextColor)
  6.4642 +                .text(getKey);
  6.4643 +
  6.4644 +            //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
  6.4645 +            // NEW ALIGNING CODE, TODO: clean up
  6.4646 +
  6.4647 +            var versPadding;
  6.4648 +            switch(vers) {
  6.4649 +                case 'furious' :
  6.4650 +                    versPadding = 23;
  6.4651 +                    break;
  6.4652 +                case 'classic' :
  6.4653 +                    versPadding = 20;
  6.4654 +            }
  6.4655 +
  6.4656 +            if (align) {
  6.4657 +
  6.4658 +                var seriesWidths = [];
  6.4659 +                series.each(function(d,i) {
  6.4660 +                    var legendText = d3.select(this).select('text');
  6.4661 +                    var nodeTextLength;
  6.4662 +                    try {
  6.4663 +                        nodeTextLength = legendText.node().getComputedTextLength();
  6.4664 +                        // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead
  6.4665 +                        if(nodeTextLength <= 0) throw Error();
  6.4666 +                    }
  6.4667 +                    catch(e) {
  6.4668 +                        nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
  6.4669 +                    }
  6.4670 +
  6.4671 +                    seriesWidths.push(nodeTextLength + padding);
  6.4672 +                });
  6.4673 +
  6.4674 +                var seriesPerRow = 0;
  6.4675 +                var legendWidth = 0;
  6.4676 +                var columnWidths = [];
  6.4677 +
  6.4678 +                while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {
  6.4679 +                    columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];
  6.4680 +                    legendWidth += seriesWidths[seriesPerRow++];
  6.4681 +                }
  6.4682 +                if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row
  6.4683 +
  6.4684 +                while ( legendWidth > availableWidth && seriesPerRow > 1 ) {
  6.4685 +                    columnWidths = [];
  6.4686 +                    seriesPerRow--;
  6.4687 +
  6.4688 +                    for (var k = 0; k < seriesWidths.length; k++) {
  6.4689 +                        if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )
  6.4690 +                            columnWidths[k % seriesPerRow] = seriesWidths[k];
  6.4691 +                    }
  6.4692 +
  6.4693 +                    legendWidth = columnWidths.reduce(function(prev, cur, index, array) {
  6.4694 +                        return prev + cur;
  6.4695 +                    });
  6.4696 +                }
  6.4697 +
  6.4698 +                var xPositions = [];
  6.4699 +                for (var i = 0, curX = 0; i < seriesPerRow; i++) {
  6.4700 +                    xPositions[i] = curX;
  6.4701 +                    curX += columnWidths[i];
  6.4702 +                }
  6.4703 +
  6.4704 +                series
  6.4705 +                    .attr('transform', function(d, i) {
  6.4706 +                        return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';
  6.4707 +                    });
  6.4708 +
  6.4709 +                //position legend as far right as possible within the total width
  6.4710 +                if (rightAlign) {
  6.4711 +                    g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');
  6.4712 +                }
  6.4713 +                else {
  6.4714 +                    g.attr('transform', 'translate(0' + ',' + margin.top + ')');
  6.4715 +                }
  6.4716 +
  6.4717 +                height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);
  6.4718 +
  6.4719 +            } else {
  6.4720 +
  6.4721 +                var ypos = 5,
  6.4722 +                    newxpos = 5,
  6.4723 +                    maxwidth = 0,
  6.4724 +                    xpos;
  6.4725 +                series
  6.4726 +                    .attr('transform', function(d, i) {
  6.4727 +                        var length = d3.select(this).select('text').node().getComputedTextLength() + padding;
  6.4728 +                        xpos = newxpos;
  6.4729 +
  6.4730 +                        if (width < margin.left + margin.right + xpos + length) {
  6.4731 +                            newxpos = xpos = 5;
  6.4732 +                            ypos += versPadding;
  6.4733 +                        }
  6.4734 +
  6.4735 +                        newxpos += length;
  6.4736 +                        if (newxpos > maxwidth) maxwidth = newxpos;
  6.4737 +
  6.4738 +                        return 'translate(' + xpos + ',' + ypos + ')';
  6.4739 +                    });
  6.4740 +
  6.4741 +                //position legend as far right as possible within the total width
  6.4742 +                g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');
  6.4743 +
  6.4744 +                height = margin.top + margin.bottom + ypos + 15;
  6.4745 +            }
  6.4746 +
  6.4747 +            if(vers == 'furious') {
  6.4748 +                // Size rectangles after text is placed
  6.4749 +                seriesShape
  6.4750 +                    .attr('width', function(d,i) {
  6.4751 +                        return seriesText[0][i].getComputedTextLength() + 27;
  6.4752 +                    })
  6.4753 +                    .attr('height', 18)
  6.4754 +                    .attr('y', -9)
  6.4755 +                    .attr('x', -15)
  6.4756 +            }
  6.4757 +
  6.4758 +            seriesShape
  6.4759 +                .style('fill', setBGColor)
  6.4760 +                .style('stroke', function(d,i) { return d.color || color(d, i) });
  6.4761 +        });
  6.4762 +
  6.4763 +        function setTextColor(d,i) {
  6.4764 +            if(vers != 'furious') return '#000';
  6.4765 +            if(expanded) {
  6.4766 +                return d.disengaged ? color(d,i) : '#fff';
  6.4767 +            } else if (!expanded) {
  6.4768 +                return !!d.disabled ? color(d,i) : '#fff';
  6.4769 +            }
  6.4770 +        }
  6.4771 +
  6.4772 +        function setBGColor(d,i) {
  6.4773 +            if(expanded && vers == 'furious') {
  6.4774 +                return d.disengaged ? '#fff' : color(d,i);
  6.4775 +            } else {
  6.4776 +                return !!d.disabled ? '#fff' : color(d,i);
  6.4777 +            }
  6.4778 +        }
  6.4779 +
  6.4780 +        return chart;
  6.4781 +    }
  6.4782 +
  6.4783 +    //============================================================
  6.4784 +    // Expose Public Variables
  6.4785 +    //------------------------------------------------------------
  6.4786 +
  6.4787 +    chart.dispatch = dispatch;
  6.4788 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.4789 +
  6.4790 +    chart._options = Object.create({}, {
  6.4791 +        // simple options, just get/set the necessary values
  6.4792 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.4793 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.4794 +        key:        {get: function(){return getKey;}, set: function(_){getKey=_;}},
  6.4795 +        align:      {get: function(){return align;}, set: function(_){align=_;}},
  6.4796 +        rightAlign:    {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
  6.4797 +        padding:       {get: function(){return padding;}, set: function(_){padding=_;}},
  6.4798 +        updateState:   {get: function(){return updateState;}, set: function(_){updateState=_;}},
  6.4799 +        radioButtonMode:    {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
  6.4800 +        expanded:   {get: function(){return expanded;}, set: function(_){expanded=_;}},
  6.4801 +        vers:   {get: function(){return vers;}, set: function(_){vers=_;}},
  6.4802 +
  6.4803 +        // options that require extra logic in the setter
  6.4804 +        margin: {get: function(){return margin;}, set: function(_){
  6.4805 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.4806 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.4807 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.4808 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.4809 +        }},
  6.4810 +        color:  {get: function(){return color;}, set: function(_){
  6.4811 +            color = nv.utils.getColor(_);
  6.4812 +        }}
  6.4813 +    });
  6.4814 +
  6.4815 +    nv.utils.initOptions(chart);
  6.4816 +
  6.4817 +    return chart;
  6.4818 +};
  6.4819 +//TODO: consider deprecating and using multibar with single series for this
  6.4820 +nv.models.historicalBar = function() {
  6.4821 +    "use strict";
  6.4822 +
  6.4823 +    //============================================================
  6.4824 +    // Public Variables with Default Settings
  6.4825 +    //------------------------------------------------------------
  6.4826 +
  6.4827 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.4828 +        , width = null
  6.4829 +        , height = null
  6.4830 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.4831 +        , container = null
  6.4832 +        , x = d3.scale.linear()
  6.4833 +        , y = d3.scale.linear()
  6.4834 +        , getX = function(d) { return d.x }
  6.4835 +        , getY = function(d) { return d.y }
  6.4836 +        , forceX = []
  6.4837 +        , forceY = [0]
  6.4838 +        , padData = false
  6.4839 +        , clipEdge = true
  6.4840 +        , color = nv.utils.defaultColor()
  6.4841 +        , xDomain
  6.4842 +        , yDomain
  6.4843 +        , xRange
  6.4844 +        , yRange
  6.4845 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
  6.4846 +        , interactive = true
  6.4847 +        ;
  6.4848 +
  6.4849 +    var renderWatch = nv.utils.renderWatch(dispatch, 0);
  6.4850 +
  6.4851 +    function chart(selection) {
  6.4852 +        selection.each(function(data) {
  6.4853 +            renderWatch.reset();
  6.4854 +
  6.4855 +            container = d3.select(this);
  6.4856 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.4857 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.4858 +
  6.4859 +            nv.utils.initSVG(container);
  6.4860 +
  6.4861 +            // Setup Scales
  6.4862 +            x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
  6.4863 +
  6.4864 +            if (padData)
  6.4865 +                x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5)  / data[0].values.length ]);
  6.4866 +            else
  6.4867 +                x.range(xRange || [0, availableWidth]);
  6.4868 +
  6.4869 +            y.domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
  6.4870 +                .range(yRange || [availableHeight, 0]);
  6.4871 +
  6.4872 +            // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
  6.4873 +            if (x.domain()[0] === x.domain()[1])
  6.4874 +                x.domain()[0] ?
  6.4875 +                    x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
  6.4876 +                    : x.domain([-1,1]);
  6.4877 +
  6.4878 +            if (y.domain()[0] === y.domain()[1])
  6.4879 +                y.domain()[0] ?
  6.4880 +                    y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
  6.4881 +                    : y.domain([-1,1]);
  6.4882 +
  6.4883 +            // Setup containers and skeleton of chart
  6.4884 +            var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]);
  6.4885 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id);
  6.4886 +            var defsEnter = wrapEnter.append('defs');
  6.4887 +            var gEnter = wrapEnter.append('g');
  6.4888 +            var g = wrap.select('g');
  6.4889 +
  6.4890 +            gEnter.append('g').attr('class', 'nv-bars');
  6.4891 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.4892 +
  6.4893 +            container
  6.4894 +                .on('click', function(d,i) {
  6.4895 +                    dispatch.chartClick({
  6.4896 +                        data: d,
  6.4897 +                        index: i,
  6.4898 +                        pos: d3.event,
  6.4899 +                        id: id
  6.4900 +                    });
  6.4901 +                });
  6.4902 +
  6.4903 +            defsEnter.append('clipPath')
  6.4904 +                .attr('id', 'nv-chart-clip-path-' + id)
  6.4905 +                .append('rect');
  6.4906 +
  6.4907 +            wrap.select('#nv-chart-clip-path-' + id + ' rect')
  6.4908 +                .attr('width', availableWidth)
  6.4909 +                .attr('height', availableHeight);
  6.4910 +
  6.4911 +            g.attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
  6.4912 +
  6.4913 +            var bars = wrap.select('.nv-bars').selectAll('.nv-bar')
  6.4914 +                .data(function(d) { return d }, function(d,i) {return getX(d,i)});
  6.4915 +            bars.exit().remove();
  6.4916 +
  6.4917 +            bars.enter().append('rect')
  6.4918 +                .attr('x', 0 )
  6.4919 +                .attr('y', function(d,i) {  return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) })
  6.4920 +                .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) })
  6.4921 +                .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
  6.4922 +                .on('mouseover', function(d,i) {
  6.4923 +                    if (!interactive) return;
  6.4924 +                    d3.select(this).classed('hover', true);
  6.4925 +                    dispatch.elementMouseover({
  6.4926 +                        data: d,
  6.4927 +                        index: i,
  6.4928 +                        color: d3.select(this).style("fill")
  6.4929 +                    });
  6.4930 +
  6.4931 +                })
  6.4932 +                .on('mouseout', function(d,i) {
  6.4933 +                    if (!interactive) return;
  6.4934 +                    d3.select(this).classed('hover', false);
  6.4935 +                    dispatch.elementMouseout({
  6.4936 +                        data: d,
  6.4937 +                        index: i,
  6.4938 +                        color: d3.select(this).style("fill")
  6.4939 +                    });
  6.4940 +                })
  6.4941 +                .on('mousemove', function(d,i) {
  6.4942 +                    if (!interactive) return;
  6.4943 +                    dispatch.elementMousemove({
  6.4944 +                        data: d,
  6.4945 +                        index: i,
  6.4946 +                        color: d3.select(this).style("fill")
  6.4947 +                    });
  6.4948 +                })
  6.4949 +                .on('click', function(d,i) {
  6.4950 +                    if (!interactive) return;
  6.4951 +                    dispatch.elementClick({
  6.4952 +                        data: d,
  6.4953 +                        index: i,
  6.4954 +                        color: d3.select(this).style("fill")
  6.4955 +                    });
  6.4956 +                    d3.event.stopPropagation();
  6.4957 +                })
  6.4958 +                .on('dblclick', function(d,i) {
  6.4959 +                    if (!interactive) return;
  6.4960 +                    dispatch.elementDblClick({
  6.4961 +                        data: d,
  6.4962 +                        index: i,
  6.4963 +                        color: d3.select(this).style("fill")
  6.4964 +                    });
  6.4965 +                    d3.event.stopPropagation();
  6.4966 +                });
  6.4967 +
  6.4968 +            bars
  6.4969 +                .attr('fill', function(d,i) { return color(d, i); })
  6.4970 +                .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
  6.4971 +                .watchTransition(renderWatch, 'bars')
  6.4972 +                .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
  6.4973 +                //TODO: better width calculations that don't assume always uniform data spacing;w
  6.4974 +                .attr('width', (availableWidth / data[0].values.length) * .9 );
  6.4975 +
  6.4976 +            bars.watchTransition(renderWatch, 'bars')
  6.4977 +                .attr('y', function(d,i) {
  6.4978 +                    var rval = getY(d,i) < 0 ?
  6.4979 +                        y(0) :
  6.4980 +                            y(0) - y(getY(d,i)) < 1 ?
  6.4981 +                        y(0) - 1 :
  6.4982 +                        y(getY(d,i));
  6.4983 +                    return nv.utils.NaNtoZero(rval);
  6.4984 +                })
  6.4985 +                .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });
  6.4986 +
  6.4987 +        });
  6.4988 +
  6.4989 +        renderWatch.renderEnd('historicalBar immediate');
  6.4990 +        return chart;
  6.4991 +    }
  6.4992 +
  6.4993 +    //Create methods to allow outside functions to highlight a specific bar.
  6.4994 +    chart.highlightPoint = function(pointIndex, isHoverOver) {
  6.4995 +        container
  6.4996 +            .select(".nv-bars .nv-bar-0-" + pointIndex)
  6.4997 +            .classed("hover", isHoverOver)
  6.4998 +        ;
  6.4999 +    };
  6.5000 +
  6.5001 +    chart.clearHighlights = function() {
  6.5002 +        container
  6.5003 +            .select(".nv-bars .nv-bar.hover")
  6.5004 +            .classed("hover", false)
  6.5005 +        ;
  6.5006 +    };
  6.5007 +
  6.5008 +    //============================================================
  6.5009 +    // Expose Public Variables
  6.5010 +    //------------------------------------------------------------
  6.5011 +
  6.5012 +    chart.dispatch = dispatch;
  6.5013 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.5014 +
  6.5015 +    chart._options = Object.create({}, {
  6.5016 +        // simple options, just get/set the necessary values
  6.5017 +        width:   {get: function(){return width;}, set: function(_){width=_;}},
  6.5018 +        height:  {get: function(){return height;}, set: function(_){height=_;}},
  6.5019 +        forceX:  {get: function(){return forceX;}, set: function(_){forceX=_;}},
  6.5020 +        forceY:  {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.5021 +        padData: {get: function(){return padData;}, set: function(_){padData=_;}},
  6.5022 +        x:       {get: function(){return getX;}, set: function(_){getX=_;}},
  6.5023 +        y:       {get: function(){return getY;}, set: function(_){getY=_;}},
  6.5024 +        xScale:  {get: function(){return x;}, set: function(_){x=_;}},
  6.5025 +        yScale:  {get: function(){return y;}, set: function(_){y=_;}},
  6.5026 +        xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.5027 +        yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.5028 +        xRange:  {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.5029 +        yRange:  {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.5030 +        clipEdge:    {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
  6.5031 +        id:          {get: function(){return id;}, set: function(_){id=_;}},
  6.5032 +        interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
  6.5033 +
  6.5034 +        // options that require extra logic in the setter
  6.5035 +        margin: {get: function(){return margin;}, set: function(_){
  6.5036 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.5037 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.5038 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.5039 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.5040 +        }},
  6.5041 +        color:  {get: function(){return color;}, set: function(_){
  6.5042 +            color = nv.utils.getColor(_);
  6.5043 +        }}
  6.5044 +    });
  6.5045 +
  6.5046 +    nv.utils.initOptions(chart);
  6.5047 +
  6.5048 +    return chart;
  6.5049 +};
  6.5050 +
  6.5051 +nv.models.historicalBarChart = function(bar_model) {
  6.5052 +    "use strict";
  6.5053 +
  6.5054 +    //============================================================
  6.5055 +    // Public Variables with Default Settings
  6.5056 +    //------------------------------------------------------------
  6.5057 +
  6.5058 +    var bars = bar_model || nv.models.historicalBar()
  6.5059 +        , xAxis = nv.models.axis()
  6.5060 +        , yAxis = nv.models.axis()
  6.5061 +        , legend = nv.models.legend()
  6.5062 +        , interactiveLayer = nv.interactiveGuideline()
  6.5063 +        , tooltip = nv.models.tooltip()
  6.5064 +        ;
  6.5065 +
  6.5066 +
  6.5067 +    var margin = {top: 30, right: 90, bottom: 50, left: 90}
  6.5068 +        , color = nv.utils.defaultColor()
  6.5069 +        , width = null
  6.5070 +        , height = null
  6.5071 +        , showLegend = false
  6.5072 +        , showXAxis = true
  6.5073 +        , showYAxis = true
  6.5074 +        , rightAlignYAxis = false
  6.5075 +        , useInteractiveGuideline = false
  6.5076 +        , x
  6.5077 +        , y
  6.5078 +        , state = {}
  6.5079 +        , defaultState = null
  6.5080 +        , noData = null
  6.5081 +        , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd')
  6.5082 +        , transitionDuration = 250
  6.5083 +        ;
  6.5084 +
  6.5085 +    xAxis.orient('bottom').tickPadding(7);
  6.5086 +    yAxis.orient( (rightAlignYAxis) ? 'right' : 'left');
  6.5087 +    tooltip
  6.5088 +        .duration(0)
  6.5089 +        .headerEnabled(false)
  6.5090 +        .valueFormatter(function(d, i) {
  6.5091 +            return yAxis.tickFormat()(d, i);
  6.5092 +        })
  6.5093 +        .headerFormatter(function(d, i) {
  6.5094 +            return xAxis.tickFormat()(d, i);
  6.5095 +        });
  6.5096 +
  6.5097 +
  6.5098 +    //============================================================
  6.5099 +    // Private Variables
  6.5100 +    //------------------------------------------------------------
  6.5101 +
  6.5102 +    var renderWatch = nv.utils.renderWatch(dispatch, 0);
  6.5103 +
  6.5104 +    function chart(selection) {
  6.5105 +        selection.each(function(data) {
  6.5106 +            renderWatch.reset();
  6.5107 +            renderWatch.models(bars);
  6.5108 +            if (showXAxis) renderWatch.models(xAxis);
  6.5109 +            if (showYAxis) renderWatch.models(yAxis);
  6.5110 +
  6.5111 +            var container = d3.select(this),
  6.5112 +                that = this;
  6.5113 +            nv.utils.initSVG(container);
  6.5114 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.5115 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.5116 +
  6.5117 +            chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
  6.5118 +            chart.container = this;
  6.5119 +
  6.5120 +            //set state.disabled
  6.5121 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.5122 +
  6.5123 +            if (!defaultState) {
  6.5124 +                var key;
  6.5125 +                defaultState = {};
  6.5126 +                for (key in state) {
  6.5127 +                    if (state[key] instanceof Array)
  6.5128 +                        defaultState[key] = state[key].slice(0);
  6.5129 +                    else
  6.5130 +                        defaultState[key] = state[key];
  6.5131 +                }
  6.5132 +            }
  6.5133 +
  6.5134 +            // Display noData message if there's nothing to show.
  6.5135 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.5136 +                nv.utils.noData(chart, container)
  6.5137 +                return chart;
  6.5138 +            } else {
  6.5139 +                container.selectAll('.nv-noData').remove();
  6.5140 +            }
  6.5141 +
  6.5142 +            // Setup Scales
  6.5143 +            x = bars.xScale();
  6.5144 +            y = bars.yScale();
  6.5145 +
  6.5146 +            // Setup containers and skeleton of chart
  6.5147 +            var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]);
  6.5148 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g');
  6.5149 +            var g = wrap.select('g');
  6.5150 +
  6.5151 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.5152 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
  6.5153 +            gEnter.append('g').attr('class', 'nv-barsWrap');
  6.5154 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.5155 +            gEnter.append('g').attr('class', 'nv-interactive');
  6.5156 +
  6.5157 +            // Legend
  6.5158 +            if (showLegend) {
  6.5159 +                legend.width(availableWidth);
  6.5160 +
  6.5161 +                g.select('.nv-legendWrap')
  6.5162 +                    .datum(data)
  6.5163 +                    .call(legend);
  6.5164 +
  6.5165 +                if ( margin.top != legend.height()) {
  6.5166 +                    margin.top = legend.height();
  6.5167 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.5168 +                }
  6.5169 +
  6.5170 +                wrap.select('.nv-legendWrap')
  6.5171 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.5172 +            }
  6.5173 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.5174 +
  6.5175 +            if (rightAlignYAxis) {
  6.5176 +                g.select(".nv-y.nv-axis")
  6.5177 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.5178 +            }
  6.5179 +
  6.5180 +            //Set up interactive layer
  6.5181 +            if (useInteractiveGuideline) {
  6.5182 +                interactiveLayer
  6.5183 +                    .width(availableWidth)
  6.5184 +                    .height(availableHeight)
  6.5185 +                    .margin({left:margin.left, top:margin.top})
  6.5186 +                    .svgContainer(container)
  6.5187 +                    .xScale(x);
  6.5188 +                wrap.select(".nv-interactive").call(interactiveLayer);
  6.5189 +            }
  6.5190 +            bars
  6.5191 +                .width(availableWidth)
  6.5192 +                .height(availableHeight)
  6.5193 +                .color(data.map(function(d,i) {
  6.5194 +                    return d.color || color(d, i);
  6.5195 +                }).filter(function(d,i) { return !data[i].disabled }));
  6.5196 +
  6.5197 +            var barsWrap = g.select('.nv-barsWrap')
  6.5198 +                .datum(data.filter(function(d) { return !d.disabled }));
  6.5199 +            barsWrap.transition().call(bars);
  6.5200 +
  6.5201 +            // Setup Axes
  6.5202 +            if (showXAxis) {
  6.5203 +                xAxis
  6.5204 +                    .scale(x)
  6.5205 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.5206 +                    .tickSize(-availableHeight, 0);
  6.5207 +
  6.5208 +                g.select('.nv-x.nv-axis')
  6.5209 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')');
  6.5210 +                g.select('.nv-x.nv-axis')
  6.5211 +                    .transition()
  6.5212 +                    .call(xAxis);
  6.5213 +            }
  6.5214 +
  6.5215 +            if (showYAxis) {
  6.5216 +                yAxis
  6.5217 +                    .scale(y)
  6.5218 +                    ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.5219 +                    .tickSize( -availableWidth, 0);
  6.5220 +
  6.5221 +                g.select('.nv-y.nv-axis')
  6.5222 +                    .transition()
  6.5223 +                    .call(yAxis);
  6.5224 +            }
  6.5225 +
  6.5226 +            //============================================================
  6.5227 +            // Event Handling/Dispatching (in chart's scope)
  6.5228 +            //------------------------------------------------------------
  6.5229 +
  6.5230 +            interactiveLayer.dispatch.on('elementMousemove', function(e) {
  6.5231 +                bars.clearHighlights();
  6.5232 +
  6.5233 +                var singlePoint, pointIndex, pointXLocation, allData = [];
  6.5234 +                data
  6.5235 +                    .filter(function(series, i) {
  6.5236 +                        series.seriesIndex = i;
  6.5237 +                        return !series.disabled;
  6.5238 +                    })
  6.5239 +                    .forEach(function(series,i) {
  6.5240 +                        pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
  6.5241 +                        bars.highlightPoint(pointIndex,true);
  6.5242 +                        var point = series.values[pointIndex];
  6.5243 +                        if (point === undefined) return;
  6.5244 +                        if (singlePoint === undefined) singlePoint = point;
  6.5245 +                        if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
  6.5246 +                        allData.push({
  6.5247 +                            key: series.key,
  6.5248 +                            value: chart.y()(point, pointIndex),
  6.5249 +                            color: color(series,series.seriesIndex),
  6.5250 +                            data: series.values[pointIndex]
  6.5251 +                        });
  6.5252 +                    });
  6.5253 +
  6.5254 +                var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
  6.5255 +                interactiveLayer.tooltip
  6.5256 +                    .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
  6.5257 +                    .chartContainer(that.parentNode)
  6.5258 +                    .valueFormatter(function(d,i) {
  6.5259 +                        return yAxis.tickFormat()(d);
  6.5260 +                    })
  6.5261 +                    .data({
  6.5262 +                        value: xValue,
  6.5263 +                        index: pointIndex,
  6.5264 +                        series: allData
  6.5265 +                    })();
  6.5266 +
  6.5267 +                interactiveLayer.renderGuideLine(pointXLocation);
  6.5268 +
  6.5269 +            });
  6.5270 +
  6.5271 +            interactiveLayer.dispatch.on("elementMouseout",function(e) {
  6.5272 +                dispatch.tooltipHide();
  6.5273 +                bars.clearHighlights();
  6.5274 +            });
  6.5275 +
  6.5276 +            legend.dispatch.on('legendClick', function(d,i) {
  6.5277 +                d.disabled = !d.disabled;
  6.5278 +
  6.5279 +                if (!data.filter(function(d) { return !d.disabled }).length) {
  6.5280 +                    data.map(function(d) {
  6.5281 +                        d.disabled = false;
  6.5282 +                        wrap.selectAll('.nv-series').classed('disabled', false);
  6.5283 +                        return d;
  6.5284 +                    });
  6.5285 +                }
  6.5286 +
  6.5287 +                state.disabled = data.map(function(d) { return !!d.disabled });
  6.5288 +                dispatch.stateChange(state);
  6.5289 +
  6.5290 +                selection.transition().call(chart);
  6.5291 +            });
  6.5292 +
  6.5293 +            legend.dispatch.on('legendDblclick', function(d) {
  6.5294 +                //Double clicking should always enable current series, and disabled all others.
  6.5295 +                data.forEach(function(d) {
  6.5296 +                    d.disabled = true;
  6.5297 +                });
  6.5298 +                d.disabled = false;
  6.5299 +
  6.5300 +                state.disabled = data.map(function(d) { return !!d.disabled });
  6.5301 +                dispatch.stateChange(state);
  6.5302 +                chart.update();
  6.5303 +            });
  6.5304 +
  6.5305 +            dispatch.on('changeState', function(e) {
  6.5306 +                if (typeof e.disabled !== 'undefined') {
  6.5307 +                    data.forEach(function(series,i) {
  6.5308 +                        series.disabled = e.disabled[i];
  6.5309 +                    });
  6.5310 +
  6.5311 +                    state.disabled = e.disabled;
  6.5312 +                }
  6.5313 +
  6.5314 +                chart.update();
  6.5315 +            });
  6.5316 +        });
  6.5317 +
  6.5318 +        renderWatch.renderEnd('historicalBarChart immediate');
  6.5319 +        return chart;
  6.5320 +    }
  6.5321 +
  6.5322 +    //============================================================
  6.5323 +    // Event Handling/Dispatching (out of chart's scope)
  6.5324 +    //------------------------------------------------------------
  6.5325 +
  6.5326 +    bars.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.5327 +        evt['series'] = {
  6.5328 +            key: chart.x()(evt.data),
  6.5329 +            value: chart.y()(evt.data),
  6.5330 +            color: evt.color
  6.5331 +        };
  6.5332 +        tooltip.data(evt).hidden(false);
  6.5333 +    });
  6.5334 +
  6.5335 +    bars.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.5336 +        tooltip.hidden(true);
  6.5337 +    });
  6.5338 +
  6.5339 +    bars.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.5340 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.5341 +    });
  6.5342 +
  6.5343 +    //============================================================
  6.5344 +    // Expose Public Variables
  6.5345 +    //------------------------------------------------------------
  6.5346 +
  6.5347 +    // expose chart's sub-components
  6.5348 +    chart.dispatch = dispatch;
  6.5349 +    chart.bars = bars;
  6.5350 +    chart.legend = legend;
  6.5351 +    chart.xAxis = xAxis;
  6.5352 +    chart.yAxis = yAxis;
  6.5353 +    chart.interactiveLayer = interactiveLayer;
  6.5354 +    chart.tooltip = tooltip;
  6.5355 +
  6.5356 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.5357 +
  6.5358 +    chart._options = Object.create({}, {
  6.5359 +        // simple options, just get/set the necessary values
  6.5360 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.5361 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.5362 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.5363 +        showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.5364 +        showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.5365 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.5366 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.5367 +
  6.5368 +        // deprecated options
  6.5369 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.5370 +            // deprecated after 1.7.1
  6.5371 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.5372 +            tooltip.enabled(!!_);
  6.5373 +        }},
  6.5374 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.5375 +            // deprecated after 1.7.1
  6.5376 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.5377 +            tooltip.contentGenerator(_);
  6.5378 +        }},
  6.5379 +
  6.5380 +        // options that require extra logic in the setter
  6.5381 +        margin: {get: function(){return margin;}, set: function(_){
  6.5382 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.5383 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.5384 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.5385 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.5386 +        }},
  6.5387 +        color:  {get: function(){return color;}, set: function(_){
  6.5388 +            color = nv.utils.getColor(_);
  6.5389 +            legend.color(color);
  6.5390 +            bars.color(color);
  6.5391 +        }},
  6.5392 +        duration:    {get: function(){return transitionDuration;}, set: function(_){
  6.5393 +            transitionDuration=_;
  6.5394 +            renderWatch.reset(transitionDuration);
  6.5395 +            yAxis.duration(transitionDuration);
  6.5396 +            xAxis.duration(transitionDuration);
  6.5397 +        }},
  6.5398 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.5399 +            rightAlignYAxis = _;
  6.5400 +            yAxis.orient( (_) ? 'right' : 'left');
  6.5401 +        }},
  6.5402 +        useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
  6.5403 +            useInteractiveGuideline = _;
  6.5404 +            if (_ === true) {
  6.5405 +                chart.interactive(false);
  6.5406 +            }
  6.5407 +        }}
  6.5408 +    });
  6.5409 +
  6.5410 +    nv.utils.inheritOptions(chart, bars);
  6.5411 +    nv.utils.initOptions(chart);
  6.5412 +
  6.5413 +    return chart;
  6.5414 +};
  6.5415 +
  6.5416 +
  6.5417 +// ohlcChart is just a historical chart with ohlc bars and some tweaks
  6.5418 +nv.models.ohlcBarChart = function() {
  6.5419 +    var chart = nv.models.historicalBarChart(nv.models.ohlcBar());
  6.5420 +
  6.5421 +    // special default tooltip since we show multiple values per x
  6.5422 +    chart.useInteractiveGuideline(true);
  6.5423 +    chart.interactiveLayer.tooltip.contentGenerator(function(data) {
  6.5424 +        // we assume only one series exists for this chart
  6.5425 +        var d = data.series[0].data;
  6.5426 +        // match line colors as defined in nv.d3.css
  6.5427 +        var color = d.open < d.close ? "2ca02c" : "d62728";
  6.5428 +        return '' +
  6.5429 +            '<h3 style="color: #' + color + '">' + data.value + '</h3>' +
  6.5430 +            '<table>' +
  6.5431 +            '<tr><td>open:</td><td>' + chart.yAxis.tickFormat()(d.open) + '</td></tr>' +
  6.5432 +            '<tr><td>close:</td><td>' + chart.yAxis.tickFormat()(d.close) + '</td></tr>' +
  6.5433 +            '<tr><td>high</td><td>' + chart.yAxis.tickFormat()(d.high) + '</td></tr>' +
  6.5434 +            '<tr><td>low:</td><td>' + chart.yAxis.tickFormat()(d.low) + '</td></tr>' +
  6.5435 +            '</table>';
  6.5436 +    });
  6.5437 +    return chart;
  6.5438 +};
  6.5439 +
  6.5440 +// candlestickChart is just a historical chart with candlestick bars and some tweaks
  6.5441 +nv.models.candlestickBarChart = function() {
  6.5442 +    var chart = nv.models.historicalBarChart(nv.models.candlestickBar());
  6.5443 +
  6.5444 +    // special default tooltip since we show multiple values per x
  6.5445 +    chart.useInteractiveGuideline(true);
  6.5446 +    chart.interactiveLayer.tooltip.contentGenerator(function(data) {
  6.5447 +        // we assume only one series exists for this chart
  6.5448 +        var d = data.series[0].data;
  6.5449 +        // match line colors as defined in nv.d3.css
  6.5450 +        var color = d.open < d.close ? "2ca02c" : "d62728";
  6.5451 +        return '' +
  6.5452 +            '<h3 style="color: #' + color + '">' + data.value + '</h3>' +
  6.5453 +            '<table>' +
  6.5454 +            '<tr><td>open:</td><td>' + chart.yAxis.tickFormat()(d.open) + '</td></tr>' +
  6.5455 +            '<tr><td>close:</td><td>' + chart.yAxis.tickFormat()(d.close) + '</td></tr>' +
  6.5456 +            '<tr><td>high</td><td>' + chart.yAxis.tickFormat()(d.high) + '</td></tr>' +
  6.5457 +            '<tr><td>low:</td><td>' + chart.yAxis.tickFormat()(d.low) + '</td></tr>' +
  6.5458 +            '</table>';
  6.5459 +    });
  6.5460 +    return chart;
  6.5461 +};
  6.5462 +nv.models.legend = function() {
  6.5463 +    "use strict";
  6.5464 +
  6.5465 +    //============================================================
  6.5466 +    // Public Variables with Default Settings
  6.5467 +    //------------------------------------------------------------
  6.5468 +
  6.5469 +    var margin = {top: 5, right: 0, bottom: 5, left: 0}
  6.5470 +        , width = 400
  6.5471 +        , height = 20
  6.5472 +        , getKey = function(d) { return d.key }
  6.5473 +        , color = nv.utils.getColor()
  6.5474 +        , align = true
  6.5475 +        , padding = 32 //define how much space between legend items. - recommend 32 for furious version
  6.5476 +        , rightAlign = true
  6.5477 +        , updateState = true   //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
  6.5478 +        , radioButtonMode = false   //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)
  6.5479 +        , expanded = false
  6.5480 +        , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
  6.5481 +        , vers = 'classic' //Options are "classic" and "furious"
  6.5482 +        ;
  6.5483 +
  6.5484 +    function chart(selection) {
  6.5485 +        selection.each(function(data) {
  6.5486 +            var availableWidth = width - margin.left - margin.right,
  6.5487 +                container = d3.select(this);
  6.5488 +            nv.utils.initSVG(container);
  6.5489 +
  6.5490 +            // Setup containers and skeleton of chart
  6.5491 +            var wrap = container.selectAll('g.nv-legend').data([data]);
  6.5492 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');
  6.5493 +            var g = wrap.select('g');
  6.5494 +
  6.5495 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.5496 +
  6.5497 +            var series = g.selectAll('.nv-series')
  6.5498 +                .data(function(d) {
  6.5499 +                    if(vers != 'furious') return d;
  6.5500 +
  6.5501 +                    return d.filter(function(n) {
  6.5502 +                        return expanded ? true : !n.disengaged;
  6.5503 +                    });
  6.5504 +                });
  6.5505 +
  6.5506 +            var seriesEnter = series.enter().append('g').attr('class', 'nv-series');
  6.5507 +            var seriesShape;
  6.5508 +
  6.5509 +            var versPadding;
  6.5510 +            switch(vers) {
  6.5511 +                case 'furious' :
  6.5512 +                    versPadding = 23;
  6.5513 +                    break;
  6.5514 +                case 'classic' :
  6.5515 +                    versPadding = 20;
  6.5516 +            }
  6.5517 +
  6.5518 +            if(vers == 'classic') {
  6.5519 +                seriesEnter.append('circle')
  6.5520 +                    .style('stroke-width', 2)
  6.5521 +                    .attr('class','nv-legend-symbol')
  6.5522 +                    .attr('r', 5);
  6.5523 +
  6.5524 +                seriesShape = series.select('circle');
  6.5525 +            } else if (vers == 'furious') {
  6.5526 +                seriesEnter.append('rect')
  6.5527 +                    .style('stroke-width', 2)
  6.5528 +                    .attr('class','nv-legend-symbol')
  6.5529 +                    .attr('rx', 3)
  6.5530 +                    .attr('ry', 3);
  6.5531 +
  6.5532 +                seriesShape = series.select('.nv-legend-symbol');
  6.5533 +
  6.5534 +                seriesEnter.append('g')
  6.5535 +                    .attr('class', 'nv-check-box')
  6.5536 +                    .property('innerHTML','<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>')
  6.5537 +                    .attr('transform', 'translate(-10,-8)scale(0.5)');
  6.5538 +
  6.5539 +                var seriesCheckbox = series.select('.nv-check-box');
  6.5540 +
  6.5541 +                seriesCheckbox.each(function(d,i) {
  6.5542 +                    d3.select(this).selectAll('path')
  6.5543 +                        .attr('stroke', setTextColor(d,i));
  6.5544 +                });
  6.5545 +            }
  6.5546 +
  6.5547 +            seriesEnter.append('text')
  6.5548 +                .attr('text-anchor', 'start')
  6.5549 +                .attr('class','nv-legend-text')
  6.5550 +                .attr('dy', '.32em')
  6.5551 +                .attr('dx', '8');
  6.5552 +
  6.5553 +            var seriesText = series.select('text.nv-legend-text');
  6.5554 +
  6.5555 +            series
  6.5556 +                .on('mouseover', function(d,i) {
  6.5557 +                    dispatch.legendMouseover(d,i);  //TODO: Make consistent with other event objects
  6.5558 +                })
  6.5559 +                .on('mouseout', function(d,i) {
  6.5560 +                    dispatch.legendMouseout(d,i);
  6.5561 +                })
  6.5562 +                .on('click', function(d,i) {
  6.5563 +                    dispatch.legendClick(d,i);
  6.5564 +                    // make sure we re-get data in case it was modified
  6.5565 +                    var data = series.data();
  6.5566 +                    if (updateState) {
  6.5567 +                        if(vers =='classic') {
  6.5568 +                            if (radioButtonMode) {
  6.5569 +                                //Radio button mode: set every series to disabled,
  6.5570 +                                //  and enable the clicked series.
  6.5571 +                                data.forEach(function(series) { series.disabled = true});
  6.5572 +                                d.disabled = false;
  6.5573 +                            }
  6.5574 +                            else {
  6.5575 +                                d.disabled = !d.disabled;
  6.5576 +                                if (data.every(function(series) { return series.disabled})) {
  6.5577 +                                    //the default behavior of NVD3 legends is, if every single series
  6.5578 +                                    // is disabled, turn all series' back on.
  6.5579 +                                    data.forEach(function(series) { series.disabled = false});
  6.5580 +                                }
  6.5581 +                            }
  6.5582 +                        } else if(vers == 'furious') {
  6.5583 +                            if(expanded) {
  6.5584 +                                d.disengaged = !d.disengaged;
  6.5585 +                                d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;
  6.5586 +                                d.disabled = d.disengaged || d.userDisabled;
  6.5587 +                            } else if (!expanded) {
  6.5588 +                                d.disabled = !d.disabled;
  6.5589 +                                d.userDisabled = d.disabled;
  6.5590 +                                var engaged = data.filter(function(d) { return !d.disengaged; });
  6.5591 +                                if (engaged.every(function(series) { return series.userDisabled })) {
  6.5592 +                                    //the default behavior of NVD3 legends is, if every single series
  6.5593 +                                    // is disabled, turn all series' back on.
  6.5594 +                                    data.forEach(function(series) {
  6.5595 +                                        series.disabled = series.userDisabled = false;
  6.5596 +                                    });
  6.5597 +                                }
  6.5598 +                            }
  6.5599 +                        }
  6.5600 +                        dispatch.stateChange({
  6.5601 +                            disabled: data.map(function(d) { return !!d.disabled }),
  6.5602 +                            disengaged: data.map(function(d) { return !!d.disengaged })
  6.5603 +                        });
  6.5604 +
  6.5605 +                    }
  6.5606 +                })
  6.5607 +                .on('dblclick', function(d,i) {
  6.5608 +                    if(vers == 'furious' && expanded) return;
  6.5609 +                    dispatch.legendDblclick(d,i);
  6.5610 +                    if (updateState) {
  6.5611 +                        // make sure we re-get data in case it was modified
  6.5612 +                        var data = series.data();
  6.5613 +                        //the default behavior of NVD3 legends, when double clicking one,
  6.5614 +                        // is to set all other series' to false, and make the double clicked series enabled.
  6.5615 +                        data.forEach(function(series) {
  6.5616 +                            series.disabled = true;
  6.5617 +                            if(vers == 'furious') series.userDisabled = series.disabled;
  6.5618 +                        });
  6.5619 +                        d.disabled = false;
  6.5620 +                        if(vers == 'furious') d.userDisabled = d.disabled;
  6.5621 +                        dispatch.stateChange({
  6.5622 +                            disabled: data.map(function(d) { return !!d.disabled })
  6.5623 +                        });
  6.5624 +                    }
  6.5625 +                });
  6.5626 +
  6.5627 +            series.classed('nv-disabled', function(d) { return d.userDisabled });
  6.5628 +            series.exit().remove();
  6.5629 +
  6.5630 +            seriesText
  6.5631 +                .attr('fill', setTextColor)
  6.5632 +                .text(getKey);
  6.5633 +
  6.5634 +            //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
  6.5635 +            // NEW ALIGNING CODE, TODO: clean up
  6.5636 +            var legendWidth = 0;
  6.5637 +            if (align) {
  6.5638 +
  6.5639 +                var seriesWidths = [];
  6.5640 +                series.each(function(d,i) {
  6.5641 +                    var legendText = d3.select(this).select('text');
  6.5642 +                    var nodeTextLength;
  6.5643 +                    try {
  6.5644 +                        nodeTextLength = legendText.node().getComputedTextLength();
  6.5645 +                        // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead
  6.5646 +                        if(nodeTextLength <= 0) throw Error();
  6.5647 +                    }
  6.5648 +                    catch(e) {
  6.5649 +                        nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
  6.5650 +                    }
  6.5651 +
  6.5652 +                    seriesWidths.push(nodeTextLength + padding);
  6.5653 +                });
  6.5654 +
  6.5655 +                var seriesPerRow = 0;
  6.5656 +                var columnWidths = [];
  6.5657 +                legendWidth = 0;
  6.5658 +
  6.5659 +                while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {
  6.5660 +                    columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];
  6.5661 +                    legendWidth += seriesWidths[seriesPerRow++];
  6.5662 +                }
  6.5663 +                if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row
  6.5664 +
  6.5665 +                while ( legendWidth > availableWidth && seriesPerRow > 1 ) {
  6.5666 +                    columnWidths = [];
  6.5667 +                    seriesPerRow--;
  6.5668 +
  6.5669 +                    for (var k = 0; k < seriesWidths.length; k++) {
  6.5670 +                        if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )
  6.5671 +                            columnWidths[k % seriesPerRow] = seriesWidths[k];
  6.5672 +                    }
  6.5673 +
  6.5674 +                    legendWidth = columnWidths.reduce(function(prev, cur, index, array) {
  6.5675 +                        return prev + cur;
  6.5676 +                    });
  6.5677 +                }
  6.5678 +
  6.5679 +                var xPositions = [];
  6.5680 +                for (var i = 0, curX = 0; i < seriesPerRow; i++) {
  6.5681 +                    xPositions[i] = curX;
  6.5682 +                    curX += columnWidths[i];
  6.5683 +                }
  6.5684 +
  6.5685 +                series
  6.5686 +                    .attr('transform', function(d, i) {
  6.5687 +                        return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';
  6.5688 +                    });
  6.5689 +
  6.5690 +                //position legend as far right as possible within the total width
  6.5691 +                if (rightAlign) {
  6.5692 +                    g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');
  6.5693 +                }
  6.5694 +                else {
  6.5695 +                    g.attr('transform', 'translate(0' + ',' + margin.top + ')');
  6.5696 +                }
  6.5697 +
  6.5698 +                height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);
  6.5699 +
  6.5700 +            } else {
  6.5701 +
  6.5702 +                var ypos = 5,
  6.5703 +                    newxpos = 5,
  6.5704 +                    maxwidth = 0,
  6.5705 +                    xpos;
  6.5706 +                series
  6.5707 +                    .attr('transform', function(d, i) {
  6.5708 +                        var length = d3.select(this).select('text').node().getComputedTextLength() + padding;
  6.5709 +                        xpos = newxpos;
  6.5710 +
  6.5711 +                        if (width < margin.left + margin.right + xpos + length) {
  6.5712 +                            newxpos = xpos = 5;
  6.5713 +                            ypos += versPadding;
  6.5714 +                        }
  6.5715 +
  6.5716 +                        newxpos += length;
  6.5717 +                        if (newxpos > maxwidth) maxwidth = newxpos;
  6.5718 +
  6.5719 +                        if(legendWidth < xpos + maxwidth) {
  6.5720 +                            legendWidth = xpos + maxwidth;
  6.5721 +                        }
  6.5722 +                        return 'translate(' + xpos + ',' + ypos + ')';
  6.5723 +                    });
  6.5724 +
  6.5725 +                //position legend as far right as possible within the total width
  6.5726 +                g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');
  6.5727 +
  6.5728 +                height = margin.top + margin.bottom + ypos + 15;
  6.5729 +            }
  6.5730 +
  6.5731 +            if(vers == 'furious') {
  6.5732 +                // Size rectangles after text is placed
  6.5733 +                seriesShape
  6.5734 +                    .attr('width', function(d,i) {
  6.5735 +                        return seriesText[0][i].getComputedTextLength() + 27;
  6.5736 +                    })
  6.5737 +                    .attr('height', 18)
  6.5738 +                    .attr('y', -9)
  6.5739 +                    .attr('x', -15);
  6.5740 +
  6.5741 +                // The background for the expanded legend (UI)
  6.5742 +                gEnter.insert('rect',':first-child')
  6.5743 +                    .attr('class', 'nv-legend-bg')
  6.5744 +                    .attr('fill', '#eee')
  6.5745 +                    // .attr('stroke', '#444')
  6.5746 +                    .attr('opacity',0);
  6.5747 +
  6.5748 +                var seriesBG = g.select('.nv-legend-bg');
  6.5749 +
  6.5750 +                seriesBG
  6.5751 +                .transition().duration(300)
  6.5752 +                    .attr('x', -versPadding )
  6.5753 +                    .attr('width', legendWidth + versPadding - 12)
  6.5754 +                    .attr('height', height + 10)
  6.5755 +                    .attr('y', -margin.top - 10)
  6.5756 +                    .attr('opacity', expanded ? 1 : 0);
  6.5757 +
  6.5758 +
  6.5759 +            }
  6.5760 +
  6.5761 +            seriesShape
  6.5762 +                .style('fill', setBGColor)
  6.5763 +                .style('fill-opacity', setBGOpacity)
  6.5764 +                .style('stroke', setBGColor);
  6.5765 +        });
  6.5766 +
  6.5767 +        function setTextColor(d,i) {
  6.5768 +            if(vers != 'furious') return '#000';
  6.5769 +            if(expanded) {
  6.5770 +                return d.disengaged ? '#000' : '#fff';
  6.5771 +            } else if (!expanded) {
  6.5772 +                if(!d.color) d.color = color(d,i);
  6.5773 +                return !!d.disabled ? d.color : '#fff';
  6.5774 +            }
  6.5775 +        }
  6.5776 +
  6.5777 +        function setBGColor(d,i) {
  6.5778 +            if(expanded && vers == 'furious') {
  6.5779 +                return d.disengaged ? '#eee' : d.color || color(d,i);
  6.5780 +            } else {
  6.5781 +                return d.color || color(d,i);
  6.5782 +            }
  6.5783 +        }
  6.5784 +
  6.5785 +
  6.5786 +        function setBGOpacity(d,i) {
  6.5787 +            if(expanded && vers == 'furious') {
  6.5788 +                return 1;
  6.5789 +            } else {
  6.5790 +                return !!d.disabled ? 0 : 1;
  6.5791 +            }
  6.5792 +        }
  6.5793 +
  6.5794 +        return chart;
  6.5795 +    }
  6.5796 +
  6.5797 +    //============================================================
  6.5798 +    // Expose Public Variables
  6.5799 +    //------------------------------------------------------------
  6.5800 +
  6.5801 +    chart.dispatch = dispatch;
  6.5802 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.5803 +
  6.5804 +    chart._options = Object.create({}, {
  6.5805 +        // simple options, just get/set the necessary values
  6.5806 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.5807 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.5808 +        key:        {get: function(){return getKey;}, set: function(_){getKey=_;}},
  6.5809 +        align:      {get: function(){return align;}, set: function(_){align=_;}},
  6.5810 +        rightAlign:    {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
  6.5811 +        padding:       {get: function(){return padding;}, set: function(_){padding=_;}},
  6.5812 +        updateState:   {get: function(){return updateState;}, set: function(_){updateState=_;}},
  6.5813 +        radioButtonMode:    {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
  6.5814 +        expanded:   {get: function(){return expanded;}, set: function(_){expanded=_;}},
  6.5815 +        vers:   {get: function(){return vers;}, set: function(_){vers=_;}},
  6.5816 +
  6.5817 +        // options that require extra logic in the setter
  6.5818 +        margin: {get: function(){return margin;}, set: function(_){
  6.5819 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.5820 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.5821 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.5822 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.5823 +        }},
  6.5824 +        color:  {get: function(){return color;}, set: function(_){
  6.5825 +            color = nv.utils.getColor(_);
  6.5826 +        }}
  6.5827 +    });
  6.5828 +
  6.5829 +    nv.utils.initOptions(chart);
  6.5830 +
  6.5831 +    return chart;
  6.5832 +};
  6.5833 +
  6.5834 +nv.models.line = function() {
  6.5835 +    "use strict";
  6.5836 +    //============================================================
  6.5837 +    // Public Variables with Default Settings
  6.5838 +    //------------------------------------------------------------
  6.5839 +
  6.5840 +    var  scatter = nv.models.scatter()
  6.5841 +        ;
  6.5842 +
  6.5843 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.5844 +        , width = 960
  6.5845 +        , height = 500
  6.5846 +        , container = null
  6.5847 +        , strokeWidth = 1.5
  6.5848 +        , color = nv.utils.defaultColor() // a function that returns a color
  6.5849 +        , getX = function(d) { return d.x } // accessor to get the x value from a data point
  6.5850 +        , getY = function(d) { return d.y } // accessor to get the y value from a data point
  6.5851 +        , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined
  6.5852 +        , isArea = function(d) { return d.area } // decides if a line is an area or just a line
  6.5853 +        , clipEdge = false // if true, masks lines within x and y scale
  6.5854 +        , x //can be accessed via chart.xScale()
  6.5855 +        , y //can be accessed via chart.yScale()
  6.5856 +        , interpolate = "linear" // controls the line interpolation
  6.5857 +        , duration = 250
  6.5858 +        , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout', 'renderEnd')
  6.5859 +        ;
  6.5860 +
  6.5861 +    scatter
  6.5862 +        .pointSize(16) // default size
  6.5863 +        .pointDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
  6.5864 +    ;
  6.5865 +
  6.5866 +    //============================================================
  6.5867 +
  6.5868 +
  6.5869 +    //============================================================
  6.5870 +    // Private Variables
  6.5871 +    //------------------------------------------------------------
  6.5872 +
  6.5873 +    var x0, y0 //used to store previous scales
  6.5874 +        , renderWatch = nv.utils.renderWatch(dispatch, duration)
  6.5875 +        ;
  6.5876 +
  6.5877 +    //============================================================
  6.5878 +
  6.5879 +
  6.5880 +    function chart(selection) {
  6.5881 +        renderWatch.reset();
  6.5882 +        renderWatch.models(scatter);
  6.5883 +        selection.each(function(data) {
  6.5884 +            container = d3.select(this);
  6.5885 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.5886 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.5887 +            nv.utils.initSVG(container);
  6.5888 +
  6.5889 +            // Setup Scales
  6.5890 +            x = scatter.xScale();
  6.5891 +            y = scatter.yScale();
  6.5892 +
  6.5893 +            x0 = x0 || x;
  6.5894 +            y0 = y0 || y;
  6.5895 +
  6.5896 +            // Setup containers and skeleton of chart
  6.5897 +            var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);
  6.5898 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');
  6.5899 +            var defsEnter = wrapEnter.append('defs');
  6.5900 +            var gEnter = wrapEnter.append('g');
  6.5901 +            var g = wrap.select('g');
  6.5902 +
  6.5903 +            gEnter.append('g').attr('class', 'nv-groups');
  6.5904 +            gEnter.append('g').attr('class', 'nv-scatterWrap');
  6.5905 +
  6.5906 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.5907 +
  6.5908 +            scatter
  6.5909 +                .width(availableWidth)
  6.5910 +                .height(availableHeight);
  6.5911 +
  6.5912 +            var scatterWrap = wrap.select('.nv-scatterWrap');
  6.5913 +            scatterWrap.call(scatter);
  6.5914 +
  6.5915 +            defsEnter.append('clipPath')
  6.5916 +                .attr('id', 'nv-edge-clip-' + scatter.id())
  6.5917 +                .append('rect');
  6.5918 +
  6.5919 +            wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
  6.5920 +                .attr('width', availableWidth)
  6.5921 +                .attr('height', (availableHeight > 0) ? availableHeight : 0);
  6.5922 +
  6.5923 +            g   .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
  6.5924 +            scatterWrap
  6.5925 +                .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
  6.5926 +
  6.5927 +            var groups = wrap.select('.nv-groups').selectAll('.nv-group')
  6.5928 +                .data(function(d) { return d }, function(d) { return d.key });
  6.5929 +            groups.enter().append('g')
  6.5930 +                .style('stroke-opacity', 1e-6)
  6.5931 +                .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth })
  6.5932 +                .style('fill-opacity', 1e-6);
  6.5933 +
  6.5934 +            groups.exit().remove();
  6.5935 +
  6.5936 +            groups
  6.5937 +                .attr('class', function(d,i) {
  6.5938 +                    return (d.classed || '') + ' nv-group nv-series-' + i;
  6.5939 +                })
  6.5940 +                .classed('hover', function(d) { return d.hover })
  6.5941 +                .style('fill', function(d,i){ return color(d, i) })
  6.5942 +                .style('stroke', function(d,i){ return color(d, i)});
  6.5943 +            groups.watchTransition(renderWatch, 'line: groups')
  6.5944 +                .style('stroke-opacity', 1)
  6.5945 +                .style('fill-opacity', function(d) { return d.fillOpacity || .5});
  6.5946 +
  6.5947 +            var areaPaths = groups.selectAll('path.nv-area')
  6.5948 +                .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area
  6.5949 +            areaPaths.enter().append('path')
  6.5950 +                .attr('class', 'nv-area')
  6.5951 +                .attr('d', function(d) {
  6.5952 +                    return d3.svg.area()
  6.5953 +                        .interpolate(interpolate)
  6.5954 +                        .defined(defined)
  6.5955 +                        .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
  6.5956 +                        .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
  6.5957 +                        .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
  6.5958 +                        //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
  6.5959 +                        .apply(this, [d.values])
  6.5960 +                });
  6.5961 +            groups.exit().selectAll('path.nv-area')
  6.5962 +                .remove();
  6.5963 +
  6.5964 +            areaPaths.watchTransition(renderWatch, 'line: areaPaths')
  6.5965 +                .attr('d', function(d) {
  6.5966 +                    return d3.svg.area()
  6.5967 +                        .interpolate(interpolate)
  6.5968 +                        .defined(defined)
  6.5969 +                        .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
  6.5970 +                        .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
  6.5971 +                        .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
  6.5972 +                        //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
  6.5973 +                        .apply(this, [d.values])
  6.5974 +                });
  6.5975 +
  6.5976 +            var linePaths = groups.selectAll('path.nv-line')
  6.5977 +                .data(function(d) { return [d.values] });
  6.5978 +
  6.5979 +            linePaths.enter().append('path')
  6.5980 +                .attr('class', 'nv-line')
  6.5981 +                .attr('d',
  6.5982 +                    d3.svg.line()
  6.5983 +                    .interpolate(interpolate)
  6.5984 +                    .defined(defined)
  6.5985 +                    .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
  6.5986 +                    .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
  6.5987 +            );
  6.5988 +
  6.5989 +            linePaths.watchTransition(renderWatch, 'line: linePaths')
  6.5990 +                .attr('d',
  6.5991 +                    d3.svg.line()
  6.5992 +                    .interpolate(interpolate)
  6.5993 +                    .defined(defined)
  6.5994 +                    .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
  6.5995 +                    .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
  6.5996 +            );
  6.5997 +
  6.5998 +            //store old scales for use in transitions on update
  6.5999 +            x0 = x.copy();
  6.6000 +            y0 = y.copy();
  6.6001 +        });
  6.6002 +        renderWatch.renderEnd('line immediate');
  6.6003 +        return chart;
  6.6004 +    }
  6.6005 +
  6.6006 +
  6.6007 +    //============================================================
  6.6008 +    // Expose Public Variables
  6.6009 +    //------------------------------------------------------------
  6.6010 +
  6.6011 +    chart.dispatch = dispatch;
  6.6012 +    chart.scatter = scatter;
  6.6013 +    // Pass through events
  6.6014 +    scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });
  6.6015 +    scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });
  6.6016 +    scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });
  6.6017 +
  6.6018 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.6019 +
  6.6020 +    chart._options = Object.create({}, {
  6.6021 +        // simple options, just get/set the necessary values
  6.6022 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.6023 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.6024 +        defined: {get: function(){return defined;}, set: function(_){defined=_;}},
  6.6025 +        interpolate:      {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
  6.6026 +        clipEdge:    {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
  6.6027 +
  6.6028 +        // options that require extra logic in the setter
  6.6029 +        margin: {get: function(){return margin;}, set: function(_){
  6.6030 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.6031 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.6032 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.6033 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.6034 +        }},
  6.6035 +        duration: {get: function(){return duration;}, set: function(_){
  6.6036 +            duration = _;
  6.6037 +            renderWatch.reset(duration);
  6.6038 +            scatter.duration(duration);
  6.6039 +        }},
  6.6040 +        isArea: {get: function(){return isArea;}, set: function(_){
  6.6041 +            isArea = d3.functor(_);
  6.6042 +        }},
  6.6043 +        x: {get: function(){return getX;}, set: function(_){
  6.6044 +            getX = _;
  6.6045 +            scatter.x(_);
  6.6046 +        }},
  6.6047 +        y: {get: function(){return getY;}, set: function(_){
  6.6048 +            getY = _;
  6.6049 +            scatter.y(_);
  6.6050 +        }},
  6.6051 +        color:  {get: function(){return color;}, set: function(_){
  6.6052 +            color = nv.utils.getColor(_);
  6.6053 +            scatter.color(color);
  6.6054 +        }}
  6.6055 +    });
  6.6056 +
  6.6057 +    nv.utils.inheritOptions(chart, scatter);
  6.6058 +    nv.utils.initOptions(chart);
  6.6059 +
  6.6060 +    return chart;
  6.6061 +};
  6.6062 +nv.models.lineChart = function() {
  6.6063 +    "use strict";
  6.6064 +
  6.6065 +    //============================================================
  6.6066 +    // Public Variables with Default Settings
  6.6067 +    //------------------------------------------------------------
  6.6068 +
  6.6069 +    var lines = nv.models.line()
  6.6070 +        , xAxis = nv.models.axis()
  6.6071 +        , yAxis = nv.models.axis()
  6.6072 +        , legend = nv.models.legend()
  6.6073 +        , interactiveLayer = nv.interactiveGuideline()
  6.6074 +        , tooltip = nv.models.tooltip()
  6.6075 +        ;
  6.6076 +
  6.6077 +    var margin = {top: 30, right: 20, bottom: 50, left: 60}
  6.6078 +        , color = nv.utils.defaultColor()
  6.6079 +        , width = null
  6.6080 +        , height = null
  6.6081 +        , showLegend = true
  6.6082 +        , showXAxis = true
  6.6083 +        , showYAxis = true
  6.6084 +        , rightAlignYAxis = false
  6.6085 +        , useInteractiveGuideline = false
  6.6086 +        , x
  6.6087 +        , y
  6.6088 +        , state = nv.utils.state()
  6.6089 +        , defaultState = null
  6.6090 +        , noData = null
  6.6091 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd')
  6.6092 +        , duration = 250
  6.6093 +        ;
  6.6094 +
  6.6095 +    // set options on sub-objects for this chart
  6.6096 +    xAxis.orient('bottom').tickPadding(7);
  6.6097 +    yAxis.orient(rightAlignYAxis ? 'right' : 'left');
  6.6098 +    tooltip.valueFormatter(function(d, i) {
  6.6099 +        return yAxis.tickFormat()(d, i);
  6.6100 +    }).headerFormatter(function(d, i) {
  6.6101 +        return xAxis.tickFormat()(d, i);
  6.6102 +    });
  6.6103 +
  6.6104 +
  6.6105 +    //============================================================
  6.6106 +    // Private Variables
  6.6107 +    //------------------------------------------------------------
  6.6108 +
  6.6109 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.6110 +
  6.6111 +    var stateGetter = function(data) {
  6.6112 +        return function(){
  6.6113 +            return {
  6.6114 +                active: data.map(function(d) { return !d.disabled })
  6.6115 +            };
  6.6116 +        }
  6.6117 +    };
  6.6118 +
  6.6119 +    var stateSetter = function(data) {
  6.6120 +        return function(state) {
  6.6121 +            if (state.active !== undefined)
  6.6122 +                data.forEach(function(series,i) {
  6.6123 +                    series.disabled = !state.active[i];
  6.6124 +                });
  6.6125 +        }
  6.6126 +    };
  6.6127 +
  6.6128 +    function chart(selection) {
  6.6129 +        renderWatch.reset();
  6.6130 +        renderWatch.models(lines);
  6.6131 +        if (showXAxis) renderWatch.models(xAxis);
  6.6132 +        if (showYAxis) renderWatch.models(yAxis);
  6.6133 +
  6.6134 +        selection.each(function(data) {
  6.6135 +            var container = d3.select(this),
  6.6136 +                that = this;
  6.6137 +            nv.utils.initSVG(container);
  6.6138 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.6139 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.6140 +
  6.6141 +            chart.update = function() {
  6.6142 +                if (duration === 0)
  6.6143 +                    container.call(chart);
  6.6144 +                else
  6.6145 +                    container.transition().duration(duration).call(chart)
  6.6146 +            };
  6.6147 +            chart.container = this;
  6.6148 +
  6.6149 +            state
  6.6150 +                .setter(stateSetter(data), chart.update)
  6.6151 +                .getter(stateGetter(data))
  6.6152 +                .update();
  6.6153 +
  6.6154 +            // DEPRECATED set state.disableddisabled
  6.6155 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.6156 +
  6.6157 +            if (!defaultState) {
  6.6158 +                var key;
  6.6159 +                defaultState = {};
  6.6160 +                for (key in state) {
  6.6161 +                    if (state[key] instanceof Array)
  6.6162 +                        defaultState[key] = state[key].slice(0);
  6.6163 +                    else
  6.6164 +                        defaultState[key] = state[key];
  6.6165 +                }
  6.6166 +            }
  6.6167 +
  6.6168 +            // Display noData message if there's nothing to show.
  6.6169 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.6170 +                nv.utils.noData(chart, container)
  6.6171 +                return chart;
  6.6172 +            } else {
  6.6173 +                container.selectAll('.nv-noData').remove();
  6.6174 +            }
  6.6175 +
  6.6176 +
  6.6177 +            // Setup Scales
  6.6178 +            x = lines.xScale();
  6.6179 +            y = lines.yScale();
  6.6180 +
  6.6181 +            // Setup containers and skeleton of chart
  6.6182 +            var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);
  6.6183 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g');
  6.6184 +            var g = wrap.select('g');
  6.6185 +
  6.6186 +            gEnter.append("rect").style("opacity",0);
  6.6187 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.6188 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
  6.6189 +            gEnter.append('g').attr('class', 'nv-linesWrap');
  6.6190 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.6191 +            gEnter.append('g').attr('class', 'nv-interactive');
  6.6192 +
  6.6193 +            g.select("rect")
  6.6194 +                .attr("width",availableWidth)
  6.6195 +                .attr("height",(availableHeight > 0) ? availableHeight : 0);
  6.6196 +
  6.6197 +            // Legend
  6.6198 +            if (showLegend) {
  6.6199 +                legend.width(availableWidth);
  6.6200 +
  6.6201 +                g.select('.nv-legendWrap')
  6.6202 +                    .datum(data)
  6.6203 +                    .call(legend);
  6.6204 +
  6.6205 +                if ( margin.top != legend.height()) {
  6.6206 +                    margin.top = legend.height();
  6.6207 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.6208 +                }
  6.6209 +
  6.6210 +                wrap.select('.nv-legendWrap')
  6.6211 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.6212 +            }
  6.6213 +
  6.6214 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.6215 +
  6.6216 +            if (rightAlignYAxis) {
  6.6217 +                g.select(".nv-y.nv-axis")
  6.6218 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.6219 +            }
  6.6220 +
  6.6221 +            //Set up interactive layer
  6.6222 +            if (useInteractiveGuideline) {
  6.6223 +                interactiveLayer
  6.6224 +                    .width(availableWidth)
  6.6225 +                    .height(availableHeight)
  6.6226 +                    .margin({left:margin.left, top:margin.top})
  6.6227 +                    .svgContainer(container)
  6.6228 +                    .xScale(x);
  6.6229 +                wrap.select(".nv-interactive").call(interactiveLayer);
  6.6230 +            }
  6.6231 +
  6.6232 +            lines
  6.6233 +                .width(availableWidth)
  6.6234 +                .height(availableHeight)
  6.6235 +                .color(data.map(function(d,i) {
  6.6236 +                    return d.color || color(d, i);
  6.6237 +                }).filter(function(d,i) { return !data[i].disabled }));
  6.6238 +
  6.6239 +
  6.6240 +            var linesWrap = g.select('.nv-linesWrap')
  6.6241 +                .datum(data.filter(function(d) { return !d.disabled }));
  6.6242 +
  6.6243 +            linesWrap.call(lines);
  6.6244 +
  6.6245 +            // Setup Axes
  6.6246 +            if (showXAxis) {
  6.6247 +                xAxis
  6.6248 +                    .scale(x)
  6.6249 +                    ._ticks(nv.utils.calcTicksX(availableWidth/100, data) )
  6.6250 +                    .tickSize(-availableHeight, 0);
  6.6251 +
  6.6252 +                g.select('.nv-x.nv-axis')
  6.6253 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')');
  6.6254 +                g.select('.nv-x.nv-axis')
  6.6255 +                    .call(xAxis);
  6.6256 +            }
  6.6257 +
  6.6258 +            if (showYAxis) {
  6.6259 +                yAxis
  6.6260 +                    .scale(y)
  6.6261 +                    ._ticks(nv.utils.calcTicksY(availableHeight/36, data) )
  6.6262 +                    .tickSize( -availableWidth, 0);
  6.6263 +
  6.6264 +                g.select('.nv-y.nv-axis')
  6.6265 +                    .call(yAxis);
  6.6266 +            }
  6.6267 +
  6.6268 +            //============================================================
  6.6269 +            // Event Handling/Dispatching (in chart's scope)
  6.6270 +            //------------------------------------------------------------
  6.6271 +
  6.6272 +            legend.dispatch.on('stateChange', function(newState) {
  6.6273 +                for (var key in newState)
  6.6274 +                    state[key] = newState[key];
  6.6275 +                dispatch.stateChange(state);
  6.6276 +                chart.update();
  6.6277 +            });
  6.6278 +
  6.6279 +            interactiveLayer.dispatch.on('elementMousemove', function(e) {
  6.6280 +                lines.clearHighlights();
  6.6281 +                var singlePoint, pointIndex, pointXLocation, allData = [];
  6.6282 +                data
  6.6283 +                    .filter(function(series, i) {
  6.6284 +                        series.seriesIndex = i;
  6.6285 +                        return !series.disabled;
  6.6286 +                    })
  6.6287 +                    .forEach(function(series,i) {
  6.6288 +                        pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
  6.6289 +                        var point = series.values[pointIndex];
  6.6290 +                        var pointYValue = chart.y()(point, pointIndex);
  6.6291 +                        if (pointYValue != null) {
  6.6292 +                            lines.highlightPoint(i, pointIndex, true);
  6.6293 +                        }
  6.6294 +                        if (point === undefined) return;
  6.6295 +                        if (singlePoint === undefined) singlePoint = point;
  6.6296 +                        if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
  6.6297 +                        allData.push({
  6.6298 +                            key: series.key,
  6.6299 +                            value: pointYValue,
  6.6300 +                            color: color(series,series.seriesIndex)
  6.6301 +                        });
  6.6302 +                    });
  6.6303 +                //Highlight the tooltip entry based on which point the mouse is closest to.
  6.6304 +                if (allData.length > 2) {
  6.6305 +                    var yValue = chart.yScale().invert(e.mouseY);
  6.6306 +                    var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
  6.6307 +                    var threshold = 0.03 * domainExtent;
  6.6308 +                    var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
  6.6309 +                    if (indexToHighlight !== null)
  6.6310 +                        allData[indexToHighlight].highlight = true;
  6.6311 +                }
  6.6312 +
  6.6313 +                var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
  6.6314 +                interactiveLayer.tooltip
  6.6315 +                    .position({left: e.mouseX + margin.left, top: e.mouseY + margin.top})
  6.6316 +                    .chartContainer(that.parentNode)
  6.6317 +                    .valueFormatter(function(d,i) {
  6.6318 +                        return d == null ? "N/A" : yAxis.tickFormat()(d);
  6.6319 +                    })
  6.6320 +                    .data({
  6.6321 +                        value: xValue,
  6.6322 +                        index: pointIndex,
  6.6323 +                        series: allData
  6.6324 +                    })();
  6.6325 +
  6.6326 +                interactiveLayer.renderGuideLine(pointXLocation);
  6.6327 +
  6.6328 +            });
  6.6329 +
  6.6330 +            interactiveLayer.dispatch.on('elementClick', function(e) {
  6.6331 +                var pointXLocation, allData = [];
  6.6332 +
  6.6333 +                data.filter(function(series, i) {
  6.6334 +                    series.seriesIndex = i;
  6.6335 +                    return !series.disabled;
  6.6336 +                }).forEach(function(series) {
  6.6337 +                    var pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
  6.6338 +                    var point = series.values[pointIndex];
  6.6339 +                    if (typeof point === 'undefined') return;
  6.6340 +                    if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
  6.6341 +                    var yPos = chart.yScale()(chart.y()(point,pointIndex));
  6.6342 +                    allData.push({
  6.6343 +                        point: point,
  6.6344 +                        pointIndex: pointIndex,
  6.6345 +                        pos: [pointXLocation, yPos],
  6.6346 +                        seriesIndex: series.seriesIndex,
  6.6347 +                        series: series
  6.6348 +                    });
  6.6349 +                });
  6.6350 +
  6.6351 +                lines.dispatch.elementClick(allData);
  6.6352 +            });
  6.6353 +
  6.6354 +            interactiveLayer.dispatch.on("elementMouseout",function(e) {
  6.6355 +                lines.clearHighlights();
  6.6356 +            });
  6.6357 +
  6.6358 +            dispatch.on('changeState', function(e) {
  6.6359 +                if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {
  6.6360 +                    data.forEach(function(series,i) {
  6.6361 +                        series.disabled = e.disabled[i];
  6.6362 +                    });
  6.6363 +
  6.6364 +                    state.disabled = e.disabled;
  6.6365 +                }
  6.6366 +
  6.6367 +                chart.update();
  6.6368 +            });
  6.6369 +
  6.6370 +        });
  6.6371 +
  6.6372 +        renderWatch.renderEnd('lineChart immediate');
  6.6373 +        return chart;
  6.6374 +    }
  6.6375 +
  6.6376 +    //============================================================
  6.6377 +    // Event Handling/Dispatching (out of chart's scope)
  6.6378 +    //------------------------------------------------------------
  6.6379 +
  6.6380 +    lines.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.6381 +        tooltip.data(evt).position(evt.pos).hidden(false);
  6.6382 +    });
  6.6383 +
  6.6384 +    lines.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.6385 +        tooltip.hidden(true)
  6.6386 +    });
  6.6387 +
  6.6388 +    //============================================================
  6.6389 +    // Expose Public Variables
  6.6390 +    //------------------------------------------------------------
  6.6391 +
  6.6392 +    // expose chart's sub-components
  6.6393 +    chart.dispatch = dispatch;
  6.6394 +    chart.lines = lines;
  6.6395 +    chart.legend = legend;
  6.6396 +    chart.xAxis = xAxis;
  6.6397 +    chart.yAxis = yAxis;
  6.6398 +    chart.interactiveLayer = interactiveLayer;
  6.6399 +    chart.tooltip = tooltip;
  6.6400 +
  6.6401 +    chart.dispatch = dispatch;
  6.6402 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.6403 +
  6.6404 +    chart._options = Object.create({}, {
  6.6405 +        // simple options, just get/set the necessary values
  6.6406 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.6407 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.6408 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.6409 +        showXAxis:      {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.6410 +        showYAxis:    {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.6411 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.6412 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.6413 +
  6.6414 +        // deprecated options
  6.6415 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.6416 +            // deprecated after 1.7.1
  6.6417 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.6418 +            tooltip.enabled(!!_);
  6.6419 +        }},
  6.6420 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.6421 +            // deprecated after 1.7.1
  6.6422 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.6423 +            tooltip.contentGenerator(_);
  6.6424 +        }},
  6.6425 +
  6.6426 +        // options that require extra logic in the setter
  6.6427 +        margin: {get: function(){return margin;}, set: function(_){
  6.6428 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.6429 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.6430 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.6431 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.6432 +        }},
  6.6433 +        duration: {get: function(){return duration;}, set: function(_){
  6.6434 +            duration = _;
  6.6435 +            renderWatch.reset(duration);
  6.6436 +            lines.duration(duration);
  6.6437 +            xAxis.duration(duration);
  6.6438 +            yAxis.duration(duration);
  6.6439 +        }},
  6.6440 +        color:  {get: function(){return color;}, set: function(_){
  6.6441 +            color = nv.utils.getColor(_);
  6.6442 +            legend.color(color);
  6.6443 +            lines.color(color);
  6.6444 +        }},
  6.6445 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.6446 +            rightAlignYAxis = _;
  6.6447 +            yAxis.orient( rightAlignYAxis ? 'right' : 'left');
  6.6448 +        }},
  6.6449 +        useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
  6.6450 +            useInteractiveGuideline = _;
  6.6451 +            if (useInteractiveGuideline) {
  6.6452 +                lines.interactive(false);
  6.6453 +                lines.useVoronoi(false);
  6.6454 +            }
  6.6455 +        }}
  6.6456 +    });
  6.6457 +
  6.6458 +    nv.utils.inheritOptions(chart, lines);
  6.6459 +    nv.utils.initOptions(chart);
  6.6460 +
  6.6461 +    return chart;
  6.6462 +};
  6.6463 +nv.models.linePlusBarChart = function() {
  6.6464 +    "use strict";
  6.6465 +
  6.6466 +    //============================================================
  6.6467 +    // Public Variables with Default Settings
  6.6468 +    //------------------------------------------------------------
  6.6469 +
  6.6470 +    var lines = nv.models.line()
  6.6471 +        , lines2 = nv.models.line()
  6.6472 +        , bars = nv.models.historicalBar()
  6.6473 +        , bars2 = nv.models.historicalBar()
  6.6474 +        , xAxis = nv.models.axis()
  6.6475 +        , x2Axis = nv.models.axis()
  6.6476 +        , y1Axis = nv.models.axis()
  6.6477 +        , y2Axis = nv.models.axis()
  6.6478 +        , y3Axis = nv.models.axis()
  6.6479 +        , y4Axis = nv.models.axis()
  6.6480 +        , legend = nv.models.legend()
  6.6481 +        , brush = d3.svg.brush()
  6.6482 +        , tooltip = nv.models.tooltip()
  6.6483 +        ;
  6.6484 +
  6.6485 +    var margin = {top: 30, right: 30, bottom: 30, left: 60}
  6.6486 +        , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
  6.6487 +        , width = null
  6.6488 +        , height = null
  6.6489 +        , getX = function(d) { return d.x }
  6.6490 +        , getY = function(d) { return d.y }
  6.6491 +        , color = nv.utils.defaultColor()
  6.6492 +        , showLegend = true
  6.6493 +        , focusEnable = true
  6.6494 +        , focusShowAxisY = false
  6.6495 +        , focusShowAxisX = true
  6.6496 +        , focusHeight = 50
  6.6497 +        , extent
  6.6498 +        , brushExtent = null
  6.6499 +        , x
  6.6500 +        , x2
  6.6501 +        , y1
  6.6502 +        , y2
  6.6503 +        , y3
  6.6504 +        , y4
  6.6505 +        , noData = null
  6.6506 +        , dispatch = d3.dispatch('brush', 'stateChange', 'changeState')
  6.6507 +        , transitionDuration = 0
  6.6508 +        , state = nv.utils.state()
  6.6509 +        , defaultState = null
  6.6510 +        , legendLeftAxisHint = ' (left axis)'
  6.6511 +        , legendRightAxisHint = ' (right axis)'
  6.6512 +        ;
  6.6513 +
  6.6514 +    lines.clipEdge(true);
  6.6515 +    lines2.interactive(false);
  6.6516 +    xAxis.orient('bottom').tickPadding(5);
  6.6517 +    y1Axis.orient('left');
  6.6518 +    y2Axis.orient('right');
  6.6519 +    x2Axis.orient('bottom').tickPadding(5);
  6.6520 +    y3Axis.orient('left');
  6.6521 +    y4Axis.orient('right');
  6.6522 +
  6.6523 +    tooltip.headerEnabled(true).headerFormatter(function(d, i) {
  6.6524 +        return xAxis.tickFormat()(d, i);
  6.6525 +    });
  6.6526 +
  6.6527 +    //============================================================
  6.6528 +    // Private Variables
  6.6529 +    //------------------------------------------------------------
  6.6530 +
  6.6531 +    var stateGetter = function(data) {
  6.6532 +        return function(){
  6.6533 +            return {
  6.6534 +                active: data.map(function(d) { return !d.disabled })
  6.6535 +            };
  6.6536 +        }
  6.6537 +    };
  6.6538 +
  6.6539 +    var stateSetter = function(data) {
  6.6540 +        return function(state) {
  6.6541 +            if (state.active !== undefined)
  6.6542 +                data.forEach(function(series,i) {
  6.6543 +                    series.disabled = !state.active[i];
  6.6544 +                });
  6.6545 +        }
  6.6546 +    };
  6.6547 +
  6.6548 +    function chart(selection) {
  6.6549 +        selection.each(function(data) {
  6.6550 +            var container = d3.select(this),
  6.6551 +                that = this;
  6.6552 +            nv.utils.initSVG(container);
  6.6553 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.6554 +                availableHeight1 = nv.utils.availableHeight(height, container, margin)
  6.6555 +                    - (focusEnable ? focusHeight : 0),
  6.6556 +                availableHeight2 = focusHeight - margin2.top - margin2.bottom;
  6.6557 +
  6.6558 +            chart.update = function() { container.transition().duration(transitionDuration).call(chart); };
  6.6559 +            chart.container = this;
  6.6560 +
  6.6561 +            state
  6.6562 +                .setter(stateSetter(data), chart.update)
  6.6563 +                .getter(stateGetter(data))
  6.6564 +                .update();
  6.6565 +
  6.6566 +            // DEPRECATED set state.disableddisabled
  6.6567 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.6568 +
  6.6569 +            if (!defaultState) {
  6.6570 +                var key;
  6.6571 +                defaultState = {};
  6.6572 +                for (key in state) {
  6.6573 +                    if (state[key] instanceof Array)
  6.6574 +                        defaultState[key] = state[key].slice(0);
  6.6575 +                    else
  6.6576 +                        defaultState[key] = state[key];
  6.6577 +                }
  6.6578 +            }
  6.6579 +
  6.6580 +            // Display No Data message if there's nothing to show.
  6.6581 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.6582 +                nv.utils.noData(chart, container)
  6.6583 +                return chart;
  6.6584 +            } else {
  6.6585 +                container.selectAll('.nv-noData').remove();
  6.6586 +            }
  6.6587 +
  6.6588 +            // Setup Scales
  6.6589 +            var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
  6.6590 +            var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
  6.6591 +
  6.6592 +            x = bars.xScale();
  6.6593 +            x2 = x2Axis.scale();
  6.6594 +            y1 = bars.yScale();
  6.6595 +            y2 = lines.yScale();
  6.6596 +            y3 = bars2.yScale();
  6.6597 +            y4 = lines2.yScale();
  6.6598 +
  6.6599 +            var series1 = data
  6.6600 +                .filter(function(d) { return !d.disabled && d.bar })
  6.6601 +                .map(function(d) {
  6.6602 +                    return d.values.map(function(d,i) {
  6.6603 +                        return { x: getX(d,i), y: getY(d,i) }
  6.6604 +                    })
  6.6605 +                });
  6.6606 +
  6.6607 +            var series2 = data
  6.6608 +                .filter(function(d) { return !d.disabled && !d.bar })
  6.6609 +                .map(function(d) {
  6.6610 +                    return d.values.map(function(d,i) {
  6.6611 +                        return { x: getX(d,i), y: getY(d,i) }
  6.6612 +                    })
  6.6613 +                });
  6.6614 +
  6.6615 +            x.range([0, availableWidth]);
  6.6616 +
  6.6617 +            x2  .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
  6.6618 +                .range([0, availableWidth]);
  6.6619 +
  6.6620 +            // Setup containers and skeleton of chart
  6.6621 +            var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
  6.6622 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
  6.6623 +            var g = wrap.select('g');
  6.6624 +
  6.6625 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.6626 +
  6.6627 +            // this is the main chart
  6.6628 +            var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
  6.6629 +            focusEnter.append('g').attr('class', 'nv-x nv-axis');
  6.6630 +            focusEnter.append('g').attr('class', 'nv-y1 nv-axis');
  6.6631 +            focusEnter.append('g').attr('class', 'nv-y2 nv-axis');
  6.6632 +            focusEnter.append('g').attr('class', 'nv-barsWrap');
  6.6633 +            focusEnter.append('g').attr('class', 'nv-linesWrap');
  6.6634 +
  6.6635 +            // context chart is where you can focus in
  6.6636 +            var contextEnter = gEnter.append('g').attr('class', 'nv-context');
  6.6637 +            contextEnter.append('g').attr('class', 'nv-x nv-axis');
  6.6638 +            contextEnter.append('g').attr('class', 'nv-y1 nv-axis');
  6.6639 +            contextEnter.append('g').attr('class', 'nv-y2 nv-axis');
  6.6640 +            contextEnter.append('g').attr('class', 'nv-barsWrap');
  6.6641 +            contextEnter.append('g').attr('class', 'nv-linesWrap');
  6.6642 +            contextEnter.append('g').attr('class', 'nv-brushBackground');
  6.6643 +            contextEnter.append('g').attr('class', 'nv-x nv-brush');
  6.6644 +
  6.6645 +            //============================================================
  6.6646 +            // Legend
  6.6647 +            //------------------------------------------------------------
  6.6648 +
  6.6649 +            if (showLegend) {
  6.6650 +                var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;
  6.6651 +                var legendXPosition = legend.align() ? legendWidth : 0;
  6.6652 +
  6.6653 +                legend.width(legendWidth);
  6.6654 +
  6.6655 +                g.select('.nv-legendWrap')
  6.6656 +                    .datum(data.map(function(series) {
  6.6657 +                        series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
  6.6658 +                        series.key = series.originalKey + (series.bar ? legendLeftAxisHint : legendRightAxisHint);
  6.6659 +                        return series;
  6.6660 +                    }))
  6.6661 +                    .call(legend);
  6.6662 +
  6.6663 +                if ( margin.top != legend.height()) {
  6.6664 +                    margin.top = legend.height();
  6.6665 +                    // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"?
  6.6666 +                    availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight;
  6.6667 +                }
  6.6668 +
  6.6669 +                g.select('.nv-legendWrap')
  6.6670 +                    .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');
  6.6671 +            }
  6.6672 +
  6.6673 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.6674 +
  6.6675 +            //============================================================
  6.6676 +            // Context chart (focus chart) components
  6.6677 +            //------------------------------------------------------------
  6.6678 +
  6.6679 +            // hide or show the focus context chart
  6.6680 +            g.select('.nv-context').style('display', focusEnable ? 'initial' : 'none');
  6.6681 +
  6.6682 +            bars2
  6.6683 +                .width(availableWidth)
  6.6684 +                .height(availableHeight2)
  6.6685 +                .color(data.map(function (d, i) {
  6.6686 +                    return d.color || color(d, i);
  6.6687 +                }).filter(function (d, i) {
  6.6688 +                    return !data[i].disabled && data[i].bar
  6.6689 +                }));
  6.6690 +            lines2
  6.6691 +                .width(availableWidth)
  6.6692 +                .height(availableHeight2)
  6.6693 +                .color(data.map(function (d, i) {
  6.6694 +                    return d.color || color(d, i);
  6.6695 +                }).filter(function (d, i) {
  6.6696 +                    return !data[i].disabled && !data[i].bar
  6.6697 +                }));
  6.6698 +
  6.6699 +            var bars2Wrap = g.select('.nv-context .nv-barsWrap')
  6.6700 +                .datum(dataBars.length ? dataBars : [
  6.6701 +                    {values: []}
  6.6702 +                ]);
  6.6703 +            var lines2Wrap = g.select('.nv-context .nv-linesWrap')
  6.6704 +                .datum(!dataLines[0].disabled ? dataLines : [
  6.6705 +                    {values: []}
  6.6706 +                ]);
  6.6707 +
  6.6708 +            g.select('.nv-context')
  6.6709 +                .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')');
  6.6710 +
  6.6711 +            bars2Wrap.transition().call(bars2);
  6.6712 +            lines2Wrap.transition().call(lines2);
  6.6713 +
  6.6714 +            // context (focus chart) axis controls
  6.6715 +            if (focusShowAxisX) {
  6.6716 +                x2Axis
  6.6717 +                    ._ticks( nv.utils.calcTicksX(availableWidth / 100, data))
  6.6718 +                    .tickSize(-availableHeight2, 0);
  6.6719 +                g.select('.nv-context .nv-x.nv-axis')
  6.6720 +                    .attr('transform', 'translate(0,' + y3.range()[0] + ')');
  6.6721 +                g.select('.nv-context .nv-x.nv-axis').transition()
  6.6722 +                    .call(x2Axis);
  6.6723 +            }
  6.6724 +
  6.6725 +            if (focusShowAxisY) {
  6.6726 +                y3Axis
  6.6727 +                    .scale(y3)
  6.6728 +                    ._ticks( availableHeight2 / 36 )
  6.6729 +                    .tickSize( -availableWidth, 0);
  6.6730 +                y4Axis
  6.6731 +                    .scale(y4)
  6.6732 +                    ._ticks( availableHeight2 / 36 )
  6.6733 +                    .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
  6.6734 +
  6.6735 +                g.select('.nv-context .nv-y3.nv-axis')
  6.6736 +                    .style('opacity', dataBars.length ? 1 : 0)
  6.6737 +                    .attr('transform', 'translate(0,' + x2.range()[0] + ')');
  6.6738 +                g.select('.nv-context .nv-y2.nv-axis')
  6.6739 +                    .style('opacity', dataLines.length ? 1 : 0)
  6.6740 +                    .attr('transform', 'translate(' + x2.range()[1] + ',0)');
  6.6741 +
  6.6742 +                g.select('.nv-context .nv-y1.nv-axis').transition()
  6.6743 +                    .call(y3Axis);
  6.6744 +                g.select('.nv-context .nv-y2.nv-axis').transition()
  6.6745 +                    .call(y4Axis);
  6.6746 +            }
  6.6747 +
  6.6748 +            // Setup Brush
  6.6749 +            brush.x(x2).on('brush', onBrush);
  6.6750 +
  6.6751 +            if (brushExtent) brush.extent(brushExtent);
  6.6752 +
  6.6753 +            var brushBG = g.select('.nv-brushBackground').selectAll('g')
  6.6754 +                .data([brushExtent || brush.extent()]);
  6.6755 +
  6.6756 +            var brushBGenter = brushBG.enter()
  6.6757 +                .append('g');
  6.6758 +
  6.6759 +            brushBGenter.append('rect')
  6.6760 +                .attr('class', 'left')
  6.6761 +                .attr('x', 0)
  6.6762 +                .attr('y', 0)
  6.6763 +                .attr('height', availableHeight2);
  6.6764 +
  6.6765 +            brushBGenter.append('rect')
  6.6766 +                .attr('class', 'right')
  6.6767 +                .attr('x', 0)
  6.6768 +                .attr('y', 0)
  6.6769 +                .attr('height', availableHeight2);
  6.6770 +
  6.6771 +            var gBrush = g.select('.nv-x.nv-brush')
  6.6772 +                .call(brush);
  6.6773 +            gBrush.selectAll('rect')
  6.6774 +                //.attr('y', -5)
  6.6775 +                .attr('height', availableHeight2);
  6.6776 +            gBrush.selectAll('.resize').append('path').attr('d', resizePath);
  6.6777 +
  6.6778 +            //============================================================
  6.6779 +            // Event Handling/Dispatching (in chart's scope)
  6.6780 +            //------------------------------------------------------------
  6.6781 +
  6.6782 +            legend.dispatch.on('stateChange', function(newState) {
  6.6783 +                for (var key in newState)
  6.6784 +                    state[key] = newState[key];
  6.6785 +                dispatch.stateChange(state);
  6.6786 +                chart.update();
  6.6787 +            });
  6.6788 +
  6.6789 +            // Update chart from a state object passed to event handler
  6.6790 +            dispatch.on('changeState', function(e) {
  6.6791 +                if (typeof e.disabled !== 'undefined') {
  6.6792 +                    data.forEach(function(series,i) {
  6.6793 +                        series.disabled = e.disabled[i];
  6.6794 +                    });
  6.6795 +                    state.disabled = e.disabled;
  6.6796 +                }
  6.6797 +                chart.update();
  6.6798 +            });
  6.6799 +
  6.6800 +            //============================================================
  6.6801 +            // Functions
  6.6802 +            //------------------------------------------------------------
  6.6803 +
  6.6804 +            // Taken from crossfilter (http://square.github.com/crossfilter/)
  6.6805 +            function resizePath(d) {
  6.6806 +                var e = +(d == 'e'),
  6.6807 +                    x = e ? 1 : -1,
  6.6808 +                    y = availableHeight2 / 3;
  6.6809 +                return 'M' + (.5 * x) + ',' + y
  6.6810 +                    + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
  6.6811 +                    + 'V' + (2 * y - 6)
  6.6812 +                    + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
  6.6813 +                    + 'Z'
  6.6814 +                    + 'M' + (2.5 * x) + ',' + (y + 8)
  6.6815 +                    + 'V' + (2 * y - 8)
  6.6816 +                    + 'M' + (4.5 * x) + ',' + (y + 8)
  6.6817 +                    + 'V' + (2 * y - 8);
  6.6818 +            }
  6.6819 +
  6.6820 +
  6.6821 +            function updateBrushBG() {
  6.6822 +                if (!brush.empty()) brush.extent(brushExtent);
  6.6823 +                brushBG
  6.6824 +                    .data([brush.empty() ? x2.domain() : brushExtent])
  6.6825 +                    .each(function(d,i) {
  6.6826 +                        var leftWidth = x2(d[0]) - x2.range()[0],
  6.6827 +                            rightWidth = x2.range()[1] - x2(d[1]);
  6.6828 +                        d3.select(this).select('.left')
  6.6829 +                            .attr('width',  leftWidth < 0 ? 0 : leftWidth);
  6.6830 +
  6.6831 +                        d3.select(this).select('.right')
  6.6832 +                            .attr('x', x2(d[1]))
  6.6833 +                            .attr('width', rightWidth < 0 ? 0 : rightWidth);
  6.6834 +                    });
  6.6835 +            }
  6.6836 +
  6.6837 +            function onBrush() {
  6.6838 +                brushExtent = brush.empty() ? null : brush.extent();
  6.6839 +                extent = brush.empty() ? x2.domain() : brush.extent();
  6.6840 +                dispatch.brush({extent: extent, brush: brush});
  6.6841 +                updateBrushBG();
  6.6842 +
  6.6843 +                // Prepare Main (Focus) Bars and Lines
  6.6844 +                bars
  6.6845 +                    .width(availableWidth)
  6.6846 +                    .height(availableHeight1)
  6.6847 +                    .color(data.map(function(d,i) {
  6.6848 +                        return d.color || color(d, i);
  6.6849 +                    }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
  6.6850 +
  6.6851 +                lines
  6.6852 +                    .width(availableWidth)
  6.6853 +                    .height(availableHeight1)
  6.6854 +                    .color(data.map(function(d,i) {
  6.6855 +                        return d.color || color(d, i);
  6.6856 +                    }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
  6.6857 +
  6.6858 +                var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')
  6.6859 +                    .datum(!dataBars.length ? [{values:[]}] :
  6.6860 +                        dataBars
  6.6861 +                            .map(function(d,i) {
  6.6862 +                                return {
  6.6863 +                                    key: d.key,
  6.6864 +                                    values: d.values.filter(function(d,i) {
  6.6865 +                                        return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];
  6.6866 +                                    })
  6.6867 +                                }
  6.6868 +                            })
  6.6869 +                );
  6.6870 +
  6.6871 +                var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
  6.6872 +                    .datum(dataLines[0].disabled ? [{values:[]}] :
  6.6873 +                        dataLines
  6.6874 +                            .map(function(d,i) {
  6.6875 +                                return {
  6.6876 +                                    area: d.area,
  6.6877 +                                    fillOpacity: d.fillOpacity,
  6.6878 +                                    key: d.key,
  6.6879 +                                    values: d.values.filter(function(d,i) {
  6.6880 +                                        return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
  6.6881 +                                    })
  6.6882 +                                }
  6.6883 +                            })
  6.6884 +                );
  6.6885 +
  6.6886 +                // Update Main (Focus) X Axis
  6.6887 +                if (dataBars.length) {
  6.6888 +                    x = bars.xScale();
  6.6889 +                } else {
  6.6890 +                    x = lines.xScale();
  6.6891 +                }
  6.6892 +
  6.6893 +                xAxis
  6.6894 +                    .scale(x)
  6.6895 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.6896 +                    .tickSize(-availableHeight1, 0);
  6.6897 +
  6.6898 +                xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);
  6.6899 +
  6.6900 +                g.select('.nv-x.nv-axis').transition().duration(transitionDuration)
  6.6901 +                    .call(xAxis);
  6.6902 +
  6.6903 +                // Update Main (Focus) Bars and Lines
  6.6904 +                focusBarsWrap.transition().duration(transitionDuration).call(bars);
  6.6905 +                focusLinesWrap.transition().duration(transitionDuration).call(lines);
  6.6906 +
  6.6907 +                // Setup and Update Main (Focus) Y Axes
  6.6908 +                g.select('.nv-focus .nv-x.nv-axis')
  6.6909 +                    .attr('transform', 'translate(0,' + y1.range()[0] + ')');
  6.6910 +
  6.6911 +                y1Axis
  6.6912 +                    .scale(y1)
  6.6913 +                    ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
  6.6914 +                    .tickSize(-availableWidth, 0);
  6.6915 +                y2Axis
  6.6916 +                    .scale(y2)
  6.6917 +                    ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
  6.6918 +                    .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
  6.6919 +
  6.6920 +                g.select('.nv-focus .nv-y1.nv-axis')
  6.6921 +                    .style('opacity', dataBars.length ? 1 : 0);
  6.6922 +                g.select('.nv-focus .nv-y2.nv-axis')
  6.6923 +                    .style('opacity', dataLines.length && !dataLines[0].disabled ? 1 : 0)
  6.6924 +                    .attr('transform', 'translate(' + x.range()[1] + ',0)');
  6.6925 +
  6.6926 +                g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration)
  6.6927 +                    .call(y1Axis);
  6.6928 +                g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration)
  6.6929 +                    .call(y2Axis);
  6.6930 +            }
  6.6931 +
  6.6932 +            onBrush();
  6.6933 +
  6.6934 +        });
  6.6935 +
  6.6936 +        return chart;
  6.6937 +    }
  6.6938 +
  6.6939 +    //============================================================
  6.6940 +    // Event Handling/Dispatching (out of chart's scope)
  6.6941 +    //------------------------------------------------------------
  6.6942 +
  6.6943 +    lines.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.6944 +        tooltip
  6.6945 +            .duration(100)
  6.6946 +            .valueFormatter(function(d, i) {
  6.6947 +                return y2Axis.tickFormat()(d, i);
  6.6948 +            })
  6.6949 +            .data(evt)
  6.6950 +            .position(evt.pos)
  6.6951 +            .hidden(false);
  6.6952 +    });
  6.6953 +
  6.6954 +    lines.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.6955 +        tooltip.hidden(true)
  6.6956 +    });
  6.6957 +
  6.6958 +    bars.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.6959 +        evt.value = chart.x()(evt.data);
  6.6960 +        evt['series'] = {
  6.6961 +            value: chart.y()(evt.data),
  6.6962 +            color: evt.color
  6.6963 +        };
  6.6964 +        tooltip
  6.6965 +            .duration(0)
  6.6966 +            .valueFormatter(function(d, i) {
  6.6967 +                return y1Axis.tickFormat()(d, i);
  6.6968 +            })
  6.6969 +            .data(evt)
  6.6970 +            .hidden(false);
  6.6971 +    });
  6.6972 +
  6.6973 +    bars.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.6974 +        tooltip.hidden(true);
  6.6975 +    });
  6.6976 +
  6.6977 +    bars.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.6978 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.6979 +    });
  6.6980 +
  6.6981 +    //============================================================
  6.6982 +
  6.6983 +
  6.6984 +    //============================================================
  6.6985 +    // Expose Public Variables
  6.6986 +    //------------------------------------------------------------
  6.6987 +
  6.6988 +    // expose chart's sub-components
  6.6989 +    chart.dispatch = dispatch;
  6.6990 +    chart.legend = legend;
  6.6991 +    chart.lines = lines;
  6.6992 +    chart.lines2 = lines2;
  6.6993 +    chart.bars = bars;
  6.6994 +    chart.bars2 = bars2;
  6.6995 +    chart.xAxis = xAxis;
  6.6996 +    chart.x2Axis = x2Axis;
  6.6997 +    chart.y1Axis = y1Axis;
  6.6998 +    chart.y2Axis = y2Axis;
  6.6999 +    chart.y3Axis = y3Axis;
  6.7000 +    chart.y4Axis = y4Axis;
  6.7001 +    chart.tooltip = tooltip;
  6.7002 +
  6.7003 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.7004 +
  6.7005 +    chart._options = Object.create({}, {
  6.7006 +        // simple options, just get/set the necessary values
  6.7007 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.7008 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.7009 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.7010 +        brushExtent:    {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
  6.7011 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.7012 +        focusEnable:    {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
  6.7013 +        focusHeight:    {get: function(){return focusHeight;}, set: function(_){focusHeight=_;}},
  6.7014 +        focusShowAxisX:    {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}},
  6.7015 +        focusShowAxisY:    {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}},
  6.7016 +        legendLeftAxisHint:    {get: function(){return legendLeftAxisHint;}, set: function(_){legendLeftAxisHint=_;}},
  6.7017 +        legendRightAxisHint:    {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}},
  6.7018 +
  6.7019 +        // deprecated options
  6.7020 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.7021 +            // deprecated after 1.7.1
  6.7022 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.7023 +            tooltip.enabled(!!_);
  6.7024 +        }},
  6.7025 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.7026 +            // deprecated after 1.7.1
  6.7027 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.7028 +            tooltip.contentGenerator(_);
  6.7029 +        }},
  6.7030 +
  6.7031 +        // options that require extra logic in the setter
  6.7032 +        margin: {get: function(){return margin;}, set: function(_){
  6.7033 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.7034 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.7035 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.7036 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.7037 +        }},
  6.7038 +        duration: {get: function(){return transitionDuration;}, set: function(_){
  6.7039 +            transitionDuration = _;
  6.7040 +        }},
  6.7041 +        color:  {get: function(){return color;}, set: function(_){
  6.7042 +            color = nv.utils.getColor(_);
  6.7043 +            legend.color(color);
  6.7044 +        }},
  6.7045 +        x: {get: function(){return getX;}, set: function(_){
  6.7046 +            getX = _;
  6.7047 +            lines.x(_);
  6.7048 +            lines2.x(_);
  6.7049 +            bars.x(_);
  6.7050 +            bars2.x(_);
  6.7051 +        }},
  6.7052 +        y: {get: function(){return getY;}, set: function(_){
  6.7053 +            getY = _;
  6.7054 +            lines.y(_);
  6.7055 +            lines2.y(_);
  6.7056 +            bars.y(_);
  6.7057 +            bars2.y(_);
  6.7058 +        }}
  6.7059 +    });
  6.7060 +
  6.7061 +    nv.utils.inheritOptions(chart, lines);
  6.7062 +    nv.utils.initOptions(chart);
  6.7063 +
  6.7064 +    return chart;
  6.7065 +};
  6.7066 +nv.models.lineWithFocusChart = function() {
  6.7067 +    "use strict";
  6.7068 +
  6.7069 +    //============================================================
  6.7070 +    // Public Variables with Default Settings
  6.7071 +    //------------------------------------------------------------
  6.7072 +
  6.7073 +    var lines = nv.models.line()
  6.7074 +        , lines2 = nv.models.line()
  6.7075 +        , xAxis = nv.models.axis()
  6.7076 +        , yAxis = nv.models.axis()
  6.7077 +        , x2Axis = nv.models.axis()
  6.7078 +        , y2Axis = nv.models.axis()
  6.7079 +        , legend = nv.models.legend()
  6.7080 +        , brush = d3.svg.brush()
  6.7081 +        , tooltip = nv.models.tooltip()
  6.7082 +        , interactiveLayer = nv.interactiveGuideline()
  6.7083 +        ;
  6.7084 +
  6.7085 +    var margin = {top: 30, right: 30, bottom: 30, left: 60}
  6.7086 +        , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
  6.7087 +        , color = nv.utils.defaultColor()
  6.7088 +        , width = null
  6.7089 +        , height = null
  6.7090 +        , height2 = 50
  6.7091 +        , useInteractiveGuideline = false
  6.7092 +        , x
  6.7093 +        , y
  6.7094 +        , x2
  6.7095 +        , y2
  6.7096 +        , showLegend = true
  6.7097 +        , brushExtent = null
  6.7098 +        , noData = null
  6.7099 +        , dispatch = d3.dispatch('brush', 'stateChange', 'changeState')
  6.7100 +        , transitionDuration = 250
  6.7101 +        , state = nv.utils.state()
  6.7102 +        , defaultState = null
  6.7103 +        ;
  6.7104 +
  6.7105 +    lines.clipEdge(true).duration(0);
  6.7106 +    lines2.interactive(false);
  6.7107 +    xAxis.orient('bottom').tickPadding(5);
  6.7108 +    yAxis.orient('left');
  6.7109 +    x2Axis.orient('bottom').tickPadding(5);
  6.7110 +    y2Axis.orient('left');
  6.7111 +
  6.7112 +    tooltip.valueFormatter(function(d, i) {
  6.7113 +        return yAxis.tickFormat()(d, i);
  6.7114 +    }).headerFormatter(function(d, i) {
  6.7115 +        return xAxis.tickFormat()(d, i);
  6.7116 +    });
  6.7117 +
  6.7118 +    //============================================================
  6.7119 +    // Private Variables
  6.7120 +    //------------------------------------------------------------
  6.7121 +
  6.7122 +    var stateGetter = function(data) {
  6.7123 +        return function(){
  6.7124 +            return {
  6.7125 +                active: data.map(function(d) { return !d.disabled })
  6.7126 +            };
  6.7127 +        }
  6.7128 +    };
  6.7129 +
  6.7130 +    var stateSetter = function(data) {
  6.7131 +        return function(state) {
  6.7132 +            if (state.active !== undefined)
  6.7133 +                data.forEach(function(series,i) {
  6.7134 +                    series.disabled = !state.active[i];
  6.7135 +                });
  6.7136 +        }
  6.7137 +    };
  6.7138 +
  6.7139 +    function chart(selection) {
  6.7140 +        selection.each(function(data) {
  6.7141 +            var container = d3.select(this),
  6.7142 +                that = this;
  6.7143 +            nv.utils.initSVG(container);
  6.7144 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.7145 +                availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2,
  6.7146 +                availableHeight2 = height2 - margin2.top - margin2.bottom;
  6.7147 +
  6.7148 +            chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
  6.7149 +            chart.container = this;
  6.7150 +
  6.7151 +            state
  6.7152 +                .setter(stateSetter(data), chart.update)
  6.7153 +                .getter(stateGetter(data))
  6.7154 +                .update();
  6.7155 +
  6.7156 +            // DEPRECATED set state.disableddisabled
  6.7157 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.7158 +
  6.7159 +            if (!defaultState) {
  6.7160 +                var key;
  6.7161 +                defaultState = {};
  6.7162 +                for (key in state) {
  6.7163 +                    if (state[key] instanceof Array)
  6.7164 +                        defaultState[key] = state[key].slice(0);
  6.7165 +                    else
  6.7166 +                        defaultState[key] = state[key];
  6.7167 +                }
  6.7168 +            }
  6.7169 +
  6.7170 +            // Display No Data message if there's nothing to show.
  6.7171 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.7172 +                nv.utils.noData(chart, container)
  6.7173 +                return chart;
  6.7174 +            } else {
  6.7175 +                container.selectAll('.nv-noData').remove();
  6.7176 +            }
  6.7177 +
  6.7178 +            // Setup Scales
  6.7179 +            x = lines.xScale();
  6.7180 +            y = lines.yScale();
  6.7181 +            x2 = lines2.xScale();
  6.7182 +            y2 = lines2.yScale();
  6.7183 +
  6.7184 +            // Setup containers and skeleton of chart
  6.7185 +            var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]);
  6.7186 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g');
  6.7187 +            var g = wrap.select('g');
  6.7188 +
  6.7189 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.7190 +
  6.7191 +            var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
  6.7192 +            focusEnter.append('g').attr('class', 'nv-x nv-axis');
  6.7193 +            focusEnter.append('g').attr('class', 'nv-y nv-axis');
  6.7194 +            focusEnter.append('g').attr('class', 'nv-linesWrap');
  6.7195 +            focusEnter.append('g').attr('class', 'nv-interactive');
  6.7196 +
  6.7197 +            var contextEnter = gEnter.append('g').attr('class', 'nv-context');
  6.7198 +            contextEnter.append('g').attr('class', 'nv-x nv-axis');
  6.7199 +            contextEnter.append('g').attr('class', 'nv-y nv-axis');
  6.7200 +            contextEnter.append('g').attr('class', 'nv-linesWrap');
  6.7201 +            contextEnter.append('g').attr('class', 'nv-brushBackground');
  6.7202 +            contextEnter.append('g').attr('class', 'nv-x nv-brush');
  6.7203 +
  6.7204 +            // Legend
  6.7205 +            if (showLegend) {
  6.7206 +                legend.width(availableWidth);
  6.7207 +
  6.7208 +                g.select('.nv-legendWrap')
  6.7209 +                    .datum(data)
  6.7210 +                    .call(legend);
  6.7211 +
  6.7212 +                if ( margin.top != legend.height()) {
  6.7213 +                    margin.top = legend.height();
  6.7214 +                    availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2;
  6.7215 +                }
  6.7216 +
  6.7217 +                g.select('.nv-legendWrap')
  6.7218 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.7219 +            }
  6.7220 +
  6.7221 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.7222 +
  6.7223 +            
  6.7224 +            //Set up interactive layer
  6.7225 +            if (useInteractiveGuideline) {
  6.7226 +                interactiveLayer
  6.7227 +                    .width(availableWidth)
  6.7228 +                    .height(availableHeight1)
  6.7229 +                    .margin({left:margin.left, top:margin.top})
  6.7230 +                    .svgContainer(container)
  6.7231 +                    .xScale(x);
  6.7232 +                wrap.select(".nv-interactive").call(interactiveLayer);
  6.7233 +            }
  6.7234 +
  6.7235 +            // Main Chart Component(s)
  6.7236 +            lines
  6.7237 +                .width(availableWidth)
  6.7238 +                .height(availableHeight1)
  6.7239 +                .color(
  6.7240 +                data
  6.7241 +                    .map(function(d,i) {
  6.7242 +                        return d.color || color(d, i);
  6.7243 +                    })
  6.7244 +                    .filter(function(d,i) {
  6.7245 +                        return !data[i].disabled;
  6.7246 +                    })
  6.7247 +            );
  6.7248 +
  6.7249 +            lines2
  6.7250 +                .defined(lines.defined())
  6.7251 +                .width(availableWidth)
  6.7252 +                .height(availableHeight2)
  6.7253 +                .color(
  6.7254 +                data
  6.7255 +                    .map(function(d,i) {
  6.7256 +                        return d.color || color(d, i);
  6.7257 +                    })
  6.7258 +                    .filter(function(d,i) {
  6.7259 +                        return !data[i].disabled;
  6.7260 +                    })
  6.7261 +            );
  6.7262 +
  6.7263 +            g.select('.nv-context')
  6.7264 +                .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
  6.7265 +
  6.7266 +            var contextLinesWrap = g.select('.nv-context .nv-linesWrap')
  6.7267 +                .datum(data.filter(function(d) { return !d.disabled }))
  6.7268 +
  6.7269 +            d3.transition(contextLinesWrap).call(lines2);
  6.7270 +
  6.7271 +            // Setup Main (Focus) Axes
  6.7272 +            xAxis
  6.7273 +                .scale(x)
  6.7274 +                ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.7275 +                .tickSize(-availableHeight1, 0);
  6.7276 +
  6.7277 +            yAxis
  6.7278 +                .scale(y)
  6.7279 +                ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
  6.7280 +                .tickSize( -availableWidth, 0);
  6.7281 +
  6.7282 +            g.select('.nv-focus .nv-x.nv-axis')
  6.7283 +                .attr('transform', 'translate(0,' + availableHeight1 + ')');
  6.7284 +
  6.7285 +            // Setup Brush
  6.7286 +            brush
  6.7287 +                .x(x2)
  6.7288 +                .on('brush', function() {
  6.7289 +                    onBrush();
  6.7290 +                });
  6.7291 +
  6.7292 +            if (brushExtent) brush.extent(brushExtent);
  6.7293 +
  6.7294 +            var brushBG = g.select('.nv-brushBackground').selectAll('g')
  6.7295 +                .data([brushExtent || brush.extent()])
  6.7296 +
  6.7297 +            var brushBGenter = brushBG.enter()
  6.7298 +                .append('g');
  6.7299 +
  6.7300 +            brushBGenter.append('rect')
  6.7301 +                .attr('class', 'left')
  6.7302 +                .attr('x', 0)
  6.7303 +                .attr('y', 0)
  6.7304 +                .attr('height', availableHeight2);
  6.7305 +
  6.7306 +            brushBGenter.append('rect')
  6.7307 +                .attr('class', 'right')
  6.7308 +                .attr('x', 0)
  6.7309 +                .attr('y', 0)
  6.7310 +                .attr('height', availableHeight2);
  6.7311 +
  6.7312 +            var gBrush = g.select('.nv-x.nv-brush')
  6.7313 +                .call(brush);
  6.7314 +            gBrush.selectAll('rect')
  6.7315 +                .attr('height', availableHeight2);
  6.7316 +            gBrush.selectAll('.resize').append('path').attr('d', resizePath);
  6.7317 +
  6.7318 +            onBrush();
  6.7319 +
  6.7320 +            // Setup Secondary (Context) Axes
  6.7321 +            x2Axis
  6.7322 +                .scale(x2)
  6.7323 +                ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.7324 +                .tickSize(-availableHeight2, 0);
  6.7325 +
  6.7326 +            g.select('.nv-context .nv-x.nv-axis')
  6.7327 +                .attr('transform', 'translate(0,' + y2.range()[0] + ')');
  6.7328 +            d3.transition(g.select('.nv-context .nv-x.nv-axis'))
  6.7329 +                .call(x2Axis);
  6.7330 +
  6.7331 +            y2Axis
  6.7332 +                .scale(y2)
  6.7333 +                ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) )
  6.7334 +                .tickSize( -availableWidth, 0);
  6.7335 +
  6.7336 +            d3.transition(g.select('.nv-context .nv-y.nv-axis'))
  6.7337 +                .call(y2Axis);
  6.7338 +
  6.7339 +            g.select('.nv-context .nv-x.nv-axis')
  6.7340 +                .attr('transform', 'translate(0,' + y2.range()[0] + ')');
  6.7341 +
  6.7342 +            //============================================================
  6.7343 +            // Event Handling/Dispatching (in chart's scope)
  6.7344 +            //------------------------------------------------------------
  6.7345 +
  6.7346 +            legend.dispatch.on('stateChange', function(newState) {
  6.7347 +                for (var key in newState)
  6.7348 +                    state[key] = newState[key];
  6.7349 +                dispatch.stateChange(state);
  6.7350 +                chart.update();
  6.7351 +            });
  6.7352 +
  6.7353 +            interactiveLayer.dispatch.on('elementMousemove', function(e) {
  6.7354 +                lines.clearHighlights();
  6.7355 +                var singlePoint, pointIndex, pointXLocation, allData = [];
  6.7356 +                data
  6.7357 +                    .filter(function(series, i) {
  6.7358 +                        series.seriesIndex = i;
  6.7359 +                        return !series.disabled;
  6.7360 +                    })
  6.7361 +                    .forEach(function(series,i) {
  6.7362 +                            var extent = brush.empty() ? x2.domain() : brush.extent();
  6.7363 +                            var currentValues = series.values.filter(function(d,i) {
  6.7364 +                            return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
  6.7365 +                        });
  6.7366 + 
  6.7367 +                        pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x());
  6.7368 +                        var point = currentValues[pointIndex];
  6.7369 +                        var pointYValue = chart.y()(point, pointIndex);
  6.7370 +                        if (pointYValue != null) {
  6.7371 +                            lines.highlightPoint(i, pointIndex, true);
  6.7372 +                        }
  6.7373 +                        if (point === undefined) return;
  6.7374 +                        if (singlePoint === undefined) singlePoint = point;
  6.7375 +                        if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
  6.7376 +                        allData.push({
  6.7377 +                            key: series.key,
  6.7378 +                            value: chart.y()(point, pointIndex),
  6.7379 +                            color: color(series,series.seriesIndex)
  6.7380 +                        });
  6.7381 +                    });
  6.7382 +                //Highlight the tooltip entry based on which point the mouse is closest to.
  6.7383 +                if (allData.length > 2) {
  6.7384 +                    var yValue = chart.yScale().invert(e.mouseY);
  6.7385 +                    var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);
  6.7386 +                    var threshold = 0.03 * domainExtent;
  6.7387 +                    var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);
  6.7388 +                    if (indexToHighlight !== null)
  6.7389 +                        allData[indexToHighlight].highlight = true;
  6.7390 +                }
  6.7391 +
  6.7392 +                var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
  6.7393 +                interactiveLayer.tooltip
  6.7394 +                    .position({left: e.mouseX + margin.left, top: e.mouseY + margin.top})
  6.7395 +                    .chartContainer(that.parentNode)
  6.7396 +                    .valueFormatter(function(d,i) {
  6.7397 +                        return d == null ? "N/A" : yAxis.tickFormat()(d);
  6.7398 +                    })
  6.7399 +                    .data({
  6.7400 +                        value: xValue,
  6.7401 +                        index: pointIndex,
  6.7402 +                        series: allData
  6.7403 +                    })();
  6.7404 +
  6.7405 +                interactiveLayer.renderGuideLine(pointXLocation);
  6.7406 +
  6.7407 +            });
  6.7408 +
  6.7409 +            interactiveLayer.dispatch.on("elementMouseout",function(e) {
  6.7410 +                lines.clearHighlights();
  6.7411 +            });
  6.7412 +
  6.7413 +            dispatch.on('changeState', function(e) {
  6.7414 +                if (typeof e.disabled !== 'undefined') {
  6.7415 +                    data.forEach(function(series,i) {
  6.7416 +                        series.disabled = e.disabled[i];
  6.7417 +                    });
  6.7418 +                }
  6.7419 +                chart.update();
  6.7420 +            });
  6.7421 +
  6.7422 +            //============================================================
  6.7423 +            // Functions
  6.7424 +            //------------------------------------------------------------
  6.7425 +
  6.7426 +            // Taken from crossfilter (http://square.github.com/crossfilter/)
  6.7427 +            function resizePath(d) {
  6.7428 +                var e = +(d == 'e'),
  6.7429 +                    x = e ? 1 : -1,
  6.7430 +                    y = availableHeight2 / 3;
  6.7431 +                return 'M' + (.5 * x) + ',' + y
  6.7432 +                    + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
  6.7433 +                    + 'V' + (2 * y - 6)
  6.7434 +                    + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
  6.7435 +                    + 'Z'
  6.7436 +                    + 'M' + (2.5 * x) + ',' + (y + 8)
  6.7437 +                    + 'V' + (2 * y - 8)
  6.7438 +                    + 'M' + (4.5 * x) + ',' + (y + 8)
  6.7439 +                    + 'V' + (2 * y - 8);
  6.7440 +            }
  6.7441 +
  6.7442 +
  6.7443 +            function updateBrushBG() {
  6.7444 +                if (!brush.empty()) brush.extent(brushExtent);
  6.7445 +                brushBG
  6.7446 +                    .data([brush.empty() ? x2.domain() : brushExtent])
  6.7447 +                    .each(function(d,i) {
  6.7448 +                        var leftWidth = x2(d[0]) - x.range()[0],
  6.7449 +                            rightWidth = availableWidth - x2(d[1]);
  6.7450 +                        d3.select(this).select('.left')
  6.7451 +                            .attr('width',  leftWidth < 0 ? 0 : leftWidth);
  6.7452 +
  6.7453 +                        d3.select(this).select('.right')
  6.7454 +                            .attr('x', x2(d[1]))
  6.7455 +                            .attr('width', rightWidth < 0 ? 0 : rightWidth);
  6.7456 +                    });
  6.7457 +            }
  6.7458 +
  6.7459 +
  6.7460 +            function onBrush() {
  6.7461 +                brushExtent = brush.empty() ? null : brush.extent();
  6.7462 +                var extent = brush.empty() ? x2.domain() : brush.extent();
  6.7463 +
  6.7464 +                //The brush extent cannot be less than one.  If it is, don't update the line chart.
  6.7465 +                if (Math.abs(extent[0] - extent[1]) <= 1) {
  6.7466 +                    return;
  6.7467 +                }
  6.7468 +
  6.7469 +                dispatch.brush({extent: extent, brush: brush});
  6.7470 +
  6.7471 +
  6.7472 +                updateBrushBG();
  6.7473 +
  6.7474 +                // Update Main (Focus)
  6.7475 +                var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
  6.7476 +                    .datum(
  6.7477 +                    data
  6.7478 +                        .filter(function(d) { return !d.disabled })
  6.7479 +                        .map(function(d,i) {
  6.7480 +                            return {
  6.7481 +                                key: d.key,
  6.7482 +                                area: d.area,
  6.7483 +                                values: d.values.filter(function(d,i) {
  6.7484 +                                    return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
  6.7485 +                                })
  6.7486 +                            }
  6.7487 +                        })
  6.7488 +                );
  6.7489 +                focusLinesWrap.transition().duration(transitionDuration).call(lines);
  6.7490 +
  6.7491 +
  6.7492 +                // Update Main (Focus) Axes
  6.7493 +                g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration)
  6.7494 +                    .call(xAxis);
  6.7495 +                g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration)
  6.7496 +                    .call(yAxis);
  6.7497 +            }
  6.7498 +        });
  6.7499 +
  6.7500 +        return chart;
  6.7501 +    }
  6.7502 +
  6.7503 +    //============================================================
  6.7504 +    // Event Handling/Dispatching (out of chart's scope)
  6.7505 +    //------------------------------------------------------------
  6.7506 +
  6.7507 +    lines.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.7508 +        tooltip.data(evt).position(evt.pos).hidden(false);
  6.7509 +    });
  6.7510 +
  6.7511 +    lines.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.7512 +        tooltip.hidden(true)
  6.7513 +    });
  6.7514 +
  6.7515 +    //============================================================
  6.7516 +    // Expose Public Variables
  6.7517 +    //------------------------------------------------------------
  6.7518 +
  6.7519 +    // expose chart's sub-components
  6.7520 +    chart.dispatch = dispatch;
  6.7521 +    chart.legend = legend;
  6.7522 +    chart.lines = lines;
  6.7523 +    chart.lines2 = lines2;
  6.7524 +    chart.xAxis = xAxis;
  6.7525 +    chart.yAxis = yAxis;
  6.7526 +    chart.x2Axis = x2Axis;
  6.7527 +    chart.y2Axis = y2Axis;
  6.7528 +    chart.interactiveLayer = interactiveLayer;
  6.7529 +    chart.tooltip = tooltip;
  6.7530 +
  6.7531 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.7532 +
  6.7533 +    chart._options = Object.create({}, {
  6.7534 +        // simple options, just get/set the necessary values
  6.7535 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.7536 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.7537 +        focusHeight:     {get: function(){return height2;}, set: function(_){height2=_;}},
  6.7538 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.7539 +        brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
  6.7540 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.7541 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.7542 +
  6.7543 +        // deprecated options
  6.7544 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.7545 +            // deprecated after 1.7.1
  6.7546 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.7547 +            tooltip.enabled(!!_);
  6.7548 +        }},
  6.7549 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.7550 +            // deprecated after 1.7.1
  6.7551 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.7552 +            tooltip.contentGenerator(_);
  6.7553 +        }},
  6.7554 +
  6.7555 +        // options that require extra logic in the setter
  6.7556 +        margin: {get: function(){return margin;}, set: function(_){
  6.7557 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.7558 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.7559 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.7560 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.7561 +        }},
  6.7562 +        color:  {get: function(){return color;}, set: function(_){
  6.7563 +            color = nv.utils.getColor(_);
  6.7564 +            legend.color(color);
  6.7565 +            // line color is handled above?
  6.7566 +        }},
  6.7567 +        interpolate: {get: function(){return lines.interpolate();}, set: function(_){
  6.7568 +            lines.interpolate(_);
  6.7569 +            lines2.interpolate(_);
  6.7570 +        }},
  6.7571 +        xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
  6.7572 +            xAxis.tickFormat(_);
  6.7573 +            x2Axis.tickFormat(_);
  6.7574 +        }},
  6.7575 +        yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
  6.7576 +            yAxis.tickFormat(_);
  6.7577 +            y2Axis.tickFormat(_);
  6.7578 +        }},
  6.7579 +        duration:    {get: function(){return transitionDuration;}, set: function(_){
  6.7580 +            transitionDuration=_;
  6.7581 +            yAxis.duration(transitionDuration);
  6.7582 +            y2Axis.duration(transitionDuration);
  6.7583 +            xAxis.duration(transitionDuration);
  6.7584 +            x2Axis.duration(transitionDuration);
  6.7585 +        }},
  6.7586 +        x: {get: function(){return lines.x();}, set: function(_){
  6.7587 +            lines.x(_);
  6.7588 +            lines2.x(_);
  6.7589 +        }},
  6.7590 +        y: {get: function(){return lines.y();}, set: function(_){
  6.7591 +            lines.y(_);
  6.7592 +            lines2.y(_);
  6.7593 +        }},
  6.7594 +        useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
  6.7595 +            useInteractiveGuideline = _;
  6.7596 +            if (useInteractiveGuideline) {
  6.7597 +                lines.interactive(false);
  6.7598 +                lines.useVoronoi(false);
  6.7599 +            }
  6.7600 +        }}
  6.7601 +    });
  6.7602 +
  6.7603 +    nv.utils.inheritOptions(chart, lines);
  6.7604 +    nv.utils.initOptions(chart);
  6.7605 +
  6.7606 +    return chart;
  6.7607 +};
  6.7608 +
  6.7609 +nv.models.multiBar = function() {
  6.7610 +    "use strict";
  6.7611 +
  6.7612 +    //============================================================
  6.7613 +    // Public Variables with Default Settings
  6.7614 +    //------------------------------------------------------------
  6.7615 +
  6.7616 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.7617 +        , width = 960
  6.7618 +        , height = 500
  6.7619 +        , x = d3.scale.ordinal()
  6.7620 +        , y = d3.scale.linear()
  6.7621 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.7622 +        , container = null
  6.7623 +        , getX = function(d) { return d.x }
  6.7624 +        , getY = function(d) { return d.y }
  6.7625 +        , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
  6.7626 +        , clipEdge = true
  6.7627 +        , stacked = false
  6.7628 +        , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function
  6.7629 +        , color = nv.utils.defaultColor()
  6.7630 +        , hideable = false
  6.7631 +        , barColor = null // adding the ability to set the color for each rather than the whole group
  6.7632 +        , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
  6.7633 +        , duration = 500
  6.7634 +        , xDomain
  6.7635 +        , yDomain
  6.7636 +        , xRange
  6.7637 +        , yRange
  6.7638 +        , groupSpacing = 0.1
  6.7639 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
  6.7640 +        ;
  6.7641 +
  6.7642 +    //============================================================
  6.7643 +    // Private Variables
  6.7644 +    //------------------------------------------------------------
  6.7645 +
  6.7646 +    var x0, y0 //used to store previous scales
  6.7647 +        , renderWatch = nv.utils.renderWatch(dispatch, duration)
  6.7648 +        ;
  6.7649 +
  6.7650 +    var last_datalength = 0;
  6.7651 +
  6.7652 +    function chart(selection) {
  6.7653 +        renderWatch.reset();
  6.7654 +        selection.each(function(data) {
  6.7655 +            var availableWidth = width - margin.left - margin.right,
  6.7656 +                availableHeight = height - margin.top - margin.bottom;
  6.7657 +
  6.7658 +            container = d3.select(this);
  6.7659 +            nv.utils.initSVG(container);
  6.7660 +            var nonStackableCount = 0;
  6.7661 +            // This function defines the requirements for render complete
  6.7662 +            var endFn = function(d, i) {
  6.7663 +                if (d.series === data.length - 1 && i === data[0].values.length - 1)
  6.7664 +                    return true;
  6.7665 +                return false;
  6.7666 +            };
  6.7667 +
  6.7668 +            if(hideable && data.length) hideable = [{
  6.7669 +                values: data[0].values.map(function(d) {
  6.7670 +                        return {
  6.7671 +                            x: d.x,
  6.7672 +                            y: 0,
  6.7673 +                            series: d.series,
  6.7674 +                            size: 0.01
  6.7675 +                        };}
  6.7676 +                )}];
  6.7677 +
  6.7678 +            if (stacked) {
  6.7679 +                var parsed = d3.layout.stack()
  6.7680 +                    .offset(stackOffset)
  6.7681 +                    .values(function(d){ return d.values })
  6.7682 +                    .y(getY)
  6.7683 +                (!data.length && hideable ? hideable : data);
  6.7684 +
  6.7685 +                parsed.forEach(function(series, i){
  6.7686 +                    // if series is non-stackable, use un-parsed data
  6.7687 +                    if (series.nonStackable) {
  6.7688 +                        data[i].nonStackableSeries = nonStackableCount++; 
  6.7689 +                        parsed[i] = data[i];
  6.7690 +                    } else {
  6.7691 +                        // don't stack this seires on top of the nonStackable seriees 
  6.7692 +                        if (i > 0 && parsed[i - 1].nonStackable){
  6.7693 +                            parsed[i].values.map(function(d,j){
  6.7694 +                                d.y0 -= parsed[i - 1].values[j].y;
  6.7695 +                                d.y1 = d.y0 + d.y;
  6.7696 +                            });
  6.7697 +                        }
  6.7698 +                    }
  6.7699 +                });
  6.7700 +                data = parsed;
  6.7701 +            }
  6.7702 +            //add series index and key to each data point for reference
  6.7703 +            data.forEach(function(series, i) {
  6.7704 +                series.values.forEach(function(point) {
  6.7705 +                    point.series = i;
  6.7706 +                    point.key = series.key;
  6.7707 +                });
  6.7708 +            });
  6.7709 +
  6.7710 +            // HACK for negative value stacking
  6.7711 +            if (stacked) {
  6.7712 +                data[0].values.map(function(d,i) {
  6.7713 +                    var posBase = 0, negBase = 0;
  6.7714 +                    data.map(function(d, idx) {
  6.7715 +                        if (!data[idx].nonStackable) {
  6.7716 +                            var f = d.values[i]
  6.7717 +                            f.size = Math.abs(f.y);
  6.7718 +                            if (f.y<0)  {
  6.7719 +                                f.y1 = negBase;
  6.7720 +                                negBase = negBase - f.size;
  6.7721 +                            } else
  6.7722 +                            {
  6.7723 +                                f.y1 = f.size + posBase;
  6.7724 +                                posBase = posBase + f.size;
  6.7725 +                            }
  6.7726 +                        }
  6.7727 +                        
  6.7728 +                    });
  6.7729 +                });
  6.7730 +            }
  6.7731 +            // Setup Scales
  6.7732 +            // remap and flatten the data for use in calculating the scales' domains
  6.7733 +            var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
  6.7734 +                data.map(function(d, idx) {
  6.7735 +                    return d.values.map(function(d,i) {
  6.7736 +                        return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx }
  6.7737 +                    })
  6.7738 +                });
  6.7739 +
  6.7740 +            x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
  6.7741 +                .rangeBands(xRange || [0, availableWidth], groupSpacing);
  6.7742 +
  6.7743 +            y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) {
  6.7744 +                var domain = d.y;
  6.7745 +                // increase the domain range if this series is stackable
  6.7746 +                if (stacked && !data[d.idx].nonStackable) {
  6.7747 +                    if (d.y > 0){
  6.7748 +                        domain = d.y1
  6.7749 +                    } else {
  6.7750 +                        domain = d.y1 + d.y
  6.7751 +                    }
  6.7752 +                }
  6.7753 +                return domain;
  6.7754 +            }).concat(forceY)))
  6.7755 +            .range(yRange || [availableHeight, 0]);
  6.7756 +
  6.7757 +            // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
  6.7758 +            if (x.domain()[0] === x.domain()[1])
  6.7759 +                x.domain()[0] ?
  6.7760 +                    x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
  6.7761 +                    : x.domain([-1,1]);
  6.7762 +
  6.7763 +            if (y.domain()[0] === y.domain()[1])
  6.7764 +                y.domain()[0] ?
  6.7765 +                    y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
  6.7766 +                    : y.domain([-1,1]);
  6.7767 +
  6.7768 +            x0 = x0 || x;
  6.7769 +            y0 = y0 || y;
  6.7770 +
  6.7771 +            // Setup containers and skeleton of chart
  6.7772 +            var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]);
  6.7773 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar');
  6.7774 +            var defsEnter = wrapEnter.append('defs');
  6.7775 +            var gEnter = wrapEnter.append('g');
  6.7776 +            var g = wrap.select('g');
  6.7777 +
  6.7778 +            gEnter.append('g').attr('class', 'nv-groups');
  6.7779 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.7780 +
  6.7781 +            defsEnter.append('clipPath')
  6.7782 +                .attr('id', 'nv-edge-clip-' + id)
  6.7783 +                .append('rect');
  6.7784 +            wrap.select('#nv-edge-clip-' + id + ' rect')
  6.7785 +                .attr('width', availableWidth)
  6.7786 +                .attr('height', availableHeight);
  6.7787 +
  6.7788 +            g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
  6.7789 +
  6.7790 +            var groups = wrap.select('.nv-groups').selectAll('.nv-group')
  6.7791 +                .data(function(d) { return d }, function(d,i) { return i });
  6.7792 +            groups.enter().append('g')
  6.7793 +                .style('stroke-opacity', 1e-6)
  6.7794 +                .style('fill-opacity', 1e-6);
  6.7795 +
  6.7796 +            var exitTransition = renderWatch
  6.7797 +                .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration))
  6.7798 +                .attr('y', function(d, i, j) {
  6.7799 +                    var yVal = y0(0) || 0;
  6.7800 +                    if (stacked) {
  6.7801 +                        if (data[d.series] && !data[d.series].nonStackable) {
  6.7802 +                            yVal = y0(d.y0);
  6.7803 +                        }
  6.7804 +                    }
  6.7805 +                    return yVal;
  6.7806 +                })
  6.7807 +                .attr('height', 0)
  6.7808 +                .remove();
  6.7809 +            if (exitTransition.delay)
  6.7810 +                exitTransition.delay(function(d,i) {
  6.7811 +                    var delay = i * (duration / (last_datalength + 1)) - i;
  6.7812 +                    return delay;
  6.7813 +                });
  6.7814 +            groups
  6.7815 +                .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
  6.7816 +                .classed('hover', function(d) { return d.hover })
  6.7817 +                .style('fill', function(d,i){ return color(d, i) })
  6.7818 +                .style('stroke', function(d,i){ return color(d, i) });
  6.7819 +            groups
  6.7820 +                .style('stroke-opacity', 1)
  6.7821 +                .style('fill-opacity', 0.75);
  6.7822 +
  6.7823 +            var bars = groups.selectAll('rect.nv-bar')
  6.7824 +                .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
  6.7825 +            bars.exit().remove();
  6.7826 +
  6.7827 +            var barsEnter = bars.enter().append('rect')
  6.7828 +                    .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
  6.7829 +                    .attr('x', function(d,i,j) {
  6.7830 +                        return stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length )
  6.7831 +                    })
  6.7832 +                    .attr('y', function(d,i,j) { return y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0 })
  6.7833 +                    .attr('height', 0)
  6.7834 +                    .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) })
  6.7835 +                    .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
  6.7836 +                ;
  6.7837 +            bars
  6.7838 +                .style('fill', function(d,i,j){ return color(d, j, i);  })
  6.7839 +                .style('stroke', function(d,i,j){ return color(d, j, i); })
  6.7840 +                .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
  6.7841 +                    d3.select(this).classed('hover', true);
  6.7842 +                    dispatch.elementMouseover({
  6.7843 +                        data: d,
  6.7844 +                        index: i,
  6.7845 +                        color: d3.select(this).style("fill")
  6.7846 +                    });
  6.7847 +                })
  6.7848 +                .on('mouseout', function(d,i) {
  6.7849 +                    d3.select(this).classed('hover', false);
  6.7850 +                    dispatch.elementMouseout({
  6.7851 +                        data: d,
  6.7852 +                        index: i,
  6.7853 +                        color: d3.select(this).style("fill")
  6.7854 +                    });
  6.7855 +                })
  6.7856 +                .on('mousemove', function(d,i) {
  6.7857 +                    dispatch.elementMousemove({
  6.7858 +                        data: d,
  6.7859 +                        index: i,
  6.7860 +                        color: d3.select(this).style("fill")
  6.7861 +                    });
  6.7862 +                })
  6.7863 +                .on('click', function(d,i) {
  6.7864 +                    dispatch.elementClick({
  6.7865 +                        data: d,
  6.7866 +                        index: i,
  6.7867 +                        color: d3.select(this).style("fill")
  6.7868 +                    });
  6.7869 +                    d3.event.stopPropagation();
  6.7870 +                })
  6.7871 +                .on('dblclick', function(d,i) {
  6.7872 +                    dispatch.elementDblClick({
  6.7873 +                        data: d,
  6.7874 +                        index: i,
  6.7875 +                        color: d3.select(this).style("fill")
  6.7876 +                    });
  6.7877 +                    d3.event.stopPropagation();
  6.7878 +                });
  6.7879 +            bars
  6.7880 +                .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
  6.7881 +                .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
  6.7882 +
  6.7883 +            if (barColor) {
  6.7884 +                if (!disabled) disabled = data.map(function() { return true });
  6.7885 +                bars
  6.7886 +                    .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(  disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i]  })[j]   ).toString(); })
  6.7887 +                    .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(  disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i]  })[j]   ).toString(); });
  6.7888 +            }
  6.7889 +
  6.7890 +            var barSelection =
  6.7891 +                bars.watchTransition(renderWatch, 'multibar', Math.min(250, duration))
  6.7892 +                    .delay(function(d,i) {
  6.7893 +                        return i * duration / data[0].values.length;
  6.7894 +                    });
  6.7895 +            if (stacked){
  6.7896 +                barSelection
  6.7897 +                    .attr('y', function(d,i,j) {
  6.7898 +                        var yVal = 0;
  6.7899 +                        // if stackable, stack it on top of the previous series
  6.7900 +                        if (!data[j].nonStackable) {
  6.7901 +                            yVal = y(d.y1);
  6.7902 +                        } else {
  6.7903 +                            if (getY(d,i) < 0){
  6.7904 +                                yVal = y(0);
  6.7905 +                            } else {
  6.7906 +                                if (y(0) - y(getY(d,i)) < -1){
  6.7907 +                                    yVal = y(0) - 1;
  6.7908 +                                } else {
  6.7909 +                                    yVal = y(getY(d, i)) || 0;
  6.7910 +                                }
  6.7911 +                            }
  6.7912 +                        }
  6.7913 +                        return yVal;
  6.7914 +                    })
  6.7915 +                    .attr('height', function(d,i,j) {
  6.7916 +                        if (!data[j].nonStackable) {
  6.7917 +                            return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 1);
  6.7918 +                        } else {
  6.7919 +                            return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
  6.7920 +                        }
  6.7921 +                    })
  6.7922 +                    .attr('x', function(d,i,j) {
  6.7923 +                        var width = 0;
  6.7924 +                        if (data[j].nonStackable) {
  6.7925 +                            width = d.series * x.rangeBand() / data.length;
  6.7926 +                            if (data.length !== nonStackableCount){
  6.7927 +                                width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2); 
  6.7928 +                            }
  6.7929 +                        }
  6.7930 +                        return width;
  6.7931 +                    })
  6.7932 +                    .attr('width', function(d,i,j){
  6.7933 +                        if (!data[j].nonStackable) {
  6.7934 +                            return x.rangeBand();
  6.7935 +                        } else {
  6.7936 +                            // if all series are nonStacable, take the full width
  6.7937 +                            var width = (x.rangeBand() / nonStackableCount);
  6.7938 +                            // otherwise, nonStackable graph will be only taking the half-width 
  6.7939 +                            // of the x rangeBand
  6.7940 +                            if (data.length !== nonStackableCount) {
  6.7941 +                                width = x.rangeBand()/(nonStackableCount*2);
  6.7942 +                            }
  6.7943 +                            return width;
  6.7944 +                        }
  6.7945 +                    });
  6.7946 +            }
  6.7947 +            else {
  6.7948 +                barSelection
  6.7949 +                    .attr('x', function(d,i) {
  6.7950 +                        return d.series * x.rangeBand() / data.length;
  6.7951 +                    })
  6.7952 +                    .attr('width', x.rangeBand() / data.length)
  6.7953 +                    .attr('y', function(d,i) {
  6.7954 +                        return getY(d,i) < 0 ?
  6.7955 +                            y(0) :
  6.7956 +                                y(0) - y(getY(d,i)) < 1 ?
  6.7957 +                            y(0) - 1 :
  6.7958 +                            y(getY(d,i)) || 0;
  6.7959 +                    })
  6.7960 +                    .attr('height', function(d,i) {
  6.7961 +                        return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
  6.7962 +                    });
  6.7963 +            }
  6.7964 +
  6.7965 +            //store old scales for use in transitions on update
  6.7966 +            x0 = x.copy();
  6.7967 +            y0 = y.copy();
  6.7968 +
  6.7969 +            // keep track of the last data value length for transition calculations
  6.7970 +            if (data[0] && data[0].values) {
  6.7971 +                last_datalength = data[0].values.length;
  6.7972 +            }
  6.7973 +
  6.7974 +        });
  6.7975 +
  6.7976 +        renderWatch.renderEnd('multibar immediate');
  6.7977 +
  6.7978 +        return chart;
  6.7979 +    }
  6.7980 +
  6.7981 +    //============================================================
  6.7982 +    // Expose Public Variables
  6.7983 +    //------------------------------------------------------------
  6.7984 +
  6.7985 +    chart.dispatch = dispatch;
  6.7986 +
  6.7987 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.7988 +
  6.7989 +    chart._options = Object.create({}, {
  6.7990 +        // simple options, just get/set the necessary values
  6.7991 +        width:   {get: function(){return width;}, set: function(_){width=_;}},
  6.7992 +        height:  {get: function(){return height;}, set: function(_){height=_;}},
  6.7993 +        x:       {get: function(){return getX;}, set: function(_){getX=_;}},
  6.7994 +        y:       {get: function(){return getY;}, set: function(_){getY=_;}},
  6.7995 +        xScale:  {get: function(){return x;}, set: function(_){x=_;}},
  6.7996 +        yScale:  {get: function(){return y;}, set: function(_){y=_;}},
  6.7997 +        xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.7998 +        yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.7999 +        xRange:  {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.8000 +        yRange:  {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.8001 +        forceY:  {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.8002 +        stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},
  6.8003 +        stackOffset: {get: function(){return stackOffset;}, set: function(_){stackOffset=_;}},
  6.8004 +        clipEdge:    {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
  6.8005 +        disabled:    {get: function(){return disabled;}, set: function(_){disabled=_;}},
  6.8006 +        id:          {get: function(){return id;}, set: function(_){id=_;}},
  6.8007 +        hideable:    {get: function(){return hideable;}, set: function(_){hideable=_;}},
  6.8008 +        groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
  6.8009 +
  6.8010 +        // options that require extra logic in the setter
  6.8011 +        margin: {get: function(){return margin;}, set: function(_){
  6.8012 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.8013 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.8014 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.8015 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.8016 +        }},
  6.8017 +        duration: {get: function(){return duration;}, set: function(_){
  6.8018 +            duration = _;
  6.8019 +            renderWatch.reset(duration);
  6.8020 +        }},
  6.8021 +        color:  {get: function(){return color;}, set: function(_){
  6.8022 +            color = nv.utils.getColor(_);
  6.8023 +        }},
  6.8024 +        barColor:  {get: function(){return barColor;}, set: function(_){
  6.8025 +            barColor = _ ? nv.utils.getColor(_) : null;
  6.8026 +        }}
  6.8027 +    });
  6.8028 +
  6.8029 +    nv.utils.initOptions(chart);
  6.8030 +
  6.8031 +    return chart;
  6.8032 +};
  6.8033 +nv.models.multiBarChart = function() {
  6.8034 +    "use strict";
  6.8035 +
  6.8036 +    //============================================================
  6.8037 +    // Public Variables with Default Settings
  6.8038 +    //------------------------------------------------------------
  6.8039 +
  6.8040 +    var multibar = nv.models.multiBar()
  6.8041 +        , xAxis = nv.models.axis()
  6.8042 +        , yAxis = nv.models.axis()
  6.8043 +        , legend = nv.models.legend()
  6.8044 +        , controls = nv.models.legend()
  6.8045 +        , tooltip = nv.models.tooltip()
  6.8046 +        ;
  6.8047 +
  6.8048 +    var margin = {top: 30, right: 20, bottom: 50, left: 60}
  6.8049 +        , width = null
  6.8050 +        , height = null
  6.8051 +        , color = nv.utils.defaultColor()
  6.8052 +        , showControls = true
  6.8053 +        , controlLabels = {}
  6.8054 +        , showLegend = true
  6.8055 +        , showXAxis = true
  6.8056 +        , showYAxis = true
  6.8057 +        , rightAlignYAxis = false
  6.8058 +        , reduceXTicks = true // if false a tick will show for every data point
  6.8059 +        , staggerLabels = false
  6.8060 +        , rotateLabels = 0
  6.8061 +        , x //can be accessed via chart.xScale()
  6.8062 +        , y //can be accessed via chart.yScale()
  6.8063 +        , state = nv.utils.state()
  6.8064 +        , defaultState = null
  6.8065 +        , noData = null
  6.8066 +        , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
  6.8067 +        , controlWidth = function() { return showControls ? 180 : 0 }
  6.8068 +        , duration = 250
  6.8069 +        ;
  6.8070 +
  6.8071 +    state.stacked = false // DEPRECATED Maintained for backward compatibility
  6.8072 +
  6.8073 +    multibar.stacked(false);
  6.8074 +    xAxis
  6.8075 +        .orient('bottom')
  6.8076 +        .tickPadding(7)
  6.8077 +        .showMaxMin(false)
  6.8078 +        .tickFormat(function(d) { return d })
  6.8079 +    ;
  6.8080 +    yAxis
  6.8081 +        .orient((rightAlignYAxis) ? 'right' : 'left')
  6.8082 +        .tickFormat(d3.format(',.1f'))
  6.8083 +    ;
  6.8084 +
  6.8085 +    tooltip
  6.8086 +        .duration(0)
  6.8087 +        .valueFormatter(function(d, i) {
  6.8088 +            return yAxis.tickFormat()(d, i);
  6.8089 +        })
  6.8090 +        .headerFormatter(function(d, i) {
  6.8091 +            return xAxis.tickFormat()(d, i);
  6.8092 +        });
  6.8093 +
  6.8094 +    controls.updateState(false);
  6.8095 +
  6.8096 +    //============================================================
  6.8097 +    // Private Variables
  6.8098 +    //------------------------------------------------------------
  6.8099 +
  6.8100 +    var renderWatch = nv.utils.renderWatch(dispatch);
  6.8101 +    var stacked = false;
  6.8102 +
  6.8103 +    var stateGetter = function(data) {
  6.8104 +        return function(){
  6.8105 +            return {
  6.8106 +                active: data.map(function(d) { return !d.disabled }),
  6.8107 +                stacked: stacked
  6.8108 +            };
  6.8109 +        }
  6.8110 +    };
  6.8111 +
  6.8112 +    var stateSetter = function(data) {
  6.8113 +        return function(state) {
  6.8114 +            if (state.stacked !== undefined)
  6.8115 +                stacked = state.stacked;
  6.8116 +            if (state.active !== undefined)
  6.8117 +                data.forEach(function(series,i) {
  6.8118 +                    series.disabled = !state.active[i];
  6.8119 +                });
  6.8120 +        }
  6.8121 +    };
  6.8122 +
  6.8123 +    function chart(selection) {
  6.8124 +        renderWatch.reset();
  6.8125 +        renderWatch.models(multibar);
  6.8126 +        if (showXAxis) renderWatch.models(xAxis);
  6.8127 +        if (showYAxis) renderWatch.models(yAxis);
  6.8128 +
  6.8129 +        selection.each(function(data) {
  6.8130 +            var container = d3.select(this),
  6.8131 +                that = this;
  6.8132 +            nv.utils.initSVG(container);
  6.8133 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.8134 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.8135 +
  6.8136 +            chart.update = function() {
  6.8137 +                if (duration === 0)
  6.8138 +                    container.call(chart);
  6.8139 +                else
  6.8140 +                    container.transition()
  6.8141 +                        .duration(duration)
  6.8142 +                        .call(chart);
  6.8143 +            };
  6.8144 +            chart.container = this;
  6.8145 +
  6.8146 +            state
  6.8147 +                .setter(stateSetter(data), chart.update)
  6.8148 +                .getter(stateGetter(data))
  6.8149 +                .update();
  6.8150 +
  6.8151 +            // DEPRECATED set state.disableddisabled
  6.8152 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.8153 +
  6.8154 +            if (!defaultState) {
  6.8155 +                var key;
  6.8156 +                defaultState = {};
  6.8157 +                for (key in state) {
  6.8158 +                    if (state[key] instanceof Array)
  6.8159 +                        defaultState[key] = state[key].slice(0);
  6.8160 +                    else
  6.8161 +                        defaultState[key] = state[key];
  6.8162 +                }
  6.8163 +            }
  6.8164 +
  6.8165 +            // Display noData message if there's nothing to show.
  6.8166 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.8167 +                nv.utils.noData(chart, container)
  6.8168 +                return chart;
  6.8169 +            } else {
  6.8170 +                container.selectAll('.nv-noData').remove();
  6.8171 +            }
  6.8172 +
  6.8173 +            // Setup Scales
  6.8174 +            x = multibar.xScale();
  6.8175 +            y = multibar.yScale();
  6.8176 +
  6.8177 +            // Setup containers and skeleton of chart
  6.8178 +            var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]);
  6.8179 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g');
  6.8180 +            var g = wrap.select('g');
  6.8181 +
  6.8182 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.8183 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
  6.8184 +            gEnter.append('g').attr('class', 'nv-barsWrap');
  6.8185 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.8186 +            gEnter.append('g').attr('class', 'nv-controlsWrap');
  6.8187 +
  6.8188 +            // Legend
  6.8189 +            if (showLegend) {
  6.8190 +                legend.width(availableWidth - controlWidth());
  6.8191 +
  6.8192 +                g.select('.nv-legendWrap')
  6.8193 +                    .datum(data)
  6.8194 +                    .call(legend);
  6.8195 +
  6.8196 +                if ( margin.top != legend.height()) {
  6.8197 +                    margin.top = legend.height();
  6.8198 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.8199 +                }
  6.8200 +
  6.8201 +                g.select('.nv-legendWrap')
  6.8202 +                    .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
  6.8203 +            }
  6.8204 +
  6.8205 +            // Controls
  6.8206 +            if (showControls) {
  6.8207 +                var controlsData = [
  6.8208 +                    { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },
  6.8209 +                    { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }
  6.8210 +                ];
  6.8211 +
  6.8212 +                controls.width(controlWidth()).color(['#444', '#444', '#444']);
  6.8213 +                g.select('.nv-controlsWrap')
  6.8214 +                    .datum(controlsData)
  6.8215 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.8216 +                    .call(controls);
  6.8217 +            }
  6.8218 +
  6.8219 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.8220 +            if (rightAlignYAxis) {
  6.8221 +                g.select(".nv-y.nv-axis")
  6.8222 +                    .attr("transform", "translate(" + availableWidth + ",0)");
  6.8223 +            }
  6.8224 +
  6.8225 +            // Main Chart Component(s)
  6.8226 +            multibar
  6.8227 +                .disabled(data.map(function(series) { return series.disabled }))
  6.8228 +                .width(availableWidth)
  6.8229 +                .height(availableHeight)
  6.8230 +                .color(data.map(function(d,i) {
  6.8231 +                    return d.color || color(d, i);
  6.8232 +                }).filter(function(d,i) { return !data[i].disabled }));
  6.8233 +
  6.8234 +
  6.8235 +            var barsWrap = g.select('.nv-barsWrap')
  6.8236 +                .datum(data.filter(function(d) { return !d.disabled }));
  6.8237 +
  6.8238 +            barsWrap.call(multibar);
  6.8239 +
  6.8240 +            // Setup Axes
  6.8241 +            if (showXAxis) {
  6.8242 +                xAxis
  6.8243 +                    .scale(x)
  6.8244 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.8245 +                    .tickSize(-availableHeight, 0);
  6.8246 +
  6.8247 +                g.select('.nv-x.nv-axis')
  6.8248 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')');
  6.8249 +                g.select('.nv-x.nv-axis')
  6.8250 +                    .call(xAxis);
  6.8251 +
  6.8252 +                var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g');
  6.8253 +
  6.8254 +                xTicks
  6.8255 +                    .selectAll('line, text')
  6.8256 +                    .style('opacity', 1)
  6.8257 +
  6.8258 +                if (staggerLabels) {
  6.8259 +                    var getTranslate = function(x,y) {
  6.8260 +                        return "translate(" + x + "," + y + ")";
  6.8261 +                    };
  6.8262 +
  6.8263 +                    var staggerUp = 5, staggerDown = 17;  //pixels to stagger by
  6.8264 +                    // Issue #140
  6.8265 +                    xTicks
  6.8266 +                        .selectAll("text")
  6.8267 +                        .attr('transform', function(d,i,j) {
  6.8268 +                            return  getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));
  6.8269 +                        });
  6.8270 +
  6.8271 +                    var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;
  6.8272 +                    g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text")
  6.8273 +                        .attr("transform", function(d,i) {
  6.8274 +                            return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);
  6.8275 +                        });
  6.8276 +                }
  6.8277 +
  6.8278 +                if (reduceXTicks)
  6.8279 +                    xTicks
  6.8280 +                        .filter(function(d,i) {
  6.8281 +                            return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;
  6.8282 +                        })
  6.8283 +                        .selectAll('text, line')
  6.8284 +                        .style('opacity', 0);
  6.8285 +
  6.8286 +                if(rotateLabels)
  6.8287 +                    xTicks
  6.8288 +                        .selectAll('.tick text')
  6.8289 +                        .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')
  6.8290 +                        .style('text-anchor', rotateLabels > 0 ? 'start' : 'end');
  6.8291 +
  6.8292 +                g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')
  6.8293 +                    .style('opacity', 1);
  6.8294 +            }
  6.8295 +
  6.8296 +            if (showYAxis) {
  6.8297 +                yAxis
  6.8298 +                    .scale(y)
  6.8299 +                    ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.8300 +                    .tickSize( -availableWidth, 0);
  6.8301 +
  6.8302 +                g.select('.nv-y.nv-axis')
  6.8303 +                    .call(yAxis);
  6.8304 +            }
  6.8305 +
  6.8306 +            //============================================================
  6.8307 +            // Event Handling/Dispatching (in chart's scope)
  6.8308 +            //------------------------------------------------------------
  6.8309 +
  6.8310 +            legend.dispatch.on('stateChange', function(newState) {
  6.8311 +                for (var key in newState)
  6.8312 +                    state[key] = newState[key];
  6.8313 +                dispatch.stateChange(state);
  6.8314 +                chart.update();
  6.8315 +            });
  6.8316 +
  6.8317 +            controls.dispatch.on('legendClick', function(d,i) {
  6.8318 +                if (!d.disabled) return;
  6.8319 +                controlsData = controlsData.map(function(s) {
  6.8320 +                    s.disabled = true;
  6.8321 +                    return s;
  6.8322 +                });
  6.8323 +                d.disabled = false;
  6.8324 +
  6.8325 +                switch (d.key) {
  6.8326 +                    case 'Grouped':
  6.8327 +                    case controlLabels.grouped:
  6.8328 +                        multibar.stacked(false);
  6.8329 +                        break;
  6.8330 +                    case 'Stacked':
  6.8331 +                    case controlLabels.stacked:
  6.8332 +                        multibar.stacked(true);
  6.8333 +                        break;
  6.8334 +                }
  6.8335 +
  6.8336 +                state.stacked = multibar.stacked();
  6.8337 +                dispatch.stateChange(state);
  6.8338 +                chart.update();
  6.8339 +            });
  6.8340 +
  6.8341 +            // Update chart from a state object passed to event handler
  6.8342 +            dispatch.on('changeState', function(e) {
  6.8343 +                if (typeof e.disabled !== 'undefined') {
  6.8344 +                    data.forEach(function(series,i) {
  6.8345 +                        series.disabled = e.disabled[i];
  6.8346 +                    });
  6.8347 +                    state.disabled = e.disabled;
  6.8348 +                }
  6.8349 +                if (typeof e.stacked !== 'undefined') {
  6.8350 +                    multibar.stacked(e.stacked);
  6.8351 +                    state.stacked = e.stacked;
  6.8352 +                    stacked = e.stacked;
  6.8353 +                }
  6.8354 +                chart.update();
  6.8355 +            });
  6.8356 +        });
  6.8357 +
  6.8358 +        renderWatch.renderEnd('multibarchart immediate');
  6.8359 +        return chart;
  6.8360 +    }
  6.8361 +
  6.8362 +    //============================================================
  6.8363 +    // Event Handling/Dispatching (out of chart's scope)
  6.8364 +    //------------------------------------------------------------
  6.8365 +
  6.8366 +    multibar.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.8367 +        evt.value = chart.x()(evt.data);
  6.8368 +        evt['series'] = {
  6.8369 +            key: evt.data.key,
  6.8370 +            value: chart.y()(evt.data),
  6.8371 +            color: evt.color
  6.8372 +        };
  6.8373 +        tooltip.data(evt).hidden(false);
  6.8374 +    });
  6.8375 +
  6.8376 +    multibar.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.8377 +        tooltip.hidden(true);
  6.8378 +    });
  6.8379 +
  6.8380 +    multibar.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.8381 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.8382 +    });
  6.8383 +
  6.8384 +    //============================================================
  6.8385 +    // Expose Public Variables
  6.8386 +    //------------------------------------------------------------
  6.8387 +
  6.8388 +    // expose chart's sub-components
  6.8389 +    chart.dispatch = dispatch;
  6.8390 +    chart.multibar = multibar;
  6.8391 +    chart.legend = legend;
  6.8392 +    chart.controls = controls;
  6.8393 +    chart.xAxis = xAxis;
  6.8394 +    chart.yAxis = yAxis;
  6.8395 +    chart.state = state;
  6.8396 +    chart.tooltip = tooltip;
  6.8397 +
  6.8398 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.8399 +
  6.8400 +    chart._options = Object.create({}, {
  6.8401 +        // simple options, just get/set the necessary values
  6.8402 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.8403 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.8404 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.8405 +        showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
  6.8406 +        controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
  6.8407 +        showXAxis:      {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.8408 +        showYAxis:    {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.8409 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.8410 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.8411 +        reduceXTicks:    {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}},
  6.8412 +        rotateLabels:    {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},
  6.8413 +        staggerLabels:    {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},
  6.8414 +
  6.8415 +        // deprecated options
  6.8416 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.8417 +            // deprecated after 1.7.1
  6.8418 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.8419 +            tooltip.enabled(!!_);
  6.8420 +        }},
  6.8421 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.8422 +            // deprecated after 1.7.1
  6.8423 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.8424 +            tooltip.contentGenerator(_);
  6.8425 +        }},
  6.8426 +
  6.8427 +        // options that require extra logic in the setter
  6.8428 +        margin: {get: function(){return margin;}, set: function(_){
  6.8429 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.8430 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.8431 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.8432 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.8433 +        }},
  6.8434 +        duration: {get: function(){return duration;}, set: function(_){
  6.8435 +            duration = _;
  6.8436 +            multibar.duration(duration);
  6.8437 +            xAxis.duration(duration);
  6.8438 +            yAxis.duration(duration);
  6.8439 +            renderWatch.reset(duration);
  6.8440 +        }},
  6.8441 +        color:  {get: function(){return color;}, set: function(_){
  6.8442 +            color = nv.utils.getColor(_);
  6.8443 +            legend.color(color);
  6.8444 +        }},
  6.8445 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
  6.8446 +            rightAlignYAxis = _;
  6.8447 +            yAxis.orient( rightAlignYAxis ? 'right' : 'left');
  6.8448 +        }},
  6.8449 +        barColor:  {get: function(){return multibar.barColor;}, set: function(_){
  6.8450 +            multibar.barColor(_);
  6.8451 +            legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})
  6.8452 +        }}
  6.8453 +    });
  6.8454 +
  6.8455 +    nv.utils.inheritOptions(chart, multibar);
  6.8456 +    nv.utils.initOptions(chart);
  6.8457 +
  6.8458 +    return chart;
  6.8459 +};
  6.8460 +
  6.8461 +nv.models.multiBarHorizontal = function() {
  6.8462 +    "use strict";
  6.8463 +
  6.8464 +    //============================================================
  6.8465 +    // Public Variables with Default Settings
  6.8466 +    //------------------------------------------------------------
  6.8467 +
  6.8468 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.8469 +        , width = 960
  6.8470 +        , height = 500
  6.8471 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.8472 +        , container = null
  6.8473 +        , x = d3.scale.ordinal()
  6.8474 +        , y = d3.scale.linear()
  6.8475 +        , getX = function(d) { return d.x }
  6.8476 +        , getY = function(d) { return d.y }
  6.8477 +        , getYerr = function(d) { return d.yErr }
  6.8478 +        , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
  6.8479 +        , color = nv.utils.defaultColor()
  6.8480 +        , barColor = null // adding the ability to set the color for each rather than the whole group
  6.8481 +        , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
  6.8482 +        , stacked = false
  6.8483 +        , showValues = false
  6.8484 +        , showBarLabels = false
  6.8485 +        , valuePadding = 60
  6.8486 +        , groupSpacing = 0.1
  6.8487 +        , valueFormat = d3.format(',.2f')
  6.8488 +        , delay = 1200
  6.8489 +        , xDomain
  6.8490 +        , yDomain
  6.8491 +        , xRange
  6.8492 +        , yRange
  6.8493 +        , duration = 250
  6.8494 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
  6.8495 +        ;
  6.8496 +
  6.8497 +    //============================================================
  6.8498 +    // Private Variables
  6.8499 +    //------------------------------------------------------------
  6.8500 +
  6.8501 +    var x0, y0; //used to store previous scales
  6.8502 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.8503 +
  6.8504 +    function chart(selection) {
  6.8505 +        renderWatch.reset();
  6.8506 +        selection.each(function(data) {
  6.8507 +            var availableWidth = width - margin.left - margin.right,
  6.8508 +                availableHeight = height - margin.top - margin.bottom;
  6.8509 +
  6.8510 +            container = d3.select(this);
  6.8511 +            nv.utils.initSVG(container);
  6.8512 +
  6.8513 +            if (stacked)
  6.8514 +                data = d3.layout.stack()
  6.8515 +                    .offset('zero')
  6.8516 +                    .values(function(d){ return d.values })
  6.8517 +                    .y(getY)
  6.8518 +                (data);
  6.8519 +
  6.8520 +            //add series index and key to each data point for reference
  6.8521 +            data.forEach(function(series, i) {
  6.8522 +                series.values.forEach(function(point) {
  6.8523 +                    point.series = i;
  6.8524 +                    point.key = series.key;
  6.8525 +                });
  6.8526 +            });
  6.8527 +
  6.8528 +            // HACK for negative value stacking
  6.8529 +            if (stacked)
  6.8530 +                data[0].values.map(function(d,i) {
  6.8531 +                    var posBase = 0, negBase = 0;
  6.8532 +                    data.map(function(d) {
  6.8533 +                        var f = d.values[i]
  6.8534 +                        f.size = Math.abs(f.y);
  6.8535 +                        if (f.y<0)  {
  6.8536 +                            f.y1 = negBase - f.size;
  6.8537 +                            negBase = negBase - f.size;
  6.8538 +                        } else
  6.8539 +                        {
  6.8540 +                            f.y1 = posBase;
  6.8541 +                            posBase = posBase + f.size;
  6.8542 +                        }
  6.8543 +                    });
  6.8544 +                });
  6.8545 +
  6.8546 +            // Setup Scales
  6.8547 +            // remap and flatten the data for use in calculating the scales' domains
  6.8548 +            var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
  6.8549 +                data.map(function(d) {
  6.8550 +                    return d.values.map(function(d,i) {
  6.8551 +                        return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
  6.8552 +                    })
  6.8553 +                });
  6.8554 +
  6.8555 +            x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
  6.8556 +                .rangeBands(xRange || [0, availableHeight], groupSpacing);
  6.8557 +
  6.8558 +            y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY)))
  6.8559 +
  6.8560 +            if (showValues && !stacked)
  6.8561 +                y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);
  6.8562 +            else
  6.8563 +                y.range(yRange || [0, availableWidth]);
  6.8564 +
  6.8565 +            x0 = x0 || x;
  6.8566 +            y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]);
  6.8567 +
  6.8568 +            // Setup containers and skeleton of chart
  6.8569 +            var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]);
  6.8570 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal');
  6.8571 +            var defsEnter = wrapEnter.append('defs');
  6.8572 +            var gEnter = wrapEnter.append('g');
  6.8573 +            var g = wrap.select('g');
  6.8574 +
  6.8575 +            gEnter.append('g').attr('class', 'nv-groups');
  6.8576 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.8577 +
  6.8578 +            var groups = wrap.select('.nv-groups').selectAll('.nv-group')
  6.8579 +                .data(function(d) { return d }, function(d,i) { return i });
  6.8580 +            groups.enter().append('g')
  6.8581 +                .style('stroke-opacity', 1e-6)
  6.8582 +                .style('fill-opacity', 1e-6);
  6.8583 +            groups.exit().watchTransition(renderWatch, 'multibarhorizontal: exit groups')
  6.8584 +                .style('stroke-opacity', 1e-6)
  6.8585 +                .style('fill-opacity', 1e-6)
  6.8586 +                .remove();
  6.8587 +            groups
  6.8588 +                .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
  6.8589 +                .classed('hover', function(d) { return d.hover })
  6.8590 +                .style('fill', function(d,i){ return color(d, i) })
  6.8591 +                .style('stroke', function(d,i){ return color(d, i) });
  6.8592 +            groups.watchTransition(renderWatch, 'multibarhorizontal: groups')
  6.8593 +                .style('stroke-opacity', 1)
  6.8594 +                .style('fill-opacity', .75);
  6.8595 +
  6.8596 +            var bars = groups.selectAll('g.nv-bar')
  6.8597 +                .data(function(d) { return d.values });
  6.8598 +            bars.exit().remove();
  6.8599 +
  6.8600 +            var barsEnter = bars.enter().append('g')
  6.8601 +                .attr('transform', function(d,i,j) {
  6.8602 +                    return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')'
  6.8603 +                });
  6.8604 +
  6.8605 +            barsEnter.append('rect')
  6.8606 +                .attr('width', 0)
  6.8607 +                .attr('height', x.rangeBand() / (stacked ? 1 : data.length) )
  6.8608 +
  6.8609 +            bars
  6.8610 +                .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
  6.8611 +                    d3.select(this).classed('hover', true);
  6.8612 +                    dispatch.elementMouseover({
  6.8613 +                        data: d,
  6.8614 +                        index: i,
  6.8615 +                        color: d3.select(this).style("fill")
  6.8616 +                    });
  6.8617 +                })
  6.8618 +                .on('mouseout', function(d,i) {
  6.8619 +                    d3.select(this).classed('hover', false);
  6.8620 +                    dispatch.elementMouseout({
  6.8621 +                        data: d,
  6.8622 +                        index: i,
  6.8623 +                        color: d3.select(this).style("fill")
  6.8624 +                    });
  6.8625 +                })
  6.8626 +                .on('mouseout', function(d,i) {
  6.8627 +                    dispatch.elementMouseout({
  6.8628 +                        data: d,
  6.8629 +                        index: i,
  6.8630 +                        color: d3.select(this).style("fill")
  6.8631 +                    });
  6.8632 +                })
  6.8633 +                .on('mousemove', function(d,i) {
  6.8634 +                    dispatch.elementMousemove({
  6.8635 +                        data: d,
  6.8636 +                        index: i,
  6.8637 +                        color: d3.select(this).style("fill")
  6.8638 +                    });
  6.8639 +                })
  6.8640 +                .on('click', function(d,i) {
  6.8641 +                    dispatch.elementClick({
  6.8642 +                        data: d,
  6.8643 +                        index: i,
  6.8644 +                        color: d3.select(this).style("fill")
  6.8645 +                    });
  6.8646 +                    d3.event.stopPropagation();
  6.8647 +                })
  6.8648 +                .on('dblclick', function(d,i) {
  6.8649 +                    dispatch.elementDblClick({
  6.8650 +                        data: d,
  6.8651 +                        index: i,
  6.8652 +                        color: d3.select(this).style("fill")
  6.8653 +                    });
  6.8654 +                    d3.event.stopPropagation();
  6.8655 +                });
  6.8656 +
  6.8657 +            if (getYerr(data[0],0)) {
  6.8658 +                barsEnter.append('polyline');
  6.8659 +
  6.8660 +                bars.select('polyline')
  6.8661 +                    .attr('fill', 'none')
  6.8662 +                    .attr('points', function(d,i) {
  6.8663 +                        var xerr = getYerr(d,i)
  6.8664 +                            , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2);
  6.8665 +                        xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)];
  6.8666 +                        xerr = xerr.map(function(e) { return y(e) - y(0); });
  6.8667 +                        var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]];
  6.8668 +                        return a.map(function (path) { return path.join(',') }).join(' ');
  6.8669 +                    })
  6.8670 +                    .attr('transform', function(d,i) {
  6.8671 +                        var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2);
  6.8672 +                        return 'translate(' + (getY(d,i) < 0 ? 0 : y(getY(d,i)) - y(0)) + ', ' + mid + ')'
  6.8673 +                    });
  6.8674 +            }
  6.8675 +
  6.8676 +            barsEnter.append('text');
  6.8677 +
  6.8678 +            if (showValues && !stacked) {
  6.8679 +                bars.select('text')
  6.8680 +                    .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
  6.8681 +                    .attr('y', x.rangeBand() / (data.length * 2))
  6.8682 +                    .attr('dy', '.32em')
  6.8683 +                    .text(function(d,i) {
  6.8684 +                        var t = valueFormat(getY(d,i))
  6.8685 +                            , yerr = getYerr(d,i);
  6.8686 +                        if (yerr === undefined)
  6.8687 +                            return t;
  6.8688 +                        if (!yerr.length)
  6.8689 +                            return t + '±' + valueFormat(Math.abs(yerr));
  6.8690 +                        return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0]));
  6.8691 +                    });
  6.8692 +                bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
  6.8693 +                    .select('text')
  6.8694 +                    .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })
  6.8695 +            } else {
  6.8696 +                bars.selectAll('text').text('');
  6.8697 +            }
  6.8698 +
  6.8699 +            if (showBarLabels && !stacked) {
  6.8700 +                barsEnter.append('text').classed('nv-bar-label',true);
  6.8701 +                bars.select('text.nv-bar-label')
  6.8702 +                    .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' })
  6.8703 +                    .attr('y', x.rangeBand() / (data.length * 2))
  6.8704 +                    .attr('dy', '.32em')
  6.8705 +                    .text(function(d,i) { return getX(d,i) });
  6.8706 +                bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
  6.8707 +                    .select('text.nv-bar-label')
  6.8708 +                    .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 });
  6.8709 +            }
  6.8710 +            else {
  6.8711 +                bars.selectAll('text.nv-bar-label').text('');
  6.8712 +            }
  6.8713 +
  6.8714 +            bars
  6.8715 +                .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
  6.8716 +
  6.8717 +            if (barColor) {
  6.8718 +                if (!disabled) disabled = data.map(function() { return true });
  6.8719 +                bars
  6.8720 +                    .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(  disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i]  })[j]   ).toString(); })
  6.8721 +                    .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(  disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i]  })[j]   ).toString(); });
  6.8722 +            }
  6.8723 +
  6.8724 +            if (stacked)
  6.8725 +                bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
  6.8726 +                    .attr('transform', function(d,i) {
  6.8727 +                        return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'
  6.8728 +                    })
  6.8729 +                    .select('rect')
  6.8730 +                    .attr('width', function(d,i) {
  6.8731 +                        return Math.abs(y(getY(d,i) + d.y0) - y(d.y0))
  6.8732 +                    })
  6.8733 +                    .attr('height', x.rangeBand() );
  6.8734 +            else
  6.8735 +                bars.watchTransition(renderWatch, 'multibarhorizontal: bars')
  6.8736 +                    .attr('transform', function(d,i) {
  6.8737 +                        //TODO: stacked must be all positive or all negative, not both?
  6.8738 +                        return 'translate(' +
  6.8739 +                            (getY(d,i) < 0 ? y(getY(d,i)) : y(0))
  6.8740 +                            + ',' +
  6.8741 +                            (d.series * x.rangeBand() / data.length
  6.8742 +                                +
  6.8743 +                                x(getX(d,i)) )
  6.8744 +                            + ')'
  6.8745 +                    })
  6.8746 +                    .select('rect')
  6.8747 +                    .attr('height', x.rangeBand() / data.length )
  6.8748 +                    .attr('width', function(d,i) {
  6.8749 +                        return Math.max(Math.abs(y(getY(d,i)) - y(0)),1)
  6.8750 +                    });
  6.8751 +
  6.8752 +            //store old scales for use in transitions on update
  6.8753 +            x0 = x.copy();
  6.8754 +            y0 = y.copy();
  6.8755 +
  6.8756 +        });
  6.8757 +
  6.8758 +        renderWatch.renderEnd('multibarHorizontal immediate');
  6.8759 +        return chart;
  6.8760 +    }
  6.8761 +
  6.8762 +    //============================================================
  6.8763 +    // Expose Public Variables
  6.8764 +    //------------------------------------------------------------
  6.8765 +
  6.8766 +    chart.dispatch = dispatch;
  6.8767 +
  6.8768 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.8769 +
  6.8770 +    chart._options = Object.create({}, {
  6.8771 +        // simple options, just get/set the necessary values
  6.8772 +        width:   {get: function(){return width;}, set: function(_){width=_;}},
  6.8773 +        height:  {get: function(){return height;}, set: function(_){height=_;}},
  6.8774 +        x:       {get: function(){return getX;}, set: function(_){getX=_;}},
  6.8775 +        y:       {get: function(){return getY;}, set: function(_){getY=_;}},
  6.8776 +        yErr:       {get: function(){return getYerr;}, set: function(_){getYerr=_;}},
  6.8777 +        xScale:  {get: function(){return x;}, set: function(_){x=_;}},
  6.8778 +        yScale:  {get: function(){return y;}, set: function(_){y=_;}},
  6.8779 +        xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.8780 +        yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.8781 +        xRange:  {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.8782 +        yRange:  {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.8783 +        forceY:  {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.8784 +        stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},
  6.8785 +        showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},
  6.8786 +        // this shows the group name, seems pointless?
  6.8787 +        //showBarLabels:    {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}},
  6.8788 +        disabled:     {get: function(){return disabled;}, set: function(_){disabled=_;}},
  6.8789 +        id:           {get: function(){return id;}, set: function(_){id=_;}},
  6.8790 +        valueFormat:  {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
  6.8791 +        valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}},
  6.8792 +        groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
  6.8793 +
  6.8794 +        // options that require extra logic in the setter
  6.8795 +        margin: {get: function(){return margin;}, set: function(_){
  6.8796 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.8797 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.8798 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.8799 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.8800 +        }},
  6.8801 +        duration: {get: function(){return duration;}, set: function(_){
  6.8802 +            duration = _;
  6.8803 +            renderWatch.reset(duration);
  6.8804 +        }},
  6.8805 +        color:  {get: function(){return color;}, set: function(_){
  6.8806 +            color = nv.utils.getColor(_);
  6.8807 +        }},
  6.8808 +        barColor:  {get: function(){return barColor;}, set: function(_){
  6.8809 +            barColor = _ ? nv.utils.getColor(_) : null;
  6.8810 +        }}
  6.8811 +    });
  6.8812 +
  6.8813 +    nv.utils.initOptions(chart);
  6.8814 +
  6.8815 +    return chart;
  6.8816 +};
  6.8817 +
  6.8818 +nv.models.multiBarHorizontalChart = function() {
  6.8819 +    "use strict";
  6.8820 +
  6.8821 +    //============================================================
  6.8822 +    // Public Variables with Default Settings
  6.8823 +    //------------------------------------------------------------
  6.8824 +
  6.8825 +    var multibar = nv.models.multiBarHorizontal()
  6.8826 +        , xAxis = nv.models.axis()
  6.8827 +        , yAxis = nv.models.axis()
  6.8828 +        , legend = nv.models.legend().height(30)
  6.8829 +        , controls = nv.models.legend().height(30)
  6.8830 +        , tooltip = nv.models.tooltip()
  6.8831 +        ;
  6.8832 +
  6.8833 +    var margin = {top: 30, right: 20, bottom: 50, left: 60}
  6.8834 +        , width = null
  6.8835 +        , height = null
  6.8836 +        , color = nv.utils.defaultColor()
  6.8837 +        , showControls = true
  6.8838 +        , controlLabels = {}
  6.8839 +        , showLegend = true
  6.8840 +        , showXAxis = true
  6.8841 +        , showYAxis = true
  6.8842 +        , stacked = false
  6.8843 +        , x //can be accessed via chart.xScale()
  6.8844 +        , y //can be accessed via chart.yScale()
  6.8845 +        , state = nv.utils.state()
  6.8846 +        , defaultState = null
  6.8847 +        , noData = null
  6.8848 +        , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')
  6.8849 +        , controlWidth = function() { return showControls ? 180 : 0 }
  6.8850 +        , duration = 250
  6.8851 +        ;
  6.8852 +
  6.8853 +    state.stacked = false; // DEPRECATED Maintained for backward compatibility
  6.8854 +
  6.8855 +    multibar.stacked(stacked);
  6.8856 +
  6.8857 +    xAxis
  6.8858 +        .orient('left')
  6.8859 +        .tickPadding(5)
  6.8860 +        .showMaxMin(false)
  6.8861 +        .tickFormat(function(d) { return d })
  6.8862 +    ;
  6.8863 +    yAxis
  6.8864 +        .orient('bottom')
  6.8865 +        .tickFormat(d3.format(',.1f'))
  6.8866 +    ;
  6.8867 +
  6.8868 +    tooltip
  6.8869 +        .duration(0)
  6.8870 +        .valueFormatter(function(d, i) {
  6.8871 +            return yAxis.tickFormat()(d, i);
  6.8872 +        })
  6.8873 +        .headerFormatter(function(d, i) {
  6.8874 +            return xAxis.tickFormat()(d, i);
  6.8875 +        });
  6.8876 +
  6.8877 +    controls.updateState(false);
  6.8878 +
  6.8879 +    //============================================================
  6.8880 +    // Private Variables
  6.8881 +    //------------------------------------------------------------
  6.8882 +
  6.8883 +    var stateGetter = function(data) {
  6.8884 +        return function(){
  6.8885 +            return {
  6.8886 +                active: data.map(function(d) { return !d.disabled }),
  6.8887 +                stacked: stacked
  6.8888 +            };
  6.8889 +        }
  6.8890 +    };
  6.8891 +
  6.8892 +    var stateSetter = function(data) {
  6.8893 +        return function(state) {
  6.8894 +            if (state.stacked !== undefined)
  6.8895 +                stacked = state.stacked;
  6.8896 +            if (state.active !== undefined)
  6.8897 +                data.forEach(function(series,i) {
  6.8898 +                    series.disabled = !state.active[i];
  6.8899 +                });
  6.8900 +        }
  6.8901 +    };
  6.8902 +
  6.8903 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
  6.8904 +
  6.8905 +    function chart(selection) {
  6.8906 +        renderWatch.reset();
  6.8907 +        renderWatch.models(multibar);
  6.8908 +        if (showXAxis) renderWatch.models(xAxis);
  6.8909 +        if (showYAxis) renderWatch.models(yAxis);
  6.8910 +
  6.8911 +        selection.each(function(data) {
  6.8912 +            var container = d3.select(this),
  6.8913 +                that = this;
  6.8914 +            nv.utils.initSVG(container);
  6.8915 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.8916 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.8917 +
  6.8918 +            chart.update = function() { container.transition().duration(duration).call(chart) };
  6.8919 +            chart.container = this;
  6.8920 +
  6.8921 +            stacked = multibar.stacked();
  6.8922 +
  6.8923 +            state
  6.8924 +                .setter(stateSetter(data), chart.update)
  6.8925 +                .getter(stateGetter(data))
  6.8926 +                .update();
  6.8927 +
  6.8928 +            // DEPRECATED set state.disableddisabled
  6.8929 +            state.disabled = data.map(function(d) { return !!d.disabled });
  6.8930 +
  6.8931 +            if (!defaultState) {
  6.8932 +                var key;
  6.8933 +                defaultState = {};
  6.8934 +                for (key in state) {
  6.8935 +                    if (state[key] instanceof Array)
  6.8936 +                        defaultState[key] = state[key].slice(0);
  6.8937 +                    else
  6.8938 +                        defaultState[key] = state[key];
  6.8939 +                }
  6.8940 +            }
  6.8941 +
  6.8942 +            // Display No Data message if there's nothing to show.
  6.8943 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.8944 +                nv.utils.noData(chart, container)
  6.8945 +                return chart;
  6.8946 +            } else {
  6.8947 +                container.selectAll('.nv-noData').remove();
  6.8948 +            }
  6.8949 +
  6.8950 +            // Setup Scales
  6.8951 +            x = multibar.xScale();
  6.8952 +            y = multibar.yScale();
  6.8953 +
  6.8954 +            // Setup containers and skeleton of chart
  6.8955 +            var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]);
  6.8956 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g');
  6.8957 +            var g = wrap.select('g');
  6.8958 +
  6.8959 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.8960 +            gEnter.append('g').attr('class', 'nv-y nv-axis')
  6.8961 +                .append('g').attr('class', 'nv-zeroLine')
  6.8962 +                .append('line');
  6.8963 +            gEnter.append('g').attr('class', 'nv-barsWrap');
  6.8964 +            gEnter.append('g').attr('class', 'nv-legendWrap');
  6.8965 +            gEnter.append('g').attr('class', 'nv-controlsWrap');
  6.8966 +
  6.8967 +            // Legend
  6.8968 +            if (showLegend) {
  6.8969 +                legend.width(availableWidth - controlWidth());
  6.8970 +
  6.8971 +                g.select('.nv-legendWrap')
  6.8972 +                    .datum(data)
  6.8973 +                    .call(legend);
  6.8974 +
  6.8975 +                if ( margin.top != legend.height()) {
  6.8976 +                    margin.top = legend.height();
  6.8977 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.8978 +                }
  6.8979 +
  6.8980 +                g.select('.nv-legendWrap')
  6.8981 +                    .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
  6.8982 +            }
  6.8983 +
  6.8984 +            // Controls
  6.8985 +            if (showControls) {
  6.8986 +                var controlsData = [
  6.8987 +                    { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },
  6.8988 +                    { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }
  6.8989 +                ];
  6.8990 +
  6.8991 +                controls.width(controlWidth()).color(['#444', '#444', '#444']);
  6.8992 +                g.select('.nv-controlsWrap')
  6.8993 +                    .datum(controlsData)
  6.8994 +                    .attr('transform', 'translate(0,' + (-margin.top) +')')
  6.8995 +                    .call(controls);
  6.8996 +            }
  6.8997 +
  6.8998 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.8999 +
  6.9000 +            // Main Chart Component(s)
  6.9001 +            multibar
  6.9002 +                .disabled(data.map(function(series) { return series.disabled }))
  6.9003 +                .width(availableWidth)
  6.9004 +                .height(availableHeight)
  6.9005 +                .color(data.map(function(d,i) {
  6.9006 +                    return d.color || color(d, i);
  6.9007 +                }).filter(function(d,i) { return !data[i].disabled }));
  6.9008 +
  6.9009 +            var barsWrap = g.select('.nv-barsWrap')
  6.9010 +                .datum(data.filter(function(d) { return !d.disabled }));
  6.9011 +
  6.9012 +            barsWrap.transition().call(multibar);
  6.9013 +
  6.9014 +            // Setup Axes
  6.9015 +            if (showXAxis) {
  6.9016 +                xAxis
  6.9017 +                    .scale(x)
  6.9018 +                    ._ticks( nv.utils.calcTicksY(availableHeight/24, data) )
  6.9019 +                    .tickSize(-availableWidth, 0);
  6.9020 +
  6.9021 +                g.select('.nv-x.nv-axis').call(xAxis);
  6.9022 +
  6.9023 +                var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
  6.9024 +
  6.9025 +                xTicks
  6.9026 +                    .selectAll('line, text');
  6.9027 +            }
  6.9028 +
  6.9029 +            if (showYAxis) {
  6.9030 +                yAxis
  6.9031 +                    .scale(y)
  6.9032 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.9033 +                    .tickSize( -availableHeight, 0);
  6.9034 +
  6.9035 +                g.select('.nv-y.nv-axis')
  6.9036 +                    .attr('transform', 'translate(0,' + availableHeight + ')');
  6.9037 +                g.select('.nv-y.nv-axis').call(yAxis);
  6.9038 +            }
  6.9039 +
  6.9040 +            // Zero line
  6.9041 +            g.select(".nv-zeroLine line")
  6.9042 +                .attr("x1", y(0))
  6.9043 +                .attr("x2", y(0))
  6.9044 +                .attr("y1", 0)
  6.9045 +                .attr("y2", -availableHeight)
  6.9046 +            ;
  6.9047 +
  6.9048 +            //============================================================
  6.9049 +            // Event Handling/Dispatching (in chart's scope)
  6.9050 +            //------------------------------------------------------------
  6.9051 +
  6.9052 +            legend.dispatch.on('stateChange', function(newState) {
  6.9053 +                for (var key in newState)
  6.9054 +                    state[key] = newState[key];
  6.9055 +                dispatch.stateChange(state);
  6.9056 +                chart.update();
  6.9057 +            });
  6.9058 +
  6.9059 +            controls.dispatch.on('legendClick', function(d,i) {
  6.9060 +                if (!d.disabled) return;
  6.9061 +                controlsData = controlsData.map(function(s) {
  6.9062 +                    s.disabled = true;
  6.9063 +                    return s;
  6.9064 +                });
  6.9065 +                d.disabled = false;
  6.9066 +
  6.9067 +                switch (d.key) {
  6.9068 +                    case 'Grouped':
  6.9069 +                        multibar.stacked(false);
  6.9070 +                        break;
  6.9071 +                    case 'Stacked':
  6.9072 +                        multibar.stacked(true);
  6.9073 +                        break;
  6.9074 +                }
  6.9075 +
  6.9076 +                state.stacked = multibar.stacked();
  6.9077 +                dispatch.stateChange(state);
  6.9078 +                stacked = multibar.stacked();
  6.9079 +
  6.9080 +                chart.update();
  6.9081 +            });
  6.9082 +
  6.9083 +            // Update chart from a state object passed to event handler
  6.9084 +            dispatch.on('changeState', function(e) {
  6.9085 +
  6.9086 +                if (typeof e.disabled !== 'undefined') {
  6.9087 +                    data.forEach(function(series,i) {
  6.9088 +                        series.disabled = e.disabled[i];
  6.9089 +                    });
  6.9090 +
  6.9091 +                    state.disabled = e.disabled;
  6.9092 +                }
  6.9093 +
  6.9094 +                if (typeof e.stacked !== 'undefined') {
  6.9095 +                    multibar.stacked(e.stacked);
  6.9096 +                    state.stacked = e.stacked;
  6.9097 +                    stacked = e.stacked;
  6.9098 +                }
  6.9099 +
  6.9100 +                chart.update();
  6.9101 +            });
  6.9102 +        });
  6.9103 +        renderWatch.renderEnd('multibar horizontal chart immediate');
  6.9104 +        return chart;
  6.9105 +    }
  6.9106 +
  6.9107 +    //============================================================
  6.9108 +    // Event Handling/Dispatching (out of chart's scope)
  6.9109 +    //------------------------------------------------------------
  6.9110 +
  6.9111 +    multibar.dispatch.on('elementMouseover.tooltip', function(evt) {
  6.9112 +        evt.value = chart.x()(evt.data);
  6.9113 +        evt['series'] = {
  6.9114 +            key: evt.data.key,
  6.9115 +            value: chart.y()(evt.data),
  6.9116 +            color: evt.color
  6.9117 +        };
  6.9118 +        tooltip.data(evt).hidden(false);
  6.9119 +    });
  6.9120 +
  6.9121 +    multibar.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9122 +        tooltip.hidden(true);
  6.9123 +    });
  6.9124 +
  6.9125 +    multibar.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.9126 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.9127 +    });
  6.9128 +
  6.9129 +    //============================================================
  6.9130 +    // Expose Public Variables
  6.9131 +    //------------------------------------------------------------
  6.9132 +
  6.9133 +    // expose chart's sub-components
  6.9134 +    chart.dispatch = dispatch;
  6.9135 +    chart.multibar = multibar;
  6.9136 +    chart.legend = legend;
  6.9137 +    chart.controls = controls;
  6.9138 +    chart.xAxis = xAxis;
  6.9139 +    chart.yAxis = yAxis;
  6.9140 +    chart.state = state;
  6.9141 +    chart.tooltip = tooltip;
  6.9142 +
  6.9143 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.9144 +
  6.9145 +    chart._options = Object.create({}, {
  6.9146 +        // simple options, just get/set the necessary values
  6.9147 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.9148 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.9149 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.9150 +        showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
  6.9151 +        controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
  6.9152 +        showXAxis:      {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
  6.9153 +        showYAxis:    {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
  6.9154 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
  6.9155 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.9156 +
  6.9157 +        // deprecated options
  6.9158 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.9159 +            // deprecated after 1.7.1
  6.9160 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.9161 +            tooltip.enabled(!!_);
  6.9162 +        }},
  6.9163 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.9164 +            // deprecated after 1.7.1
  6.9165 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.9166 +            tooltip.contentGenerator(_);
  6.9167 +        }},
  6.9168 +
  6.9169 +        // options that require extra logic in the setter
  6.9170 +        margin: {get: function(){return margin;}, set: function(_){
  6.9171 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.9172 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.9173 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.9174 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.9175 +        }},
  6.9176 +        duration: {get: function(){return duration;}, set: function(_){
  6.9177 +            duration = _;
  6.9178 +            renderWatch.reset(duration);
  6.9179 +            multibar.duration(duration);
  6.9180 +            xAxis.duration(duration);
  6.9181 +            yAxis.duration(duration);
  6.9182 +        }},
  6.9183 +        color:  {get: function(){return color;}, set: function(_){
  6.9184 +            color = nv.utils.getColor(_);
  6.9185 +            legend.color(color);
  6.9186 +        }},
  6.9187 +        barColor:  {get: function(){return multibar.barColor;}, set: function(_){
  6.9188 +            multibar.barColor(_);
  6.9189 +            legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})
  6.9190 +        }}
  6.9191 +    });
  6.9192 +
  6.9193 +    nv.utils.inheritOptions(chart, multibar);
  6.9194 +    nv.utils.initOptions(chart);
  6.9195 +
  6.9196 +    return chart;
  6.9197 +};
  6.9198 +nv.models.multiChart = function() {
  6.9199 +    "use strict";
  6.9200 +
  6.9201 +    //============================================================
  6.9202 +    // Public Variables with Default Settings
  6.9203 +    //------------------------------------------------------------
  6.9204 +
  6.9205 +    var margin = {top: 30, right: 20, bottom: 50, left: 60},
  6.9206 +        color = nv.utils.defaultColor(),
  6.9207 +        width = null,
  6.9208 +        height = null,
  6.9209 +        showLegend = true,
  6.9210 +        noData = null,
  6.9211 +        yDomain1,
  6.9212 +        yDomain2,
  6.9213 +        getX = function(d) { return d.x },
  6.9214 +        getY = function(d) { return d.y},
  6.9215 +        interpolate = 'monotone',
  6.9216 +        useVoronoi = true
  6.9217 +        ;
  6.9218 +
  6.9219 +    //============================================================
  6.9220 +    // Private Variables
  6.9221 +    //------------------------------------------------------------
  6.9222 +
  6.9223 +    var x = d3.scale.linear(),
  6.9224 +        yScale1 = d3.scale.linear(),
  6.9225 +        yScale2 = d3.scale.linear(),
  6.9226 +
  6.9227 +        lines1 = nv.models.line().yScale(yScale1),
  6.9228 +        lines2 = nv.models.line().yScale(yScale2),
  6.9229 +
  6.9230 +        bars1 = nv.models.multiBar().stacked(false).yScale(yScale1),
  6.9231 +        bars2 = nv.models.multiBar().stacked(false).yScale(yScale2),
  6.9232 +
  6.9233 +        stack1 = nv.models.stackedArea().yScale(yScale1),
  6.9234 +        stack2 = nv.models.stackedArea().yScale(yScale2),
  6.9235 +
  6.9236 +        xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5),
  6.9237 +        yAxis1 = nv.models.axis().scale(yScale1).orient('left'),
  6.9238 +        yAxis2 = nv.models.axis().scale(yScale2).orient('right'),
  6.9239 +
  6.9240 +        legend = nv.models.legend().height(30),
  6.9241 +        tooltip = nv.models.tooltip(),
  6.9242 +        dispatch = d3.dispatch();
  6.9243 +
  6.9244 +    function chart(selection) {
  6.9245 +        selection.each(function(data) {
  6.9246 +            var container = d3.select(this),
  6.9247 +                that = this;
  6.9248 +            nv.utils.initSVG(container);
  6.9249 +
  6.9250 +            chart.update = function() { container.transition().call(chart); };
  6.9251 +            chart.container = this;
  6.9252 +
  6.9253 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.9254 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.9255 +
  6.9256 +            var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1});
  6.9257 +            var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2});
  6.9258 +            var dataBars1 =  data.filter(function(d) {return d.type == 'bar'  && d.yAxis == 1});
  6.9259 +            var dataBars2 =  data.filter(function(d) {return d.type == 'bar'  && d.yAxis == 2});
  6.9260 +            var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1});
  6.9261 +            var dataStack2 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 2});
  6.9262 +
  6.9263 +            // Display noData message if there's nothing to show.
  6.9264 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
  6.9265 +                nv.utils.noData(chart, container);
  6.9266 +                return chart;
  6.9267 +            } else {
  6.9268 +                container.selectAll('.nv-noData').remove();
  6.9269 +            }
  6.9270 +
  6.9271 +            var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1})
  6.9272 +                .map(function(d) {
  6.9273 +                    return d.values.map(function(d,i) {
  6.9274 +                        return { x: d.x, y: d.y }
  6.9275 +                    })
  6.9276 +                });
  6.9277 +
  6.9278 +            var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2})
  6.9279 +                .map(function(d) {
  6.9280 +                    return d.values.map(function(d,i) {
  6.9281 +                        return { x: d.x, y: d.y }
  6.9282 +                    })
  6.9283 +                });
  6.9284 +
  6.9285 +            x   .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
  6.9286 +                .range([0, availableWidth]);
  6.9287 +
  6.9288 +            var wrap = container.selectAll('g.wrap.multiChart').data([data]);
  6.9289 +            var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g');
  6.9290 +
  6.9291 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
  6.9292 +            gEnter.append('g').attr('class', 'nv-y1 nv-axis');
  6.9293 +            gEnter.append('g').attr('class', 'nv-y2 nv-axis');
  6.9294 +            gEnter.append('g').attr('class', 'lines1Wrap');
  6.9295 +            gEnter.append('g').attr('class', 'lines2Wrap');
  6.9296 +            gEnter.append('g').attr('class', 'bars1Wrap');
  6.9297 +            gEnter.append('g').attr('class', 'bars2Wrap');
  6.9298 +            gEnter.append('g').attr('class', 'stack1Wrap');
  6.9299 +            gEnter.append('g').attr('class', 'stack2Wrap');
  6.9300 +            gEnter.append('g').attr('class', 'legendWrap');
  6.9301 +
  6.9302 +            var g = wrap.select('g');
  6.9303 +
  6.9304 +            var color_array = data.map(function(d,i) {
  6.9305 +                return data[i].color || color(d, i);
  6.9306 +            });
  6.9307 +
  6.9308 +            if (showLegend) {
  6.9309 +                var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;
  6.9310 +                var legendXPosition = legend.align() ? legendWidth : 0;
  6.9311 +
  6.9312 +                legend.width(legendWidth);
  6.9313 +                legend.color(color_array);
  6.9314 +
  6.9315 +                g.select('.legendWrap')
  6.9316 +                    .datum(data.map(function(series) {
  6.9317 +                        series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
  6.9318 +                        series.key = series.originalKey + (series.yAxis == 1 ? '' : ' (right axis)');
  6.9319 +                        return series;
  6.9320 +                    }))
  6.9321 +                    .call(legend);
  6.9322 +
  6.9323 +                if ( margin.top != legend.height()) {
  6.9324 +                    margin.top = legend.height();
  6.9325 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
  6.9326 +                }
  6.9327 +
  6.9328 +                g.select('.legendWrap')
  6.9329 +                    .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');
  6.9330 +            }
  6.9331 +
  6.9332 +            lines1
  6.9333 +                .width(availableWidth)
  6.9334 +                .height(availableHeight)
  6.9335 +                .interpolate(interpolate)
  6.9336 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'}));
  6.9337 +            lines2
  6.9338 +                .width(availableWidth)
  6.9339 +                .height(availableHeight)
  6.9340 +                .interpolate(interpolate)
  6.9341 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'}));
  6.9342 +            bars1
  6.9343 +                .width(availableWidth)
  6.9344 +                .height(availableHeight)
  6.9345 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'}));
  6.9346 +            bars2
  6.9347 +                .width(availableWidth)
  6.9348 +                .height(availableHeight)
  6.9349 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'}));
  6.9350 +            stack1
  6.9351 +                .width(availableWidth)
  6.9352 +                .height(availableHeight)
  6.9353 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'}));
  6.9354 +            stack2
  6.9355 +                .width(availableWidth)
  6.9356 +                .height(availableHeight)
  6.9357 +                .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'}));
  6.9358 +
  6.9359 +            g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.9360 +
  6.9361 +            var lines1Wrap = g.select('.lines1Wrap')
  6.9362 +                .datum(dataLines1.filter(function(d){return !d.disabled}));
  6.9363 +            var bars1Wrap = g.select('.bars1Wrap')
  6.9364 +                .datum(dataBars1.filter(function(d){return !d.disabled}));
  6.9365 +            var stack1Wrap = g.select('.stack1Wrap')
  6.9366 +                .datum(dataStack1.filter(function(d){return !d.disabled}));
  6.9367 +            var lines2Wrap = g.select('.lines2Wrap')
  6.9368 +                .datum(dataLines2.filter(function(d){return !d.disabled}));
  6.9369 +            var bars2Wrap = g.select('.bars2Wrap')
  6.9370 +                .datum(dataBars2.filter(function(d){return !d.disabled}));
  6.9371 +            var stack2Wrap = g.select('.stack2Wrap')
  6.9372 +                .datum(dataStack2.filter(function(d){return !d.disabled}));
  6.9373 +
  6.9374 +            var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){
  6.9375 +                return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
  6.9376 +            }).concat([{x:0, y:0}]) : [];
  6.9377 +            var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){
  6.9378 +                return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
  6.9379 +            }).concat([{x:0, y:0}]) : [];
  6.9380 +
  6.9381 +            yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } ))
  6.9382 +                .range([0, availableHeight]);
  6.9383 +
  6.9384 +            yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } ))
  6.9385 +                .range([0, availableHeight]);
  6.9386 +
  6.9387 +            lines1.yDomain(yScale1.domain());
  6.9388 +            bars1.yDomain(yScale1.domain());
  6.9389 +            stack1.yDomain(yScale1.domain());
  6.9390 +
  6.9391 +            lines2.yDomain(yScale2.domain());
  6.9392 +            bars2.yDomain(yScale2.domain());
  6.9393 +            stack2.yDomain(yScale2.domain());
  6.9394 +
  6.9395 +            if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);}
  6.9396 +            if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);}
  6.9397 +
  6.9398 +            if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);}
  6.9399 +            if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);}
  6.9400 +
  6.9401 +            if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);}
  6.9402 +            if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);}
  6.9403 +
  6.9404 +            xAxis
  6.9405 +                ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
  6.9406 +                .tickSize(-availableHeight, 0);
  6.9407 +
  6.9408 +            g.select('.nv-x.nv-axis')
  6.9409 +                .attr('transform', 'translate(0,' + availableHeight + ')');
  6.9410 +            d3.transition(g.select('.nv-x.nv-axis'))
  6.9411 +                .call(xAxis);
  6.9412 +
  6.9413 +            yAxis1
  6.9414 +                ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.9415 +                .tickSize( -availableWidth, 0);
  6.9416 +
  6.9417 +
  6.9418 +            d3.transition(g.select('.nv-y1.nv-axis'))
  6.9419 +                .call(yAxis1);
  6.9420 +
  6.9421 +            yAxis2
  6.9422 +                ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
  6.9423 +                .tickSize( -availableWidth, 0);
  6.9424 +
  6.9425 +            d3.transition(g.select('.nv-y2.nv-axis'))
  6.9426 +                .call(yAxis2);
  6.9427 +
  6.9428 +            g.select('.nv-y1.nv-axis')
  6.9429 +                .classed('nv-disabled', series1.length ? false : true)
  6.9430 +                .attr('transform', 'translate(' + x.range()[0] + ',0)');
  6.9431 +
  6.9432 +            g.select('.nv-y2.nv-axis')
  6.9433 +                .classed('nv-disabled', series2.length ? false : true)
  6.9434 +                .attr('transform', 'translate(' + x.range()[1] + ',0)');
  6.9435 +
  6.9436 +            legend.dispatch.on('stateChange', function(newState) {
  6.9437 +                chart.update();
  6.9438 +            });
  6.9439 +
  6.9440 +            //============================================================
  6.9441 +            // Event Handling/Dispatching
  6.9442 +            //------------------------------------------------------------
  6.9443 +
  6.9444 +            function mouseover_line(evt) {
  6.9445 +                var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
  6.9446 +                evt.value = evt.point.x;
  6.9447 +                evt.series = {
  6.9448 +                    value: evt.point.y,
  6.9449 +                    color: evt.point.color
  6.9450 +                };
  6.9451 +                tooltip
  6.9452 +                    .duration(100)
  6.9453 +                    .valueFormatter(function(d, i) {
  6.9454 +                        return yaxis.tickFormat()(d, i);
  6.9455 +                    })
  6.9456 +                    .data(evt)
  6.9457 +                    .position(evt.pos)
  6.9458 +                    .hidden(false);
  6.9459 +            }
  6.9460 +
  6.9461 +            function mouseover_stack(evt) {
  6.9462 +                var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
  6.9463 +                evt.point['x'] = stack1.x()(evt.point);
  6.9464 +                evt.point['y'] = stack1.y()(evt.point);
  6.9465 +                tooltip
  6.9466 +                    .duration(100)
  6.9467 +                    .valueFormatter(function(d, i) {
  6.9468 +                        return yaxis.tickFormat()(d, i);
  6.9469 +                    })
  6.9470 +                    .data(evt)
  6.9471 +                    .position(evt.pos)
  6.9472 +                    .hidden(false);
  6.9473 +            }
  6.9474 +
  6.9475 +            function mouseover_bar(evt) {
  6.9476 +                var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1;
  6.9477 +
  6.9478 +                evt.value = bars1.x()(evt.data);
  6.9479 +                evt['series'] = {
  6.9480 +                    value: bars1.y()(evt.data),
  6.9481 +                    color: evt.color
  6.9482 +                };
  6.9483 +                tooltip
  6.9484 +                    .duration(0)
  6.9485 +                    .valueFormatter(function(d, i) {
  6.9486 +                        return yaxis.tickFormat()(d, i);
  6.9487 +                    })
  6.9488 +                    .data(evt)
  6.9489 +                    .hidden(false);
  6.9490 +            }
  6.9491 +
  6.9492 +            lines1.dispatch.on('elementMouseover.tooltip', mouseover_line);
  6.9493 +            lines2.dispatch.on('elementMouseover.tooltip', mouseover_line);
  6.9494 +            lines1.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9495 +                tooltip.hidden(true)
  6.9496 +            });
  6.9497 +            lines2.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9498 +                tooltip.hidden(true)
  6.9499 +            });
  6.9500 +
  6.9501 +            stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack);
  6.9502 +            stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack);
  6.9503 +            stack1.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9504 +                tooltip.hidden(true)
  6.9505 +            });
  6.9506 +            stack2.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9507 +                tooltip.hidden(true)
  6.9508 +            });
  6.9509 +
  6.9510 +            bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar);
  6.9511 +            bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar);
  6.9512 +
  6.9513 +            bars1.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9514 +                tooltip.hidden(true);
  6.9515 +            });
  6.9516 +            bars2.dispatch.on('elementMouseout.tooltip', function(evt) {
  6.9517 +                tooltip.hidden(true);
  6.9518 +            });
  6.9519 +            bars1.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.9520 +                tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.9521 +            });
  6.9522 +            bars2.dispatch.on('elementMousemove.tooltip', function(evt) {
  6.9523 +                tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
  6.9524 +            });
  6.9525 +
  6.9526 +        });
  6.9527 +
  6.9528 +        return chart;
  6.9529 +    }
  6.9530 +
  6.9531 +    //============================================================
  6.9532 +    // Global getters and setters
  6.9533 +    //------------------------------------------------------------
  6.9534 +
  6.9535 +    chart.dispatch = dispatch;
  6.9536 +    chart.lines1 = lines1;
  6.9537 +    chart.lines2 = lines2;
  6.9538 +    chart.bars1 = bars1;
  6.9539 +    chart.bars2 = bars2;
  6.9540 +    chart.stack1 = stack1;
  6.9541 +    chart.stack2 = stack2;
  6.9542 +    chart.xAxis = xAxis;
  6.9543 +    chart.yAxis1 = yAxis1;
  6.9544 +    chart.yAxis2 = yAxis2;
  6.9545 +    chart.tooltip = tooltip;
  6.9546 +
  6.9547 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.9548 +
  6.9549 +    chart._options = Object.create({}, {
  6.9550 +        // simple options, just get/set the necessary values
  6.9551 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
  6.9552 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
  6.9553 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
  6.9554 +        yDomain1:      {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}},
  6.9555 +        yDomain2:    {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}},
  6.9556 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
  6.9557 +        interpolate:    {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
  6.9558 +
  6.9559 +        // deprecated options
  6.9560 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
  6.9561 +            // deprecated after 1.7.1
  6.9562 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
  6.9563 +            tooltip.enabled(!!_);
  6.9564 +        }},
  6.9565 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
  6.9566 +            // deprecated after 1.7.1
  6.9567 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
  6.9568 +            tooltip.contentGenerator(_);
  6.9569 +        }},
  6.9570 +
  6.9571 +        // options that require extra logic in the setter
  6.9572 +        margin: {get: function(){return margin;}, set: function(_){
  6.9573 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
  6.9574 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
  6.9575 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
  6.9576 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
  6.9577 +        }},
  6.9578 +        color:  {get: function(){return color;}, set: function(_){
  6.9579 +            color = nv.utils.getColor(_);
  6.9580 +        }},
  6.9581 +        x: {get: function(){return getX;}, set: function(_){
  6.9582 +            getX = _;
  6.9583 +            lines1.x(_);
  6.9584 +            lines2.x(_);
  6.9585 +            bars1.x(_);
  6.9586 +            bars2.x(_);
  6.9587 +            stack1.x(_);
  6.9588 +            stack2.x(_);
  6.9589 +        }},
  6.9590 +        y: {get: function(){return getY;}, set: function(_){
  6.9591 +            getY = _;
  6.9592 +            lines1.y(_);
  6.9593 +            lines2.y(_);
  6.9594 +            stack1.y(_);
  6.9595 +            stack2.y(_);
  6.9596 +            bars1.y(_);
  6.9597 +            bars2.y(_);
  6.9598 +        }},
  6.9599 +        useVoronoi: {get: function(){return useVoronoi;}, set: function(_){
  6.9600 +            useVoronoi=_;
  6.9601 +            lines1.useVoronoi(_);
  6.9602 +            lines2.useVoronoi(_);
  6.9603 +            stack1.useVoronoi(_);
  6.9604 +            stack2.useVoronoi(_);
  6.9605 +        }}
  6.9606 +    });
  6.9607 +
  6.9608 +    nv.utils.initOptions(chart);
  6.9609 +
  6.9610 +    return chart;
  6.9611 +};
  6.9612 +
  6.9613 +
  6.9614 +nv.models.ohlcBar = function() {
  6.9615 +    "use strict";
  6.9616 +
  6.9617 +    //============================================================
  6.9618 +    // Public Variables with Default Settings
  6.9619 +    //------------------------------------------------------------
  6.9620 +
  6.9621 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
  6.9622 +        , width = null
  6.9623 +        , height = null
  6.9624 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
  6.9625 +        , container = null
  6.9626 +        , x = d3.scale.linear()
  6.9627 +        , y = d3.scale.linear()
  6.9628 +        , getX = function(d) { return d.x }
  6.9629 +        , getY = function(d) { return d.y }
  6.9630 +        , getOpen = function(d) { return d.open }
  6.9631 +        , getClose = function(d) { return d.close }
  6.9632 +        , getHigh = function(d) { return d.high }
  6.9633 +        , getLow = function(d) { return d.low }
  6.9634 +        , forceX = []
  6.9635 +        , forceY = []
  6.9636 +        , padData     = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
  6.9637 +        , clipEdge = true
  6.9638 +        , color = nv.utils.defaultColor()
  6.9639 +        , interactive = false
  6.9640 +        , xDomain
  6.9641 +        , yDomain
  6.9642 +        , xRange
  6.9643 +        , yRange
  6.9644 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove')
  6.9645 +        ;
  6.9646 +
  6.9647 +    //============================================================
  6.9648 +    // Private Variables
  6.9649 +    //------------------------------------------------------------
  6.9650 +
  6.9651 +    function chart(selection) {
  6.9652 +        selection.each(function(data) {
  6.9653 +            container = d3.select(this);
  6.9654 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.9655 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.9656 +
  6.9657 +            nv.utils.initSVG(container);
  6.9658 +
  6.9659 +            // ohlc bar width.
  6.9660 +            var w = (availableWidth / data[0].values.length) * .9;
  6.9661 +
  6.9662 +            // Setup Scales
  6.9663 +            x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
  6.9664 +
  6.9665 +            if (padData)
  6.9666 +                x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5)  / data[0].values.length ]);
  6.9667 +            else
  6.9668 +                x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]);
  6.9669 +
  6.9670 +            y.domain(yDomain || [
  6.9671 +                    d3.min(data[0].values.map(getLow).concat(forceY)),
  6.9672 +                    d3.max(data[0].values.map(getHigh).concat(forceY))
  6.9673 +                ]
  6.9674 +            ).range(yRange || [availableHeight, 0]);
  6.9675 +
  6.9676 +            // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
  6.9677 +            if (x.domain()[0] === x.domain()[1])
  6.9678 +                x.domain()[0] ?
  6.9679 +                    x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
  6.9680 +                    : x.domain([-1,1]);
  6.9681 +
  6.9682 +            if (y.domain()[0] === y.domain()[1])
  6.9683 +                y.domain()[0] ?
  6.9684 +                    y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
  6.9685 +                    : y.domain([-1,1]);
  6.9686 +
  6.9687 +            // Setup containers and skeleton of chart
  6.9688 +            var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]);
  6.9689 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar');
  6.9690 +            var defsEnter = wrapEnter.append('defs');
  6.9691 +            var gEnter = wrapEnter.append('g');
  6.9692 +            var g = wrap.select('g');
  6.9693 +
  6.9694 +            gEnter.append('g').attr('class', 'nv-ticks');
  6.9695 +
  6.9696 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.9697 +
  6.9698 +            container
  6.9699 +                .on('click', function(d,i) {
  6.9700 +                    dispatch.chartClick({
  6.9701 +                        data: d,
  6.9702 +                        index: i,
  6.9703 +                        pos: d3.event,
  6.9704 +                        id: id
  6.9705 +                    });
  6.9706 +                });
  6.9707 +
  6.9708 +            defsEnter.append('clipPath')
  6.9709 +                .attr('id', 'nv-chart-clip-path-' + id)
  6.9710 +                .append('rect');
  6.9711 +
  6.9712 +            wrap.select('#nv-chart-clip-path-' + id + ' rect')
  6.9713 +                .attr('width', availableWidth)
  6.9714 +                .attr('height', availableHeight);
  6.9715 +
  6.9716 +            g   .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');
  6.9717 +
  6.9718 +            var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')
  6.9719 +                .data(function(d) { return d });
  6.9720 +            ticks.exit().remove();
  6.9721 +
  6.9722 +            ticks.enter().append('path')
  6.9723 +                .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })
  6.9724 +                .attr('d', function(d,i) {
  6.9725 +                    return 'm0,0l0,'
  6.9726 +                        + (y(getOpen(d,i))
  6.9727 +                            - y(getHigh(d,i)))
  6.9728 +                        + 'l'
  6.9729 +                        + (-w/2)
  6.9730 +                        + ',0l'
  6.9731 +                        + (w/2)
  6.9732 +                        + ',0l0,'
  6.9733 +                        + (y(getLow(d,i)) - y(getOpen(d,i)))
  6.9734 +                        + 'l0,'
  6.9735 +                        + (y(getClose(d,i))
  6.9736 +                            - y(getLow(d,i)))
  6.9737 +                        + 'l'
  6.9738 +                        + (w/2)
  6.9739 +                        + ',0l'
  6.9740 +                        + (-w/2)
  6.9741 +                        + ',0z';
  6.9742 +                })
  6.9743 +                .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
  6.9744 +                .attr('fill', function(d,i) { return color[0]; })
  6.9745 +                .attr('stroke', function(d,i) { return color[0]; })
  6.9746 +                .attr('x', 0 )
  6.9747 +                .attr('y', function(d,i) {  return y(Math.max(0, getY(d,i))) })
  6.9748 +                .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });
  6.9749 +
  6.9750 +            // the bar colors are controlled by CSS currently
  6.9751 +            ticks.attr('class', function(d,i,j) {
  6.9752 +                return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i;
  6.9753 +            });
  6.9754 +
  6.9755 +            d3.transition(ticks)
  6.9756 +                .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
  6.9757 +                .attr('d', function(d,i) {
  6.9758 +                    var w = (availableWidth / data[0].values.length) * .9;
  6.9759 +                    return 'm0,0l0,'
  6.9760 +                        + (y(getOpen(d,i))
  6.9761 +                            - y(getHigh(d,i)))
  6.9762 +                        + 'l'
  6.9763 +                        + (-w/2)
  6.9764 +                        + ',0l'
  6.9765 +                        + (w/2)
  6.9766 +                        + ',0l0,'
  6.9767 +                        + (y(getLow(d,i))
  6.9768 +                            - y(getOpen(d,i)))
  6.9769 +                        + 'l0,'
  6.9770 +                        + (y(getClose(d,i))
  6.9771 +                            - y(getLow(d,i)))
  6.9772 +                        + 'l'
  6.9773 +                        + (w/2)
  6.9774 +                        + ',0l'
  6.9775 +                        + (-w/2)
  6.9776 +                        + ',0z';
  6.9777 +                });
  6.9778 +        });
  6.9779 +
  6.9780 +        return chart;
  6.9781 +    }
  6.9782 +
  6.9783 +
  6.9784 +    //Create methods to allow outside functions to highlight a specific bar.
  6.9785 +    chart.highlightPoint = function(pointIndex, isHoverOver) {
  6.9786 +        chart.clearHighlights();
  6.9787 +        container.select(".nv-ohlcBar .nv-tick-0-" + pointIndex)
  6.9788 +            .classed("hover", isHoverOver)
  6.9789 +        ;
  6.9790 +    };
  6.9791 +
  6.9792 +    chart.clearHighlights = function() {
  6.9793 +        container.select(".nv-ohlcBar .nv-tick.hover")
  6.9794 +            .classed("hover", false)
  6.9795 +        ;
  6.9796 +    };
  6.9797 +
  6.9798 +    //============================================================
  6.9799 +    // Expose Public Variables
  6.9800 +    //------------------------------------------------------------
  6.9801 +
  6.9802 +    chart.dispatch = dispatch;
  6.9803 +    chart.options = nv.utils.optionsFunc.bind(chart);
  6.9804 +
  6.9805 +    chart._options = Object.create({}, {
  6.9806 +        // simple options, just get/set the necessary values
  6.9807 +        width:    {get: function(){return width;}, set: function(_){width=_;}},
  6.9808 +        height:   {get: function(){return height;}, set: function(_){height=_;}},
  6.9809 +        xScale:   {get: function(){return x;}, set: function(_){x=_;}},
  6.9810 +        yScale:   {get: function(){return y;}, set: function(_){y=_;}},
  6.9811 +        xDomain:  {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
  6.9812 +        yDomain:  {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
  6.9813 +        xRange:   {get: function(){return xRange;}, set: function(_){xRange=_;}},
  6.9814 +        yRange:   {get: function(){return yRange;}, set: function(_){yRange=_;}},
  6.9815 +        forceX:   {get: function(){return forceX;}, set: function(_){forceX=_;}},
  6.9816 +        forceY:   {get: function(){return forceY;}, set: function(_){forceY=_;}},
  6.9817 +        padData:  {get: function(){return padData;}, set: function(_){padData=_;}},
  6.9818 +        clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
  6.9819 +        id:       {get: function(){return id;}, set: function(_){id=_;}},
  6.9820 +        interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},
  6.9821 +
  6.9822 +        x:     {get: function(){return getX;}, set: function(_){getX=_;}},
  6.9823 +        y:     {get: function(){return getY;}, set: function(_){getY=_;}},
  6.9824 +        open:  {get: function(){return getOpen();}, set: function(_){getOpen=_;}},
  6.9825 +        close: {get: function(){return getClose();}, set: function(_){getClose=_;}},
  6.9826 +        high:  {get: function(){return getHigh;}, set: function(_){getHigh=_;}},
  6.9827 +        low:   {get: function(){return getLow;}, set: function(_){getLow=_;}},
  6.9828 +
  6.9829 +        // options that require extra logic in the setter
  6.9830 +        margin: {get: function(){return margin;}, set: function(_){
  6.9831 +            margin.top    = _.top    != undefined ? _.top    : margin.top;
  6.9832 +            margin.right  = _.right  != undefined ? _.right  : margin.right;
  6.9833 +            margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
  6.9834 +            margin.left   = _.left   != undefined ? _.left   : margin.left;
  6.9835 +        }},
  6.9836 +        color:  {get: function(){return color;}, set: function(_){
  6.9837 +            color = nv.utils.getColor(_);
  6.9838 +        }}
  6.9839 +    });
  6.9840 +
  6.9841 +    nv.utils.initOptions(chart);
  6.9842 +    return chart;
  6.9843 +};
  6.9844 +// Code adapted from Jason Davies' "Parallel Coordinates"
  6.9845 +// http://bl.ocks.org/jasondavies/1341281
  6.9846 +nv.models.parallelCoordinates = function() {
  6.9847 +    "use strict";
  6.9848 +
  6.9849 +    //============================================================
  6.9850 +    // Public Variables with Default Settings
  6.9851 +    //------------------------------------------------------------
  6.9852 +
  6.9853 +    var margin = {top: 30, right: 0, bottom: 10, left: 0}
  6.9854 +        , width = null
  6.9855 +        , height = null
  6.9856 +        , x = d3.scale.ordinal()
  6.9857 +        , y = {}
  6.9858 +        , dimensionNames = []
  6.9859 +        , dimensionFormats = []
  6.9860 +        , color = nv.utils.defaultColor()
  6.9861 +        , filters = []
  6.9862 +        , active = []
  6.9863 +        , dragging = []
  6.9864 +        , lineTension = 1
  6.9865 +        , dispatch = d3.dispatch('brush', 'elementMouseover', 'elementMouseout')
  6.9866 +        ;
  6.9867 +
  6.9868 +    //============================================================
  6.9869 +    // Private Variables
  6.9870 +    //------------------------------------------------------------
  6.9871 +
  6.9872 +    function chart(selection) {
  6.9873 +        selection.each(function(data) {
  6.9874 +            var container = d3.select(this);
  6.9875 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
  6.9876 +                availableHeight = nv.utils.availableHeight(height, container, margin);
  6.9877 +
  6.9878 +            nv.utils.initSVG(container);
  6.9879 +
  6.9880 +            active = data; //set all active before first brush call
  6.9881 +
  6.9882 +            // Setup Scales
  6.9883 +            x.rangePoints([0, availableWidth], 1).domain(dimensionNames);
  6.9884 +
  6.9885 +            //Set as true if all values on an axis are missing.
  6.9886 +            var onlyNanValues = {};
  6.9887 +            // Extract the list of dimensions and create a scale for each.
  6.9888 +            dimensionNames.forEach(function(d) {
  6.9889 +                var extent = d3.extent(data, function(p) { return +p[d]; });
  6.9890 +                onlyNanValues[d] = false;
  6.9891 +                //If there is no values to display on an axis, set the extent to 0
  6.9892 +                if (extent[0] === undefined) {
  6.9893 +                    onlyNanValues[d] = true;
  6.9894 +                    extent[0] = 0;
  6.9895 +                    extent[1] = 0;
  6.9896 +                }
  6.9897 +                //Scale axis if there is only one value
  6.9898 +                if (extent[0] === extent[1]) {
  6.9899 +                    extent[0] = extent[0] - 1;
  6.9900 +                    extent[1] = extent[1] + 1;
  6.9901 +                }
  6.9902 +                //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display "undefined values" text.
  6.9903 +                //The remaining 10% are used to display the missingValue line.
  6.9904 +                y[d] = d3.scale.linear()
  6.9905 +                    .domain(extent)
  6.9906 +                    .range([(availableHeight - 12) * 0.9, 0]);
  6.9907 +
  6.9908 +                y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush);
  6.9909 +
  6.9910 +                return d != 'name';
  6.9911 +            });
  6.9912 +
  6.9913 +            // Setup containers and skeleton of chart
  6.9914 +            var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]);
  6.9915 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates');
  6.9916 +            var gEnter = wrapEnter.append('g');
  6.9917 +            var g = wrap.select('g');
  6.9918 +
  6.9919 +            gEnter.append('g').attr('class', 'nv-parallelCoordinates background');
  6.9920 +            gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground');
  6.9921 +            gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline');
  6.9922 +
  6.9923 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  6.9924 +
  6.9925 +            var line = d3.svg.line().interpolate('cardinal').tension(lineTension),
  6.9926 +                axis = d3.svg.axis().orient('left'),
  6.9927 +                axisDrag = d3.behavior.drag()
  6.9928 +                        .on('dragstart', dragStart)
  6.9929 +                        .on('drag', dragMove)
  6.9930 +                        .on('dragend', dragEnd);
  6.9931 +
  6.9932 +            //Add missing value line at the bottom of the chart
  6.9933 +            var missingValuesline, missingValueslineText;
  6.9934 +            var step = x.range()[1] - x.range()[0];
  6.9935 +            var axisWithMissingValues = [];
  6.9936 +            var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12];
  6.9937 +            missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]);
  6.9938 +            missingValuesline.enter().append('line');
  6.9939 +            missingValuesline.exit().remove();
  6.9940 +            missingValuesline.attr("x1", function(d) { return d[0]; })
  6.9941 +                    .attr("y1", function(d) { return d[1]; })
  6.9942 +                    .attr("x2", function(d) { return d[2]; })
  6.9943 +                    .attr("y2", function(d) { return d[3]; });
  6.9944 +
  6.9945 +            //Add the text "undefined values" under the missing value line
  6.9946 +            missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data(["undefined values"]);
  6.9947 +            missingValueslineText.append('text').data(["undefined values"]);
  6.9948 +            missingValueslineText.enter().append('text');
  6.9949 +            missingValueslineText.exit().remove();
  6.9950 +            missingValueslineText.attr("y", availableHeight)
  6.9951 +                    //To have the text right align with the missingValues line, substract 92 representing the text size.
  6.9952 +                    .attr("x", availableWidth - 92 - step / 2)
  6.9953 +                    .text(function(d) { return d; });
  6.9954 +
  6.9955 +            // Add grey background lines for context.
  6.9956 +            var background = wrap.select('.background').selectAll('path').data(data);
  6.9957 +            background.enter().append('path');
  6.9958 +            background.exit().remove();
  6.9959 +            background.attr('d', path);
  6.9960 +
  6.9961 +            // Add blue foreground lines for focus.
  6.9962 +            var foreground = wrap.select('.foreground').selectAll('path').data(data);
  6.9963 +            foreground.enter().append('path')
  6.9964 +            foreground.exit().remove();
  6.9965 +            foreground.attr('d', path).attr('stroke', color);
  6.9966 +            foreground.on("mouseover", function (d, i) {
  6.9967 +                d3.select(this).classed('hover', true);
  6.9968 +                dispatch.elementMouseover({
  6.9969 +                    label: d.name,
  6.9970 +                    data: d.data,
  6.9971 +                    index: i,
  6.9972 +                    pos: [d3.mouse(this.parentNode)[0], d3.mouse(this.parentNode)[1]]
  6.9973 +                });
  6.9974 +
  6.9975 +            });
  6.9976 +            foreground.on("mouseout", function (d, i) {
  6.9977 +                d3.select(this).classed('hover', false);
  6.9978 +                dispatch.elementMouseout({
  6.9979 +                    label: d.name,
  6.9980 +                    data: d.data,
  6.9981 +                    index: i
  6.9982 +                });
  6.9983 +            });
  6.9984 +
  6.9985 +            // Add a group element for each dimension.
  6.9986 +            var dimensions = g.selectAll('.dimension').data(dimensionNames);
  6.9987 +            var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension');
  6.9988 +            dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates nv-axis');
  6.9989 +            dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates-brush');
  6.9990 +            dimensionsEnter.append('text').attr('class', 'nv-parallelCoordinates nv-label');
  6.9991 +
  6.9992 +            dimensions.attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; });
  6.9993 +            dimensions.exit().remove();
  6.9994 +
  6.9995 +            // Add an axis and title.
  6.9996 +            dimensions.select('.nv-label')
  6.9997 +                .style("cursor", "move")
  6.9998 +                .attr('dy', '-1em')
  6.9999 +                .attr('text-anchor', 'middle')
 6.10000 +                .text(String)
 6.10001 +                .on("mouseover", function(d, i) {
 6.10002 +                    dispatch.elementMouseover({
 6.10003 +                        dim: d,
 6.10004 +                        pos: [d3.mouse(this.parentNode.parentNode)[0], d3.mouse(this.parentNode.parentNode)[1]]
 6.10005 +                    });
 6.10006 +                })
 6.10007 +                .on("mouseout", function(d, i) {
 6.10008 +                    dispatch.elementMouseout({
 6.10009 +                        dim: d
 6.10010 +                    });
 6.10011 +                })
 6.10012 +                .call(axisDrag);
 6.10013 +
 6.10014 +            dimensions.select('.nv-axis')
 6.10015 +                .each(function (d, i) {
 6.10016 +                    d3.select(this).call(axis.scale(y[d]).tickFormat(d3.format(dimensionFormats[i])));
 6.10017 +                });
 6.10018 +
 6.10019 +                dimensions.select('.nv-parallelCoordinates-brush')
 6.10020 +                .each(function (d) {
 6.10021 +                    d3.select(this).call(y[d].brush);
 6.10022 +                })
 6.10023 +                .selectAll('rect')
 6.10024 +                .attr('x', -8)
 6.10025 +                .attr('width', 16);
 6.10026 +
 6.10027 +            // Returns the path for a given data point.
 6.10028 +            function path(d) {
 6.10029 +                return line(dimensionNames.map(function (p) {
 6.10030 +                    //If value if missing, put the value on the missing value line
 6.10031 +                    if(isNaN(d[p]) || isNaN(parseFloat(d[p]))) {
 6.10032 +                        var domain = y[p].domain();
 6.10033 +                        var range = y[p].range();
 6.10034 +                        var min = domain[0] - (domain[1] - domain[0]) / 9;
 6.10035 +
 6.10036 +                        //If it's not already the case, allow brush to select undefined values
 6.10037 +                        if(axisWithMissingValues.indexOf(p) < 0) {
 6.10038 +
 6.10039 +                            var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]);
 6.10040 +                            y[p].brush.y(newscale);
 6.10041 +                            axisWithMissingValues.push(p);
 6.10042 +                        }
 6.10043 +
 6.10044 +                        return [x(p), y[p](min)];
 6.10045 +                    }
 6.10046 +
 6.10047 +                    //If parallelCoordinate contain missing values show the missing values line otherwise, hide it.
 6.10048 +                    if(axisWithMissingValues.length > 0) {
 6.10049 +                        missingValuesline.style("display", "inline");
 6.10050 +                        missingValueslineText.style("display", "inline");
 6.10051 +                    } else {
 6.10052 +                        missingValuesline.style("display", "none");
 6.10053 +                        missingValueslineText.style("display", "none");
 6.10054 +                    }
 6.10055 +
 6.10056 +                     return [x(p), y[p](d[p])];
 6.10057 +                }));
 6.10058 +            }
 6.10059 +
 6.10060 +            // Handles a brush event, toggling the display of foreground lines.
 6.10061 +            function brush() {
 6.10062 +                var actives = dimensionNames.filter(function(p) { return !y[p].brush.empty(); }),
 6.10063 +                    extents = actives.map(function(p) { return y[p].brush.extent(); });
 6.10064 +
 6.10065 +                filters = []; //erase current filters
 6.10066 +                actives.forEach(function(d,i) {
 6.10067 +                    filters[i] = {
 6.10068 +                        dimension: d,
 6.10069 +                        extent: extents[i]
 6.10070 +                    }
 6.10071 +                });
 6.10072 +
 6.10073 +                active = []; //erase current active list
 6.10074 +                foreground.style('display', function(d) {
 6.10075 +                    var isActive = actives.every(function(p, i) {
 6.10076 +                        if(isNaN(d[p]) && extents[i][0] == y[p].brush.y().domain()[0]) return true;
 6.10077 +                        return extents[i][0] <= d[p] && d[p] <= extents[i][1];
 6.10078 +                    });
 6.10079 +                    if (isActive) active.push(d);
 6.10080 +                    return isActive ? null : 'none';
 6.10081 +                });
 6.10082 +
 6.10083 +                dispatch.brush({
 6.10084 +                    filters: filters,
 6.10085 +                    active: active
 6.10086 +                });
 6.10087 +            }
 6.10088 +
 6.10089 +            function dragStart(d, i) {
 6.10090 +                dragging[d] = this.parentNode.__origin__ = x(d);
 6.10091 +                background.attr("visibility", "hidden");
 6.10092 +
 6.10093 +            }
 6.10094 +
 6.10095 +            function dragMove(d, i) {
 6.10096 +                dragging[d] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x));
 6.10097 +                foreground.attr("d", path);
 6.10098 +                dimensionNames.sort(function (a, b) { return position(a) - position(b); });
 6.10099 +                x.domain(dimensionNames);
 6.10100 +                dimensions.attr("transform", function(d) { return "translate(" + position(d) + ")"; });
 6.10101 +            }
 6.10102 +
 6.10103 +            function dragEnd(d, i) {
 6.10104 +                delete this.parentNode.__origin__;
 6.10105 +                delete dragging[d];
 6.10106 +                d3.select(this.parentNode).attr("transform", "translate(" + x(d) + ")");
 6.10107 +                foreground
 6.10108 +                  .attr("d", path);
 6.10109 +                background
 6.10110 +                  .attr("d", path)
 6.10111 +                  .attr("visibility", null);
 6.10112 +
 6.10113 +            }
 6.10114 +
 6.10115 +            function position(d) {
 6.10116 +                var v = dragging[d];
 6.10117 +                return v == null ? x(d) : v;
 6.10118 +            }
 6.10119 +        });
 6.10120 +
 6.10121 +        return chart;
 6.10122 +    }
 6.10123 +
 6.10124 +    //============================================================
 6.10125 +    // Expose Public Variables
 6.10126 +    //------------------------------------------------------------
 6.10127 +
 6.10128 +    chart.dispatch = dispatch;
 6.10129 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.10130 +
 6.10131 +    chart._options = Object.create({}, {
 6.10132 +        // simple options, just get/set the necessary values
 6.10133 +        width:         {get: function(){return width;},           set: function(_){width= _;}},
 6.10134 +        height:        {get: function(){return height;},          set: function(_){height= _;}},
 6.10135 +        dimensionNames: {get: function() { return dimensionNames;}, set: function(_){dimensionNames= _;}},
 6.10136 +        dimensionFormats : {get: function(){return dimensionFormats;}, set: function (_){dimensionFormats=_;}},
 6.10137 +        lineTension:   {get: function(){return lineTension;},     set: function(_){lineTension = _;}},
 6.10138 +
 6.10139 +        // deprecated options
 6.10140 +        dimensions: {get: function (){return dimensionNames;}, set: function(_){
 6.10141 +            // deprecated after 1.8.1
 6.10142 +            nv.deprecated('dimensions', 'use dimensionNames instead');
 6.10143 +            dimensionNames = _;
 6.10144 +        }},
 6.10145 +
 6.10146 +        // options that require extra logic in the setter
 6.10147 +        margin: {get: function(){return margin;}, set: function(_){
 6.10148 +            margin.top    =  _.top    !== undefined ? _.top    : margin.top;
 6.10149 +            margin.right  =  _.right  !== undefined ? _.right  : margin.right;
 6.10150 +            margin.bottom =  _.bottom !== undefined ? _.bottom : margin.bottom;
 6.10151 +            margin.left   =  _.left   !== undefined ? _.left   : margin.left;
 6.10152 +        }},
 6.10153 +        color:  {get: function(){return color;}, set: function(_){
 6.10154 +            color = nv.utils.getColor(_);
 6.10155 +        }}
 6.10156 +    });
 6.10157 +
 6.10158 +    nv.utils.initOptions(chart);
 6.10159 +    return chart;
 6.10160 +};
 6.10161 +nv.models.pie = function() {
 6.10162 +    "use strict";
 6.10163 +
 6.10164 +    //============================================================
 6.10165 +    // Public Variables with Default Settings
 6.10166 +    //------------------------------------------------------------
 6.10167 +
 6.10168 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
 6.10169 +        , width = 500
 6.10170 +        , height = 500
 6.10171 +        , getX = function(d) { return d.x }
 6.10172 +        , getY = function(d) { return d.y }
 6.10173 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
 6.10174 +        , container = null
 6.10175 +        , color = nv.utils.defaultColor()
 6.10176 +        , valueFormat = d3.format(',.2f')
 6.10177 +        , showLabels = true
 6.10178 +        , labelsOutside = false
 6.10179 +        , labelType = "key"
 6.10180 +        , labelThreshold = .02 //if slice percentage is under this, don't show label
 6.10181 +        , donut = false
 6.10182 +        , title = false
 6.10183 +        , growOnHover = true
 6.10184 +        , titleOffset = 0
 6.10185 +        , labelSunbeamLayout = false
 6.10186 +        , startAngle = false
 6.10187 +        , padAngle = false
 6.10188 +        , endAngle = false
 6.10189 +        , cornerRadius = 0
 6.10190 +        , donutRatio = 0.5
 6.10191 +        , arcsRadius = []
 6.10192 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
 6.10193 +        ;
 6.10194 +
 6.10195 +    var arcs = [];
 6.10196 +    var arcsOver = [];
 6.10197 +
 6.10198 +    //============================================================
 6.10199 +    // chart function
 6.10200 +    //------------------------------------------------------------
 6.10201 +
 6.10202 +    var renderWatch = nv.utils.renderWatch(dispatch);
 6.10203 +
 6.10204 +    function chart(selection) {
 6.10205 +        renderWatch.reset();
 6.10206 +        selection.each(function(data) {
 6.10207 +            var availableWidth = width - margin.left - margin.right
 6.10208 +                , availableHeight = height - margin.top - margin.bottom
 6.10209 +                , radius = Math.min(availableWidth, availableHeight) / 2
 6.10210 +                , arcsRadiusOuter = []
 6.10211 +                , arcsRadiusInner = []
 6.10212 +                ;
 6.10213 +
 6.10214 +            container = d3.select(this)
 6.10215 +            if (arcsRadius.length === 0) {
 6.10216 +                var outer = radius - radius / 5;
 6.10217 +                var inner = donutRatio * radius;
 6.10218 +                for (var i = 0; i < data[0].length; i++) {
 6.10219 +                    arcsRadiusOuter.push(outer);
 6.10220 +                    arcsRadiusInner.push(inner);
 6.10221 +                }
 6.10222 +            } else {
 6.10223 +                arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; });
 6.10224 +                arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; });
 6.10225 +                donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); }));
 6.10226 +            }
 6.10227 +            nv.utils.initSVG(container);
 6.10228 +
 6.10229 +            // Setup containers and skeleton of chart
 6.10230 +            var wrap = container.selectAll('.nv-wrap.nv-pie').data(data);
 6.10231 +            var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id);
 6.10232 +            var gEnter = wrapEnter.append('g');
 6.10233 +            var g = wrap.select('g');
 6.10234 +            var g_pie = gEnter.append('g').attr('class', 'nv-pie');
 6.10235 +            gEnter.append('g').attr('class', 'nv-pieLabels');
 6.10236 +
 6.10237 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.10238 +            g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
 6.10239 +            g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
 6.10240 +
 6.10241 +            //
 6.10242 +            container.on('click', function(d,i) {
 6.10243 +                dispatch.chartClick({
 6.10244 +                    data: d,
 6.10245 +                    index: i,
 6.10246 +                    pos: d3.event,
 6.10247 +                    id: id
 6.10248 +                });
 6.10249 +            });
 6.10250 +
 6.10251 +            arcs = [];
 6.10252 +            arcsOver = [];
 6.10253 +            for (var i = 0; i < data[0].length; i++) {
 6.10254 +
 6.10255 +                var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]);
 6.10256 +                var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5);
 6.10257 +
 6.10258 +                if (startAngle !== false) {
 6.10259 +                    arc.startAngle(startAngle);
 6.10260 +                    arcOver.startAngle(startAngle);
 6.10261 +                }
 6.10262 +                if (endAngle !== false) {
 6.10263 +                    arc.endAngle(endAngle);
 6.10264 +                    arcOver.endAngle(endAngle);
 6.10265 +                }
 6.10266 +                if (donut) {
 6.10267 +                    arc.innerRadius(arcsRadiusInner[i]);
 6.10268 +                    arcOver.innerRadius(arcsRadiusInner[i]);
 6.10269 +                }
 6.10270 +
 6.10271 +                if (arc.cornerRadius && cornerRadius) {
 6.10272 +                    arc.cornerRadius(cornerRadius);
 6.10273 +                    arcOver.cornerRadius(cornerRadius);
 6.10274 +                }
 6.10275 +
 6.10276 +                arcs.push(arc);
 6.10277 +                arcsOver.push(arcOver);
 6.10278 +            }
 6.10279 +
 6.10280 +            // Setup the Pie chart and choose the data element
 6.10281 +            var pie = d3.layout.pie()
 6.10282 +                .sort(null)
 6.10283 +                .value(function(d) { return d.disabled ? 0 : getY(d) });
 6.10284 +
 6.10285 +            // padAngle added in d3 3.5
 6.10286 +            if (pie.padAngle && padAngle) {
 6.10287 +                pie.padAngle(padAngle);
 6.10288 +            }
 6.10289 +
 6.10290 +            // if title is specified and donut, put it in the middle
 6.10291 +            if (donut && title) {
 6.10292 +                g_pie.append("text").attr('class', 'nv-pie-title');
 6.10293 +
 6.10294 +                wrap.select('.nv-pie-title')
 6.10295 +                    .style("text-anchor", "middle")
 6.10296 +                    .text(function (d) {
 6.10297 +                        return title;
 6.10298 +                    })
 6.10299 +                    .style("font-size", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + "px")
 6.10300 +                    .attr("dy", "0.35em") // trick to vertically center text
 6.10301 +                    .attr('transform', function(d, i) {
 6.10302 +                        return 'translate(0, '+ titleOffset + ')';
 6.10303 +                    });
 6.10304 +            }
 6.10305 +
 6.10306 +            var slices = wrap.select('.nv-pie').selectAll('.nv-slice').data(pie);
 6.10307 +            var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label').data(pie);
 6.10308 +
 6.10309 +            slices.exit().remove();
 6.10310 +            pieLabels.exit().remove();
 6.10311 +
 6.10312 +            var ae = slices.enter().append('g');
 6.10313 +            ae.attr('class', 'nv-slice');
 6.10314 +            ae.on('mouseover', function(d, i) {
 6.10315 +                d3.select(this).classed('hover', true);
 6.10316 +                if (growOnHover) {
 6.10317 +                    d3.select(this).select("path").transition()
 6.10318 +                        .duration(70)
 6.10319 +                        .attr("d", arcsOver[i]);
 6.10320 +                }
 6.10321 +                dispatch.elementMouseover({
 6.10322 +                    data: d.data,
 6.10323 +                    index: i,
 6.10324 +                    color: d3.select(this).style("fill")
 6.10325 +                });
 6.10326 +            });
 6.10327 +            ae.on('mouseout', function(d, i) {
 6.10328 +                d3.select(this).classed('hover', false);
 6.10329 +                if (growOnHover) {
 6.10330 +                    d3.select(this).select("path").transition()
 6.10331 +                        .duration(50)
 6.10332 +                        .attr("d", arcs[i]);
 6.10333 +                }
 6.10334 +                dispatch.elementMouseout({data: d.data, index: i});
 6.10335 +            });
 6.10336 +            ae.on('mousemove', function(d, i) {
 6.10337 +                dispatch.elementMousemove({data: d.data, index: i});
 6.10338 +            });
 6.10339 +            ae.on('click', function(d, i) {
 6.10340 +                dispatch.elementClick({
 6.10341 +                    data: d.data,
 6.10342 +                    index: i,
 6.10343 +                    color: d3.select(this).style("fill")
 6.10344 +                });
 6.10345 +            });
 6.10346 +            ae.on('dblclick', function(d, i) {
 6.10347 +                dispatch.elementDblClick({
 6.10348 +                    data: d.data,
 6.10349 +                    index: i,
 6.10350 +                    color: d3.select(this).style("fill")
 6.10351 +                });
 6.10352 +            });
 6.10353 +
 6.10354 +            slices.attr('fill', function(d,i) { return color(d.data, i); });
 6.10355 +            slices.attr('stroke', function(d,i) { return color(d.data, i); });
 6.10356 +
 6.10357 +            var paths = ae.append('path').each(function(d) {
 6.10358 +                this._current = d;
 6.10359 +            });
 6.10360 +
 6.10361 +            slices.select('path')
 6.10362 +                .transition()
 6.10363 +                .attr('d', function (d, i) { return arcs[i](d); })
 6.10364 +                .attrTween('d', arcTween);
 6.10365 +
 6.10366 +            if (showLabels) {
 6.10367 +                // This does the normal label
 6.10368 +                var labelsArc = [];
 6.10369 +                for (var i = 0; i < data[0].length; i++) {
 6.10370 +                    labelsArc.push(arcs[i]);
 6.10371 +
 6.10372 +                    if (labelsOutside) {
 6.10373 +                        if (donut) {
 6.10374 +                            labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius());
 6.10375 +                            if (startAngle !== false) labelsArc[i].startAngle(startAngle);
 6.10376 +                            if (endAngle !== false) labelsArc[i].endAngle(endAngle);
 6.10377 +                        }
 6.10378 +                    } else if (!donut) {
 6.10379 +                            labelsArc[i].innerRadius(0);
 6.10380 +                    }
 6.10381 +                }
 6.10382 +
 6.10383 +                pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) {
 6.10384 +                    var group = d3.select(this);
 6.10385 +
 6.10386 +                    group.attr('transform', function (d, i) {
 6.10387 +                        if (labelSunbeamLayout) {
 6.10388 +                            d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate
 6.10389 +                            d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate
 6.10390 +                            var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
 6.10391 +                            if ((d.startAngle + d.endAngle) / 2 < Math.PI) {
 6.10392 +                                rotateAngle -= 90;
 6.10393 +                            } else {
 6.10394 +                                rotateAngle += 90;
 6.10395 +                            }
 6.10396 +                            return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';
 6.10397 +                        } else {
 6.10398 +                            d.outerRadius = radius + 10; // Set Outer Coordinate
 6.10399 +                            d.innerRadius = radius + 15; // Set Inner Coordinate
 6.10400 +                            return 'translate(' + labelsArc[i].centroid(d) + ')'
 6.10401 +                        }
 6.10402 +                    });
 6.10403 +
 6.10404 +                    group.append('rect')
 6.10405 +                        .style('stroke', '#fff')
 6.10406 +                        .style('fill', '#fff')
 6.10407 +                        .attr("rx", 3)
 6.10408 +                        .attr("ry", 3);
 6.10409 +
 6.10410 +                    group.append('text')
 6.10411 +                        .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
 6.10412 +                        .style('fill', '#000')
 6.10413 +                });
 6.10414 +
 6.10415 +                var labelLocationHash = {};
 6.10416 +                var avgHeight = 14;
 6.10417 +                var avgWidth = 140;
 6.10418 +                var createHashKey = function(coordinates) {
 6.10419 +                    return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight;
 6.10420 +                };
 6.10421 +
 6.10422 +                pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) {
 6.10423 +                    if (labelSunbeamLayout) {
 6.10424 +                        d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate
 6.10425 +                        d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate
 6.10426 +                        var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
 6.10427 +                        if ((d.startAngle + d.endAngle) / 2 < Math.PI) {
 6.10428 +                            rotateAngle -= 90;
 6.10429 +                        } else {
 6.10430 +                            rotateAngle += 90;
 6.10431 +                        }
 6.10432 +                        return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';
 6.10433 +                    } else {
 6.10434 +                        d.outerRadius = radius + 10; // Set Outer Coordinate
 6.10435 +                        d.innerRadius = radius + 15; // Set Inner Coordinate
 6.10436 +
 6.10437 +                        /*
 6.10438 +                        Overlapping pie labels are not good. What this attempts to do is, prevent overlapping.
 6.10439 +                        Each label location is hashed, and if a hash collision occurs, we assume an overlap.
 6.10440 +                        Adjust the label's y-position to remove the overlap.
 6.10441 +                        */
 6.10442 +                        var center = labelsArc[i].centroid(d);
 6.10443 +                        if (d.value) {
 6.10444 +                            var hashKey = createHashKey(center);
 6.10445 +                            if (labelLocationHash[hashKey]) {
 6.10446 +                                center[1] -= avgHeight;
 6.10447 +                            }
 6.10448 +                            labelLocationHash[createHashKey(center)] = true;
 6.10449 +                        }
 6.10450 +                        return 'translate(' + center + ')'
 6.10451 +                    }
 6.10452 +                });
 6.10453 +
 6.10454 +                pieLabels.select(".nv-label text")
 6.10455 +                    .style('text-anchor', function(d,i) {
 6.10456 +                        //center the text on it's origin or begin/end if orthogonal aligned
 6.10457 +                        return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle';
 6.10458 +                    })
 6.10459 +                    .text(function(d, i) {
 6.10460 +                        var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);
 6.10461 +                        var label = '';
 6.10462 +                        if (!d.value || percent < labelThreshold) return '';
 6.10463 +
 6.10464 +                        if(typeof labelType === 'function') {
 6.10465 +                            label = labelType(d, i, {
 6.10466 +                                'key': getX(d.data),
 6.10467 +                                'value': getY(d.data),
 6.10468 +                                'percent': valueFormat(percent)
 6.10469 +                            });
 6.10470 +                        } else {
 6.10471 +                            switch (labelType) {
 6.10472 +                                case 'key':
 6.10473 +                                    label = getX(d.data);
 6.10474 +                                    break;
 6.10475 +                                case 'value':
 6.10476 +                                    label = valueFormat(getY(d.data));
 6.10477 +                                    break;
 6.10478 +                                case 'percent':
 6.10479 +                                    label = d3.format('%')(percent);
 6.10480 +                                    break;
 6.10481 +                            }
 6.10482 +                        }
 6.10483 +                        return label;
 6.10484 +                    })
 6.10485 +                ;
 6.10486 +            }
 6.10487 +
 6.10488 +
 6.10489 +            // Computes the angle of an arc, converting from radians to degrees.
 6.10490 +            function angle(d) {
 6.10491 +                var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
 6.10492 +                return a > 90 ? a - 180 : a;
 6.10493 +            }
 6.10494 +
 6.10495 +            function arcTween(a, idx) {
 6.10496 +                a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle;
 6.10497 +                a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle;
 6.10498 +                if (!donut) a.innerRadius = 0;
 6.10499 +                var i = d3.interpolate(this._current, a);
 6.10500 +                this._current = i(0);
 6.10501 +                return function (t) {
 6.10502 +                    return arcs[idx](i(t));
 6.10503 +                };
 6.10504 +            }
 6.10505 +        });
 6.10506 +
 6.10507 +        renderWatch.renderEnd('pie immediate');
 6.10508 +        return chart;
 6.10509 +    }
 6.10510 +
 6.10511 +    //============================================================
 6.10512 +    // Expose Public Variables
 6.10513 +    //------------------------------------------------------------
 6.10514 +
 6.10515 +    chart.dispatch = dispatch;
 6.10516 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.10517 +
 6.10518 +    chart._options = Object.create({}, {
 6.10519 +        // simple options, just get/set the necessary values
 6.10520 +        arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } },
 6.10521 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
 6.10522 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
 6.10523 +        showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}},
 6.10524 +        title:      {get: function(){return title;}, set: function(_){title=_;}},
 6.10525 +        titleOffset:    {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}},
 6.10526 +        labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}},
 6.10527 +        valueFormat:    {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
 6.10528 +        x:          {get: function(){return getX;}, set: function(_){getX=_;}},
 6.10529 +        id:         {get: function(){return id;}, set: function(_){id=_;}},
 6.10530 +        endAngle:   {get: function(){return endAngle;}, set: function(_){endAngle=_;}},
 6.10531 +        startAngle: {get: function(){return startAngle;}, set: function(_){startAngle=_;}},
 6.10532 +        padAngle:   {get: function(){return padAngle;}, set: function(_){padAngle=_;}},
 6.10533 +        cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}},
 6.10534 +        donutRatio:   {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}},
 6.10535 +        labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}},
 6.10536 +        labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}},
 6.10537 +        donut:              {get: function(){return donut;}, set: function(_){donut=_;}},
 6.10538 +        growOnHover:        {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}},
 6.10539 +
 6.10540 +        // depreciated after 1.7.1
 6.10541 +        pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){
 6.10542 +            labelsOutside=_;
 6.10543 +            nv.deprecated('pieLabelsOutside', 'use labelsOutside instead');
 6.10544 +        }},
 6.10545 +        // depreciated after 1.7.1
 6.10546 +        donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){
 6.10547 +            labelsOutside=_;
 6.10548 +            nv.deprecated('donutLabelsOutside', 'use labelsOutside instead');
 6.10549 +        }},
 6.10550 +        // deprecated after 1.7.1
 6.10551 +        labelFormat: {get: function(){ return valueFormat;}, set: function(_) {
 6.10552 +            valueFormat=_;
 6.10553 +            nv.deprecated('labelFormat','use valueFormat instead');
 6.10554 +        }},
 6.10555 +
 6.10556 +        // options that require extra logic in the setter
 6.10557 +        margin: {get: function(){return margin;}, set: function(_){
 6.10558 +            margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
 6.10559 +            margin.right  = typeof _.right  != 'undefined' ? _.right  : margin.right;
 6.10560 +            margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
 6.10561 +            margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
 6.10562 +        }},
 6.10563 +        y: {get: function(){return getY;}, set: function(_){
 6.10564 +            getY=d3.functor(_);
 6.10565 +        }},
 6.10566 +        color: {get: function(){return color;}, set: function(_){
 6.10567 +            color=nv.utils.getColor(_);
 6.10568 +        }},
 6.10569 +        labelType:          {get: function(){return labelType;}, set: function(_){
 6.10570 +            labelType= _ || 'key';
 6.10571 +        }}
 6.10572 +    });
 6.10573 +
 6.10574 +    nv.utils.initOptions(chart);
 6.10575 +    return chart;
 6.10576 +};
 6.10577 +nv.models.pieChart = function() {
 6.10578 +    "use strict";
 6.10579 +
 6.10580 +    //============================================================
 6.10581 +    // Public Variables with Default Settings
 6.10582 +    //------------------------------------------------------------
 6.10583 +
 6.10584 +    var pie = nv.models.pie();
 6.10585 +    var legend = nv.models.legend();
 6.10586 +    var tooltip = nv.models.tooltip();
 6.10587 +
 6.10588 +    var margin = {top: 30, right: 20, bottom: 20, left: 20}
 6.10589 +        , width = null
 6.10590 +        , height = null
 6.10591 +        , showLegend = true
 6.10592 +        , legendPosition = "top"
 6.10593 +        , color = nv.utils.defaultColor()
 6.10594 +        , state = nv.utils.state()
 6.10595 +        , defaultState = null
 6.10596 +        , noData = null
 6.10597 +        , duration = 250
 6.10598 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd')
 6.10599 +        ;
 6.10600 +
 6.10601 +    tooltip
 6.10602 +        .headerEnabled(false)
 6.10603 +        .duration(0)
 6.10604 +        .valueFormatter(function(d, i) {
 6.10605 +            return pie.valueFormat()(d, i);
 6.10606 +        });
 6.10607 +
 6.10608 +    //============================================================
 6.10609 +    // Private Variables
 6.10610 +    //------------------------------------------------------------
 6.10611 +
 6.10612 +    var renderWatch = nv.utils.renderWatch(dispatch);
 6.10613 +
 6.10614 +    var stateGetter = function(data) {
 6.10615 +        return function(){
 6.10616 +            return {
 6.10617 +                active: data.map(function(d) { return !d.disabled })
 6.10618 +            };
 6.10619 +        }
 6.10620 +    };
 6.10621 +
 6.10622 +    var stateSetter = function(data) {
 6.10623 +        return function(state) {
 6.10624 +            if (state.active !== undefined) {
 6.10625 +                data.forEach(function (series, i) {
 6.10626 +                    series.disabled = !state.active[i];
 6.10627 +                });
 6.10628 +            }
 6.10629 +        }
 6.10630 +    };
 6.10631 +
 6.10632 +    //============================================================
 6.10633 +    // Chart function
 6.10634 +    //------------------------------------------------------------
 6.10635 +
 6.10636 +    function chart(selection) {
 6.10637 +        renderWatch.reset();
 6.10638 +        renderWatch.models(pie);
 6.10639 +
 6.10640 +        selection.each(function(data) {
 6.10641 +            var container = d3.select(this);
 6.10642 +            nv.utils.initSVG(container);
 6.10643 +
 6.10644 +            var that = this;
 6.10645 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.10646 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.10647 +
 6.10648 +            chart.update = function() { container.transition().call(chart); };
 6.10649 +            chart.container = this;
 6.10650 +
 6.10651 +            state.setter(stateSetter(data), chart.update)
 6.10652 +                .getter(stateGetter(data))
 6.10653 +                .update();
 6.10654 +
 6.10655 +            //set state.disabled
 6.10656 +            state.disabled = data.map(function(d) { return !!d.disabled });
 6.10657 +
 6.10658 +            if (!defaultState) {
 6.10659 +                var key;
 6.10660 +                defaultState = {};
 6.10661 +                for (key in state) {
 6.10662 +                    if (state[key] instanceof Array)
 6.10663 +                        defaultState[key] = state[key].slice(0);
 6.10664 +                    else
 6.10665 +                        defaultState[key] = state[key];
 6.10666 +                }
 6.10667 +            }
 6.10668 +
 6.10669 +            // Display No Data message if there's nothing to show.
 6.10670 +            if (!data || !data.length) {
 6.10671 +                nv.utils.noData(chart, container);
 6.10672 +                return chart;
 6.10673 +            } else {
 6.10674 +                container.selectAll('.nv-noData').remove();
 6.10675 +            }
 6.10676 +
 6.10677 +            // Setup containers and skeleton of chart
 6.10678 +            var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);
 6.10679 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');
 6.10680 +            var g = wrap.select('g');
 6.10681 +
 6.10682 +            gEnter.append('g').attr('class', 'nv-pieWrap');
 6.10683 +            gEnter.append('g').attr('class', 'nv-legendWrap');
 6.10684 +
 6.10685 +            // Legend
 6.10686 +            if (showLegend) {
 6.10687 +                if (legendPosition === "top") {
 6.10688 +                    legend.width( availableWidth ).key(pie.x());
 6.10689 +
 6.10690 +                    wrap.select('.nv-legendWrap')
 6.10691 +                        .datum(data)
 6.10692 +                        .call(legend);
 6.10693 +
 6.10694 +                    if ( margin.top != legend.height()) {
 6.10695 +                        margin.top = legend.height();
 6.10696 +                        availableHeight = nv.utils.availableHeight(height, container, margin);
 6.10697 +                    }
 6.10698 +
 6.10699 +                    wrap.select('.nv-legendWrap')
 6.10700 +                        .attr('transform', 'translate(0,' + (-margin.top) +')');
 6.10701 +                } else if (legendPosition === "right") {
 6.10702 +                    var legendWidth = nv.models.legend().width();
 6.10703 +                    if (availableWidth / 2 < legendWidth) {
 6.10704 +                        legendWidth = (availableWidth / 2)
 6.10705 +                    }
 6.10706 +                    legend.height(availableHeight).key(pie.x());
 6.10707 +                    legend.width(legendWidth);
 6.10708 +                    availableWidth -= legend.width();
 6.10709 +
 6.10710 +                    wrap.select('.nv-legendWrap')
 6.10711 +                        .datum(data)
 6.10712 +                        .call(legend)
 6.10713 +                        .attr('transform', 'translate(' + (availableWidth) +',0)');
 6.10714 +                }
 6.10715 +            }
 6.10716 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.10717 +
 6.10718 +            // Main Chart Component(s)
 6.10719 +            pie.width(availableWidth).height(availableHeight);
 6.10720 +            var pieWrap = g.select('.nv-pieWrap').datum([data]);
 6.10721 +            d3.transition(pieWrap).call(pie);
 6.10722 +
 6.10723 +            //============================================================
 6.10724 +            // Event Handling/Dispatching (in chart's scope)
 6.10725 +            //------------------------------------------------------------
 6.10726 +
 6.10727 +            legend.dispatch.on('stateChange', function(newState) {
 6.10728 +                for (var key in newState) {
 6.10729 +                    state[key] = newState[key];
 6.10730 +                }
 6.10731 +                dispatch.stateChange(state);
 6.10732 +                chart.update();
 6.10733 +            });
 6.10734 +
 6.10735 +            // Update chart from a state object passed to event handler
 6.10736 +            dispatch.on('changeState', function(e) {
 6.10737 +                if (typeof e.disabled !== 'undefined') {
 6.10738 +                    data.forEach(function(series,i) {
 6.10739 +                        series.disabled = e.disabled[i];
 6.10740 +                    });
 6.10741 +                    state.disabled = e.disabled;
 6.10742 +                }
 6.10743 +                chart.update();
 6.10744 +            });
 6.10745 +        });
 6.10746 +
 6.10747 +        renderWatch.renderEnd('pieChart immediate');
 6.10748 +        return chart;
 6.10749 +    }
 6.10750 +
 6.10751 +    //============================================================
 6.10752 +    // Event Handling/Dispatching (out of chart's scope)
 6.10753 +    //------------------------------------------------------------
 6.10754 +
 6.10755 +    pie.dispatch.on('elementMouseover.tooltip', function(evt) {
 6.10756 +        evt['series'] = {
 6.10757 +            key: chart.x()(evt.data),
 6.10758 +            value: chart.y()(evt.data),
 6.10759 +            color: evt.color
 6.10760 +        };
 6.10761 +        tooltip.data(evt).hidden(false);
 6.10762 +    });
 6.10763 +
 6.10764 +    pie.dispatch.on('elementMouseout.tooltip', function(evt) {
 6.10765 +        tooltip.hidden(true);
 6.10766 +    });
 6.10767 +
 6.10768 +    pie.dispatch.on('elementMousemove.tooltip', function(evt) {
 6.10769 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
 6.10770 +    });
 6.10771 +
 6.10772 +    //============================================================
 6.10773 +    // Expose Public Variables
 6.10774 +    //------------------------------------------------------------
 6.10775 +
 6.10776 +    // expose chart's sub-components
 6.10777 +    chart.legend = legend;
 6.10778 +    chart.dispatch = dispatch;
 6.10779 +    chart.pie = pie;
 6.10780 +    chart.tooltip = tooltip;
 6.10781 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.10782 +
 6.10783 +    // use Object get/set functionality to map between vars and chart functions
 6.10784 +    chart._options = Object.create({}, {
 6.10785 +        // simple options, just get/set the necessary values
 6.10786 +        noData:         {get: function(){return noData;},         set: function(_){noData=_;}},
 6.10787 +        showLegend:     {get: function(){return showLegend;},     set: function(_){showLegend=_;}},
 6.10788 +        legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
 6.10789 +        defaultState:   {get: function(){return defaultState;},   set: function(_){defaultState=_;}},
 6.10790 +
 6.10791 +        // deprecated options
 6.10792 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
 6.10793 +            // deprecated after 1.7.1
 6.10794 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
 6.10795 +            tooltip.enabled(!!_);
 6.10796 +        }},
 6.10797 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
 6.10798 +            // deprecated after 1.7.1
 6.10799 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
 6.10800 +            tooltip.contentGenerator(_);
 6.10801 +        }},
 6.10802 +
 6.10803 +        // options that require extra logic in the setter
 6.10804 +        color: {get: function(){return color;}, set: function(_){
 6.10805 +            color = _;
 6.10806 +            legend.color(color);
 6.10807 +            pie.color(color);
 6.10808 +        }},
 6.10809 +        duration: {get: function(){return duration;}, set: function(_){
 6.10810 +            duration = _;
 6.10811 +            renderWatch.reset(duration);
 6.10812 +        }},
 6.10813 +        margin: {get: function(){return margin;}, set: function(_){
 6.10814 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.10815 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.10816 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.10817 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.10818 +        }}
 6.10819 +    });
 6.10820 +    nv.utils.inheritOptions(chart, pie);
 6.10821 +    nv.utils.initOptions(chart);
 6.10822 +    return chart;
 6.10823 +};
 6.10824 +
 6.10825 +nv.models.scatter = function() {
 6.10826 +    "use strict";
 6.10827 +
 6.10828 +    //============================================================
 6.10829 +    // Public Variables with Default Settings
 6.10830 +    //------------------------------------------------------------
 6.10831 +
 6.10832 +    var margin       = {top: 0, right: 0, bottom: 0, left: 0}
 6.10833 +        , width        = null
 6.10834 +        , height       = null
 6.10835 +        , color        = nv.utils.defaultColor() // chooses color
 6.10836 +        , id           = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
 6.10837 +        , container    = null
 6.10838 +        , x            = d3.scale.linear()
 6.10839 +        , y            = d3.scale.linear()
 6.10840 +        , z            = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
 6.10841 +        , getX         = function(d) { return d.x } // accessor to get the x value
 6.10842 +        , getY         = function(d) { return d.y } // accessor to get the y value
 6.10843 +        , getSize      = function(d) { return d.size || 1} // accessor to get the point size
 6.10844 +        , getShape     = function(d) { return d.shape || 'circle' } // accessor to get point shape
 6.10845 +        , forceX       = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
 6.10846 +        , forceY       = [] // List of numbers to Force into the Y scale
 6.10847 +        , forceSize    = [] // List of numbers to Force into the Size scale
 6.10848 +        , interactive  = true // If true, plots a voronoi overlay for advanced point intersection
 6.10849 +        , pointActive  = function(d) { return !d.notActive } // any points that return false will be filtered out
 6.10850 +        , padData      = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
 6.10851 +        , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding
 6.10852 +        , clipEdge     = false // if true, masks points within x and y scale
 6.10853 +        , clipVoronoi  = true // if true, masks each point with a circle... can turn off to slightly increase performance
 6.10854 +        , showVoronoi  = false // display the voronoi areas
 6.10855 +        , clipRadius   = function() { return 25 } // function to get the radius for voronoi point clips
 6.10856 +        , xDomain      = null // Override x domain (skips the calculation from data)
 6.10857 +        , yDomain      = null // Override y domain
 6.10858 +        , xRange       = null // Override x range
 6.10859 +        , yRange       = null // Override y range
 6.10860 +        , sizeDomain   = null // Override point size domain
 6.10861 +        , sizeRange    = null
 6.10862 +        , singlePoint  = false
 6.10863 +        , dispatch     = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd')
 6.10864 +        , useVoronoi   = true
 6.10865 +        , duration     = 250
 6.10866 +        ;
 6.10867 +
 6.10868 +
 6.10869 +    //============================================================
 6.10870 +    // Private Variables
 6.10871 +    //------------------------------------------------------------
 6.10872 +
 6.10873 +    var x0, y0, z0 // used to store previous scales
 6.10874 +        , timeoutID
 6.10875 +        , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
 6.10876 +        , renderWatch = nv.utils.renderWatch(dispatch, duration)
 6.10877 +        , _sizeRange_def = [16, 256]
 6.10878 +        ;
 6.10879 +
 6.10880 +    function chart(selection) {
 6.10881 +        renderWatch.reset();
 6.10882 +        selection.each(function(data) {
 6.10883 +            container = d3.select(this);
 6.10884 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.10885 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.10886 +
 6.10887 +            nv.utils.initSVG(container);
 6.10888 +
 6.10889 +            //add series index to each data point for reference
 6.10890 +            data.forEach(function(series, i) {
 6.10891 +                series.values.forEach(function(point) {
 6.10892 +                    point.series = i;
 6.10893 +                });
 6.10894 +            });
 6.10895 +
 6.10896 +            // Setup Scales
 6.10897 +            // remap and flatten the data for use in calculating the scales' domains
 6.10898 +            var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance
 6.10899 +                d3.merge(
 6.10900 +                    data.map(function(d) {
 6.10901 +                        return d.values.map(function(d,i) {
 6.10902 +                            return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }
 6.10903 +                        })
 6.10904 +                    })
 6.10905 +                );
 6.10906 +
 6.10907 +            x   .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
 6.10908 +
 6.10909 +            if (padData && data[0])
 6.10910 +                x.range(xRange || [(availableWidth * padDataOuter +  availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length)  ]);
 6.10911 +            //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5)  / data[0].values.length ]);
 6.10912 +            else
 6.10913 +                x.range(xRange || [0, availableWidth]);
 6.10914 +
 6.10915 +            y   .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
 6.10916 +                .range(yRange || [availableHeight, 0]);
 6.10917 +
 6.10918 +            z   .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))
 6.10919 +                .range(sizeRange || _sizeRange_def);
 6.10920 +
 6.10921 +            // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
 6.10922 +            singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1];
 6.10923 +
 6.10924 +            if (x.domain()[0] === x.domain()[1])
 6.10925 +                x.domain()[0] ?
 6.10926 +                    x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])
 6.10927 +                    : x.domain([-1,1]);
 6.10928 +
 6.10929 +            if (y.domain()[0] === y.domain()[1])
 6.10930 +                y.domain()[0] ?
 6.10931 +                    y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01])
 6.10932 +                    : y.domain([-1,1]);
 6.10933 +
 6.10934 +            if ( isNaN(x.domain()[0])) {
 6.10935 +                x.domain([-1,1]);
 6.10936 +            }
 6.10937 +
 6.10938 +            if ( isNaN(y.domain()[0])) {
 6.10939 +                y.domain([-1,1]);
 6.10940 +            }
 6.10941 +
 6.10942 +            x0 = x0 || x;
 6.10943 +            y0 = y0 || y;
 6.10944 +            z0 = z0 || z;
 6.10945 +
 6.10946 +            // Setup containers and skeleton of chart
 6.10947 +            var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);
 6.10948 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id);
 6.10949 +            var defsEnter = wrapEnter.append('defs');
 6.10950 +            var gEnter = wrapEnter.append('g');
 6.10951 +            var g = wrap.select('g');
 6.10952 +
 6.10953 +            wrap.classed('nv-single-point', singlePoint);
 6.10954 +            gEnter.append('g').attr('class', 'nv-groups');
 6.10955 +            gEnter.append('g').attr('class', 'nv-point-paths');
 6.10956 +            wrapEnter.append('g').attr('class', 'nv-point-clips');
 6.10957 +
 6.10958 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.10959 +
 6.10960 +            defsEnter.append('clipPath')
 6.10961 +                .attr('id', 'nv-edge-clip-' + id)
 6.10962 +                .append('rect');
 6.10963 +
 6.10964 +            wrap.select('#nv-edge-clip-' + id + ' rect')
 6.10965 +                .attr('width', availableWidth)
 6.10966 +                .attr('height', (availableHeight > 0) ? availableHeight : 0);
 6.10967 +
 6.10968 +            g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
 6.10969 +
 6.10970 +            function updateInteractiveLayer() {
 6.10971 +                // Always clear needs-update flag regardless of whether or not
 6.10972 +                // we will actually do anything (avoids needless invocations).
 6.10973 +                needsUpdate = false;
 6.10974 +
 6.10975 +                if (!interactive) return false;
 6.10976 +
 6.10977 +                // inject series and point index for reference into voronoi
 6.10978 +                if (useVoronoi === true) {
 6.10979 +                    var vertices = d3.merge(data.map(function(group, groupIndex) {
 6.10980 +                            return group.values
 6.10981 +                                .map(function(point, pointIndex) {
 6.10982 +                                    // *Adding noise to make duplicates very unlikely
 6.10983 +                                    // *Injecting series and point index for reference
 6.10984 +                                    /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.
 6.10985 +                                     */
 6.10986 +                                    var pX = getX(point,pointIndex);
 6.10987 +                                    var pY = getY(point,pointIndex);
 6.10988 +
 6.10989 +                                    return [x(pX)+ Math.random() * 1e-4,
 6.10990 +                                            y(pY)+ Math.random() * 1e-4,
 6.10991 +                                        groupIndex,
 6.10992 +                                        pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates
 6.10993 +                                })
 6.10994 +                                .filter(function(pointArray, pointIndex) {
 6.10995 +                                    return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!
 6.10996 +                                })
 6.10997 +                        })
 6.10998 +                    );
 6.10999 +
 6.11000 +                    if (vertices.length == 0) return false;  // No active points, we're done
 6.11001 +                    if (vertices.length < 3) {
 6.11002 +                        // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
 6.11003 +                        vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);
 6.11004 +                        vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);
 6.11005 +                        vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
 6.11006 +                        vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
 6.11007 +                    }
 6.11008 +
 6.11009 +                    // keep voronoi sections from going more than 10 outside of graph
 6.11010 +                    // to avoid overlap with other things like legend etc
 6.11011 +                    var bounds = d3.geom.polygon([
 6.11012 +                        [-10,-10],
 6.11013 +                        [-10,height + 10],
 6.11014 +                        [width + 10,height + 10],
 6.11015 +                        [width + 10,-10]
 6.11016 +                    ]);
 6.11017 +
 6.11018 +                    var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
 6.11019 +                        return {
 6.11020 +                            'data': bounds.clip(d),
 6.11021 +                            'series': vertices[i][2],
 6.11022 +                            'point': vertices[i][3]
 6.11023 +                        }
 6.11024 +                    });
 6.11025 +
 6.11026 +                    // nuke all voronoi paths on reload and recreate them
 6.11027 +                    wrap.select('.nv-point-paths').selectAll('path').remove();
 6.11028 +                    var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi);
 6.11029 +                    var vPointPaths = pointPaths
 6.11030 +                        .enter().append("svg:path")
 6.11031 +                        .attr("d", function(d) {
 6.11032 +                            if (!d || !d.data || d.data.length === 0)
 6.11033 +                                return 'M 0 0';
 6.11034 +                            else
 6.11035 +                                return "M" + d.data.join(",") + "Z";
 6.11036 +                        })
 6.11037 +                        .attr("id", function(d,i) {
 6.11038 +                            return "nv-path-"+i; })
 6.11039 +                        .attr("clip-path", function(d,i) { return "url(#nv-clip-"+i+")"; })
 6.11040 +                        ;
 6.11041 +
 6.11042 +                    // good for debugging point hover issues
 6.11043 +                    if (showVoronoi) {
 6.11044 +                        vPointPaths.style("fill", d3.rgb(230, 230, 230))
 6.11045 +                            .style('fill-opacity', 0.4)
 6.11046 +                            .style('stroke-opacity', 1)
 6.11047 +                            .style("stroke", d3.rgb(200,200,200));
 6.11048 +                    }
 6.11049 +
 6.11050 +                    if (clipVoronoi) {
 6.11051 +                        // voronoi sections are already set to clip,
 6.11052 +                        // just create the circles with the IDs they expect
 6.11053 +                        wrap.select('.nv-point-clips').selectAll('clipPath').remove();
 6.11054 +                        wrap.select('.nv-point-clips').selectAll("clipPath")
 6.11055 +                            .data(vertices)
 6.11056 +                            .enter().append("svg:clipPath")
 6.11057 +                            .attr("id", function(d, i) { return "nv-clip-"+i;})
 6.11058 +                            .append("svg:circle")
 6.11059 +                            .attr('cx', function(d) { return d[0]; })
 6.11060 +                            .attr('cy', function(d) { return d[1]; })
 6.11061 +                            .attr('r', clipRadius);
 6.11062 +                    }
 6.11063 +
 6.11064 +                    var mouseEventCallback = function(d, mDispatch) {
 6.11065 +                        if (needsUpdate) return 0;
 6.11066 +                        var series = data[d.series];
 6.11067 +                        if (series === undefined) return;
 6.11068 +                        var point  = series.values[d.point];
 6.11069 +                        point['color'] = color(series, d.series);
 6.11070 +
 6.11071 +                        // standardize attributes for tooltip.
 6.11072 +                        point['x'] = getX(point);
 6.11073 +                        point['y'] = getY(point);
 6.11074 +
 6.11075 +                        // can't just get box of event node since it's actually a voronoi polygon
 6.11076 +                        var box = container.node().getBoundingClientRect();
 6.11077 +                        var scrollTop  = window.pageYOffset || document.documentElement.scrollTop;
 6.11078 +                        var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
 6.11079 +
 6.11080 +                        var pos = {
 6.11081 +                            left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10,
 6.11082 +                            top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10
 6.11083 +                        };
 6.11084 +
 6.11085 +                        mDispatch({
 6.11086 +                            point: point,
 6.11087 +                            series: series,
 6.11088 +                            pos: pos,
 6.11089 +                            seriesIndex: d.series,
 6.11090 +                            pointIndex: d.point
 6.11091 +                        });
 6.11092 +                    };
 6.11093 +
 6.11094 +                    pointPaths
 6.11095 +                        .on('click', function(d) {
 6.11096 +                            mouseEventCallback(d, dispatch.elementClick);
 6.11097 +                        })
 6.11098 +                        .on('dblclick', function(d) {
 6.11099 +                            mouseEventCallback(d, dispatch.elementDblClick);
 6.11100 +                        })
 6.11101 +                        .on('mouseover', function(d) {
 6.11102 +                            mouseEventCallback(d, dispatch.elementMouseover);
 6.11103 +                        })
 6.11104 +                        .on('mouseout', function(d, i) {
 6.11105 +                            mouseEventCallback(d, dispatch.elementMouseout);
 6.11106 +                        });
 6.11107 +
 6.11108 +                } else {
 6.11109 +                    // add event handlers to points instead voronoi paths
 6.11110 +                    wrap.select('.nv-groups').selectAll('.nv-group')
 6.11111 +                        .selectAll('.nv-point')
 6.11112 +                        //.data(dataWithPoints)
 6.11113 +                        //.style('pointer-events', 'auto') // recativate events, disabled by css
 6.11114 +                        .on('click', function(d,i) {
 6.11115 +                            //nv.log('test', d, i);
 6.11116 +                            if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
 6.11117 +                            var series = data[d.series],
 6.11118 +                                point  = series.values[i];
 6.11119 +
 6.11120 +                            dispatch.elementClick({
 6.11121 +                                point: point,
 6.11122 +                                series: series,
 6.11123 +                                pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
 6.11124 +                                seriesIndex: d.series,
 6.11125 +                                pointIndex: i
 6.11126 +                            });
 6.11127 +                        })
 6.11128 +                        .on('dblclick', function(d,i) {
 6.11129 +                            if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
 6.11130 +                            var series = data[d.series],
 6.11131 +                                point  = series.values[i];
 6.11132 +
 6.11133 +                            dispatch.elementDblClick({
 6.11134 +                                point: point,
 6.11135 +                                series: series,
 6.11136 +                                pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
 6.11137 +                                seriesIndex: d.series,
 6.11138 +                                pointIndex: i
 6.11139 +                            });
 6.11140 +                        })
 6.11141 +                        .on('mouseover', function(d,i) {
 6.11142 +                            if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
 6.11143 +                            var series = data[d.series],
 6.11144 +                                point  = series.values[i];
 6.11145 +
 6.11146 +                            dispatch.elementMouseover({
 6.11147 +                                point: point,
 6.11148 +                                series: series,
 6.11149 +                                pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
 6.11150 +                                seriesIndex: d.series,
 6.11151 +                                pointIndex: i,
 6.11152 +                                color: color(d, i)
 6.11153 +                            });
 6.11154 +                        })
 6.11155 +                        .on('mouseout', function(d,i) {
 6.11156 +                            if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
 6.11157 +                            var series = data[d.series],
 6.11158 +                                point  = series.values[i];
 6.11159 +
 6.11160 +                            dispatch.elementMouseout({
 6.11161 +                                point: point,
 6.11162 +                                series: series,
 6.11163 +                                seriesIndex: d.series,
 6.11164 +                                pointIndex: i,
 6.11165 +                                color: color(d, i)
 6.11166 +                            });
 6.11167 +                        });
 6.11168 +                }
 6.11169 +            }
 6.11170 +
 6.11171 +            needsUpdate = true;
 6.11172 +            var groups = wrap.select('.nv-groups').selectAll('.nv-group')
 6.11173 +                .data(function(d) { return d }, function(d) { return d.key });
 6.11174 +            groups.enter().append('g')
 6.11175 +                .style('stroke-opacity', 1e-6)
 6.11176 +                .style('fill-opacity', 1e-6);
 6.11177 +            groups.exit()
 6.11178 +                .remove();
 6.11179 +            groups
 6.11180 +                .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
 6.11181 +                .classed('hover', function(d) { return d.hover });
 6.11182 +            groups.watchTransition(renderWatch, 'scatter: groups')
 6.11183 +                .style('fill', function(d,i) { return color(d, i) })
 6.11184 +                .style('stroke', function(d,i) { return color(d, i) })
 6.11185 +                .style('stroke-opacity', 1)
 6.11186 +                .style('fill-opacity', .5);
 6.11187 +
 6.11188 +            // create the points, maintaining their IDs from the original data set
 6.11189 +            var points = groups.selectAll('path.nv-point')
 6.11190 +                .data(function(d) {
 6.11191 +                    return d.values.map(
 6.11192 +                        function (point, pointIndex) {
 6.11193 +                            return [point, pointIndex]
 6.11194 +                        }).filter(
 6.11195 +                            function(pointArray, pointIndex) {
 6.11196 +                                return pointActive(pointArray[0], pointIndex)
 6.11197 +                            })
 6.11198 +                    });
 6.11199 +            points.enter().append('path')
 6.11200 +                .style('fill', function (d) { return d.color })
 6.11201 +                .style('stroke', function (d) { return d.color })
 6.11202 +                .attr('transform', function(d) {
 6.11203 +                    return 'translate(' + x0(getX(d[0],d[1])) + ',' + y0(getY(d[0],d[1])) + ')'
 6.11204 +                })
 6.11205 +                .attr('d',
 6.11206 +                    nv.utils.symbol()
 6.11207 +                    .type(function(d) { return getShape(d[0]); })
 6.11208 +                    .size(function(d) { return z(getSize(d[0],d[1])) })
 6.11209 +            );
 6.11210 +            points.exit().remove();
 6.11211 +            groups.exit().selectAll('path.nv-point')
 6.11212 +                .watchTransition(renderWatch, 'scatter exit')
 6.11213 +                .attr('transform', function(d) {
 6.11214 +                    return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')'
 6.11215 +                })
 6.11216 +                .remove();
 6.11217 +            points.each(function(d) {
 6.11218 +                d3.select(this)
 6.11219 +                    .classed('nv-point', true)
 6.11220 +                    .classed('nv-point-' + d[1], true)
 6.11221 +                    .classed('nv-noninteractive', !interactive)
 6.11222 +                    .classed('hover',false)
 6.11223 +                ;
 6.11224 +            });
 6.11225 +            points
 6.11226 +                .watchTransition(renderWatch, 'scatter points')
 6.11227 +                .attr('transform', function(d) {
 6.11228 +                    //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1])));
 6.11229 +                    return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')'
 6.11230 +                })
 6.11231 +                .attr('d',
 6.11232 +                    nv.utils.symbol()
 6.11233 +                    .type(function(d) { return getShape(d[0]); })
 6.11234 +                    .size(function(d) { return z(getSize(d[0],d[1])) })
 6.11235 +            );
 6.11236 +
 6.11237 +            // Delay updating the invisible interactive layer for smoother animation
 6.11238 +            clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
 6.11239 +            timeoutID = setTimeout(updateInteractiveLayer, 300);
 6.11240 +            //updateInteractiveLayer();
 6.11241 +
 6.11242 +            //store old scales for use in transitions on update
 6.11243 +            x0 = x.copy();
 6.11244 +            y0 = y.copy();
 6.11245 +            z0 = z.copy();
 6.11246 +
 6.11247 +        });
 6.11248 +        renderWatch.renderEnd('scatter immediate');
 6.11249 +        return chart;
 6.11250 +    }
 6.11251 +
 6.11252 +    //============================================================
 6.11253 +    // Expose Public Variables
 6.11254 +    //------------------------------------------------------------
 6.11255 +
 6.11256 +    chart.dispatch = dispatch;
 6.11257 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.11258 +
 6.11259 +    // utility function calls provided by this chart
 6.11260 +    chart._calls = new function() {
 6.11261 +        this.clearHighlights = function () {
 6.11262 +            nv.dom.write(function() {
 6.11263 +                container.selectAll(".nv-point.hover").classed("hover", false);
 6.11264 +            });
 6.11265 +            return null;
 6.11266 +        };
 6.11267 +        this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) {
 6.11268 +            nv.dom.write(function() {
 6.11269 +                container.select(" .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
 6.11270 +                    .classed("hover", isHoverOver);
 6.11271 +            });
 6.11272 +        };
 6.11273 +    };
 6.11274 +
 6.11275 +    // trigger calls from events too
 6.11276 +    dispatch.on('elementMouseover.point', function(d) {
 6.11277 +        if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,true);
 6.11278 +    });
 6.11279 +
 6.11280 +    dispatch.on('elementMouseout.point', function(d) {
 6.11281 +        if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,false);
 6.11282 +    });
 6.11283 +
 6.11284 +    chart._options = Object.create({}, {
 6.11285 +        // simple options, just get/set the necessary values
 6.11286 +        width:        {get: function(){return width;}, set: function(_){width=_;}},
 6.11287 +        height:       {get: function(){return height;}, set: function(_){height=_;}},
 6.11288 +        xScale:       {get: function(){return x;}, set: function(_){x=_;}},
 6.11289 +        yScale:       {get: function(){return y;}, set: function(_){y=_;}},
 6.11290 +        pointScale:   {get: function(){return z;}, set: function(_){z=_;}},
 6.11291 +        xDomain:      {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
 6.11292 +        yDomain:      {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
 6.11293 +        pointDomain:  {get: function(){return sizeDomain;}, set: function(_){sizeDomain=_;}},
 6.11294 +        xRange:       {get: function(){return xRange;}, set: function(_){xRange=_;}},
 6.11295 +        yRange:       {get: function(){return yRange;}, set: function(_){yRange=_;}},
 6.11296 +        pointRange:   {get: function(){return sizeRange;}, set: function(_){sizeRange=_;}},
 6.11297 +        forceX:       {get: function(){return forceX;}, set: function(_){forceX=_;}},
 6.11298 +        forceY:       {get: function(){return forceY;}, set: function(_){forceY=_;}},
 6.11299 +        forcePoint:   {get: function(){return forceSize;}, set: function(_){forceSize=_;}},
 6.11300 +        interactive:  {get: function(){return interactive;}, set: function(_){interactive=_;}},
 6.11301 +        pointActive:  {get: function(){return pointActive;}, set: function(_){pointActive=_;}},
 6.11302 +        padDataOuter: {get: function(){return padDataOuter;}, set: function(_){padDataOuter=_;}},
 6.11303 +        padData:      {get: function(){return padData;}, set: function(_){padData=_;}},
 6.11304 +        clipEdge:     {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
 6.11305 +        clipVoronoi:  {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}},
 6.11306 +        clipRadius:   {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}},
 6.11307 +        showVoronoi:   {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}},
 6.11308 +        id:           {get: function(){return id;}, set: function(_){id=_;}},
 6.11309 +
 6.11310 +
 6.11311 +        // simple functor options
 6.11312 +        x:     {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},
 6.11313 +        y:     {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},
 6.11314 +        pointSize: {get: function(){return getSize;}, set: function(_){getSize = d3.functor(_);}},
 6.11315 +        pointShape: {get: function(){return getShape;}, set: function(_){getShape = d3.functor(_);}},
 6.11316 +
 6.11317 +        // options that require extra logic in the setter
 6.11318 +        margin: {get: function(){return margin;}, set: function(_){
 6.11319 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.11320 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.11321 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.11322 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.11323 +        }},
 6.11324 +        duration: {get: function(){return duration;}, set: function(_){
 6.11325 +            duration = _;
 6.11326 +            renderWatch.reset(duration);
 6.11327 +        }},
 6.11328 +        color: {get: function(){return color;}, set: function(_){
 6.11329 +            color = nv.utils.getColor(_);
 6.11330 +        }},
 6.11331 +        useVoronoi: {get: function(){return useVoronoi;}, set: function(_){
 6.11332 +            useVoronoi = _;
 6.11333 +            if (useVoronoi === false) {
 6.11334 +                clipVoronoi = false;
 6.11335 +            }
 6.11336 +        }}
 6.11337 +    });
 6.11338 +
 6.11339 +    nv.utils.initOptions(chart);
 6.11340 +    return chart;
 6.11341 +};
 6.11342 +
 6.11343 +nv.models.scatterChart = function() {
 6.11344 +    "use strict";
 6.11345 +
 6.11346 +    //============================================================
 6.11347 +    // Public Variables with Default Settings
 6.11348 +    //------------------------------------------------------------
 6.11349 +
 6.11350 +    var scatter      = nv.models.scatter()
 6.11351 +        , xAxis        = nv.models.axis()
 6.11352 +        , yAxis        = nv.models.axis()
 6.11353 +        , legend       = nv.models.legend()
 6.11354 +        , distX        = nv.models.distribution()
 6.11355 +        , distY        = nv.models.distribution()
 6.11356 +        , tooltip      = nv.models.tooltip()
 6.11357 +        ;
 6.11358 +
 6.11359 +    var margin       = {top: 30, right: 20, bottom: 50, left: 75}
 6.11360 +        , width        = null
 6.11361 +        , height       = null
 6.11362 +        , container    = null
 6.11363 +        , color        = nv.utils.defaultColor()
 6.11364 +        , x            = scatter.xScale()
 6.11365 +        , y            = scatter.yScale()
 6.11366 +        , showDistX    = false
 6.11367 +        , showDistY    = false
 6.11368 +        , showLegend   = true
 6.11369 +        , showXAxis    = true
 6.11370 +        , showYAxis    = true
 6.11371 +        , rightAlignYAxis = false
 6.11372 +        , state = nv.utils.state()
 6.11373 +        , defaultState = null
 6.11374 +        , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
 6.11375 +        , noData       = null
 6.11376 +        , duration = 250
 6.11377 +        ;
 6.11378 +
 6.11379 +    scatter.xScale(x).yScale(y);
 6.11380 +    xAxis.orient('bottom').tickPadding(10);
 6.11381 +    yAxis
 6.11382 +        .orient((rightAlignYAxis) ? 'right' : 'left')
 6.11383 +        .tickPadding(10)
 6.11384 +    ;
 6.11385 +    distX.axis('x');
 6.11386 +    distY.axis('y');
 6.11387 +    tooltip
 6.11388 +        .headerFormatter(function(d, i) {
 6.11389 +            return xAxis.tickFormat()(d, i);
 6.11390 +        })
 6.11391 +        .valueFormatter(function(d, i) {
 6.11392 +            return yAxis.tickFormat()(d, i);
 6.11393 +        });
 6.11394 +
 6.11395 +    //============================================================
 6.11396 +    // Private Variables
 6.11397 +    //------------------------------------------------------------
 6.11398 +
 6.11399 +    var x0, y0
 6.11400 +        , renderWatch = nv.utils.renderWatch(dispatch, duration);
 6.11401 +
 6.11402 +    var stateGetter = function(data) {
 6.11403 +        return function(){
 6.11404 +            return {
 6.11405 +                active: data.map(function(d) { return !d.disabled })
 6.11406 +            };
 6.11407 +        }
 6.11408 +    };
 6.11409 +
 6.11410 +    var stateSetter = function(data) {
 6.11411 +        return function(state) {
 6.11412 +            if (state.active !== undefined)
 6.11413 +                data.forEach(function(series,i) {
 6.11414 +                    series.disabled = !state.active[i];
 6.11415 +                });
 6.11416 +        }
 6.11417 +    };
 6.11418 +
 6.11419 +    function chart(selection) {
 6.11420 +        renderWatch.reset();
 6.11421 +        renderWatch.models(scatter);
 6.11422 +        if (showXAxis) renderWatch.models(xAxis);
 6.11423 +        if (showYAxis) renderWatch.models(yAxis);
 6.11424 +        if (showDistX) renderWatch.models(distX);
 6.11425 +        if (showDistY) renderWatch.models(distY);
 6.11426 +
 6.11427 +        selection.each(function(data) {
 6.11428 +            var that = this;
 6.11429 +
 6.11430 +            container = d3.select(this);
 6.11431 +            nv.utils.initSVG(container);
 6.11432 +
 6.11433 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.11434 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.11435 +
 6.11436 +            chart.update = function() {
 6.11437 +                if (duration === 0)
 6.11438 +                    container.call(chart);
 6.11439 +                else
 6.11440 +                    container.transition().duration(duration).call(chart);
 6.11441 +            };
 6.11442 +            chart.container = this;
 6.11443 +
 6.11444 +            state
 6.11445 +                .setter(stateSetter(data), chart.update)
 6.11446 +                .getter(stateGetter(data))
 6.11447 +                .update();
 6.11448 +
 6.11449 +            // DEPRECATED set state.disableddisabled
 6.11450 +            state.disabled = data.map(function(d) { return !!d.disabled });
 6.11451 +
 6.11452 +            if (!defaultState) {
 6.11453 +                var key;
 6.11454 +                defaultState = {};
 6.11455 +                for (key in state) {
 6.11456 +                    if (state[key] instanceof Array)
 6.11457 +                        defaultState[key] = state[key].slice(0);
 6.11458 +                    else
 6.11459 +                        defaultState[key] = state[key];
 6.11460 +                }
 6.11461 +            }
 6.11462 +
 6.11463 +            // Display noData message if there's nothing to show.
 6.11464 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
 6.11465 +                nv.utils.noData(chart, container);
 6.11466 +                renderWatch.renderEnd('scatter immediate');
 6.11467 +                return chart;
 6.11468 +            } else {
 6.11469 +                container.selectAll('.nv-noData').remove();
 6.11470 +            }
 6.11471 +
 6.11472 +            // Setup Scales
 6.11473 +            x = scatter.xScale();
 6.11474 +            y = scatter.yScale();
 6.11475 +
 6.11476 +            // Setup containers and skeleton of chart
 6.11477 +            var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
 6.11478 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
 6.11479 +            var gEnter = wrapEnter.append('g');
 6.11480 +            var g = wrap.select('g');
 6.11481 +
 6.11482 +            // background for pointer events
 6.11483 +            gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none");
 6.11484 +
 6.11485 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
 6.11486 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
 6.11487 +            gEnter.append('g').attr('class', 'nv-scatterWrap');
 6.11488 +            gEnter.append('g').attr('class', 'nv-regressionLinesWrap');
 6.11489 +            gEnter.append('g').attr('class', 'nv-distWrap');
 6.11490 +            gEnter.append('g').attr('class', 'nv-legendWrap');
 6.11491 +
 6.11492 +            if (rightAlignYAxis) {
 6.11493 +                g.select(".nv-y.nv-axis")
 6.11494 +                    .attr("transform", "translate(" + availableWidth + ",0)");
 6.11495 +            }
 6.11496 +
 6.11497 +            // Legend
 6.11498 +            if (showLegend) {
 6.11499 +                var legendWidth = availableWidth;
 6.11500 +                legend.width(legendWidth);
 6.11501 +
 6.11502 +                wrap.select('.nv-legendWrap')
 6.11503 +                    .datum(data)
 6.11504 +                    .call(legend);
 6.11505 +
 6.11506 +                if ( margin.top != legend.height()) {
 6.11507 +                    margin.top = legend.height();
 6.11508 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
 6.11509 +                }
 6.11510 +
 6.11511 +                wrap.select('.nv-legendWrap')
 6.11512 +                    .attr('transform', 'translate(0' + ',' + (-margin.top) +')');
 6.11513 +            }
 6.11514 +
 6.11515 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.11516 +
 6.11517 +            // Main Chart Component(s)
 6.11518 +            scatter
 6.11519 +                .width(availableWidth)
 6.11520 +                .height(availableHeight)
 6.11521 +                .color(data.map(function(d,i) {
 6.11522 +                    d.color = d.color || color(d, i);
 6.11523 +                    return d.color;
 6.11524 +                }).filter(function(d,i) { return !data[i].disabled }));
 6.11525 +
 6.11526 +            wrap.select('.nv-scatterWrap')
 6.11527 +                .datum(data.filter(function(d) { return !d.disabled }))
 6.11528 +                .call(scatter);
 6.11529 +
 6.11530 +
 6.11531 +            wrap.select('.nv-regressionLinesWrap')
 6.11532 +                .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')');
 6.11533 +
 6.11534 +            var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines')
 6.11535 +                .data(function (d) {
 6.11536 +                    return d;
 6.11537 +                });
 6.11538 +
 6.11539 +            regWrap.enter().append('g').attr('class', 'nv-regLines');
 6.11540 +
 6.11541 +            var regLine = regWrap.selectAll('.nv-regLine')
 6.11542 +                .data(function (d) {
 6.11543 +                    return [d]
 6.11544 +                });
 6.11545 +
 6.11546 +            regLine.enter()
 6.11547 +                .append('line').attr('class', 'nv-regLine')
 6.11548 +                .style('stroke-opacity', 0);
 6.11549 +
 6.11550 +            // don't add lines unless we have slope and intercept to use
 6.11551 +            regLine.filter(function(d) {
 6.11552 +                return d.intercept && d.slope;
 6.11553 +            })
 6.11554 +                .watchTransition(renderWatch, 'scatterPlusLineChart: regline')
 6.11555 +                .attr('x1', x.range()[0])
 6.11556 +                .attr('x2', x.range()[1])
 6.11557 +                .attr('y1', function (d, i) {
 6.11558 +                    return y(x.domain()[0] * d.slope + d.intercept)
 6.11559 +                })
 6.11560 +                .attr('y2', function (d, i) {
 6.11561 +                    return y(x.domain()[1] * d.slope + d.intercept)
 6.11562 +                })
 6.11563 +                .style('stroke', function (d, i, j) {
 6.11564 +                    return color(d, j)
 6.11565 +                })
 6.11566 +                .style('stroke-opacity', function (d, i) {
 6.11567 +                    return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1
 6.11568 +                });
 6.11569 +
 6.11570 +            // Setup Axes
 6.11571 +            if (showXAxis) {
 6.11572 +                xAxis
 6.11573 +                    .scale(x)
 6.11574 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
 6.11575 +                    .tickSize( -availableHeight , 0);
 6.11576 +
 6.11577 +                g.select('.nv-x.nv-axis')
 6.11578 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')')
 6.11579 +                    .call(xAxis);
 6.11580 +            }
 6.11581 +
 6.11582 +            if (showYAxis) {
 6.11583 +                yAxis
 6.11584 +                    .scale(y)
 6.11585 +                    ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
 6.11586 +                    .tickSize( -availableWidth, 0);
 6.11587 +
 6.11588 +                g.select('.nv-y.nv-axis')
 6.11589 +                    .call(yAxis);
 6.11590 +            }
 6.11591 +
 6.11592 +
 6.11593 +            if (showDistX) {
 6.11594 +                distX
 6.11595 +                    .getData(scatter.x())
 6.11596 +                    .scale(x)
 6.11597 +                    .width(availableWidth)
 6.11598 +                    .color(data.map(function(d,i) {
 6.11599 +                        return d.color || color(d, i);
 6.11600 +                    }).filter(function(d,i) { return !data[i].disabled }));
 6.11601 +                gEnter.select('.nv-distWrap').append('g')
 6.11602 +                    .attr('class', 'nv-distributionX');
 6.11603 +                g.select('.nv-distributionX')
 6.11604 +                    .attr('transform', 'translate(0,' + y.range()[0] + ')')
 6.11605 +                    .datum(data.filter(function(d) { return !d.disabled }))
 6.11606 +                    .call(distX);
 6.11607 +            }
 6.11608 +
 6.11609 +            if (showDistY) {
 6.11610 +                distY
 6.11611 +                    .getData(scatter.y())
 6.11612 +                    .scale(y)
 6.11613 +                    .width(availableHeight)
 6.11614 +                    .color(data.map(function(d,i) {
 6.11615 +                        return d.color || color(d, i);
 6.11616 +                    }).filter(function(d,i) { return !data[i].disabled }));
 6.11617 +                gEnter.select('.nv-distWrap').append('g')
 6.11618 +                    .attr('class', 'nv-distributionY');
 6.11619 +                g.select('.nv-distributionY')
 6.11620 +                    .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')
 6.11621 +                    .datum(data.filter(function(d) { return !d.disabled }))
 6.11622 +                    .call(distY);
 6.11623 +            }
 6.11624 +
 6.11625 +            //============================================================
 6.11626 +            // Event Handling/Dispatching (in chart's scope)
 6.11627 +            //------------------------------------------------------------
 6.11628 +
 6.11629 +            legend.dispatch.on('stateChange', function(newState) {
 6.11630 +                for (var key in newState)
 6.11631 +                    state[key] = newState[key];
 6.11632 +                dispatch.stateChange(state);
 6.11633 +                chart.update();
 6.11634 +            });
 6.11635 +
 6.11636 +            // Update chart from a state object passed to event handler
 6.11637 +            dispatch.on('changeState', function(e) {
 6.11638 +                if (typeof e.disabled !== 'undefined') {
 6.11639 +                    data.forEach(function(series,i) {
 6.11640 +                        series.disabled = e.disabled[i];
 6.11641 +                    });
 6.11642 +                    state.disabled = e.disabled;
 6.11643 +                }
 6.11644 +                chart.update();
 6.11645 +            });
 6.11646 +
 6.11647 +            // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block
 6.11648 +            scatter.dispatch.on('elementMouseout.tooltip', function(evt) {
 6.11649 +                tooltip.hidden(true);
 6.11650 +                container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)
 6.11651 +                    .attr('y1', 0);
 6.11652 +                container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)
 6.11653 +                    .attr('x2', distY.size());
 6.11654 +            });
 6.11655 +
 6.11656 +            scatter.dispatch.on('elementMouseover.tooltip', function(evt) {
 6.11657 +                container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)
 6.11658 +                    .attr('y1', evt.pos.top - availableHeight - margin.top);
 6.11659 +                container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)
 6.11660 +                    .attr('x2', evt.pos.left + distX.size() - margin.left);
 6.11661 +                tooltip.position(evt.pos).data(evt).hidden(false);
 6.11662 +            });
 6.11663 +
 6.11664 +            //store old scales for use in transitions on update
 6.11665 +            x0 = x.copy();
 6.11666 +            y0 = y.copy();
 6.11667 +
 6.11668 +        });
 6.11669 +
 6.11670 +        renderWatch.renderEnd('scatter with line immediate');
 6.11671 +        return chart;
 6.11672 +    }
 6.11673 +
 6.11674 +    //============================================================
 6.11675 +    // Expose Public Variables
 6.11676 +    //------------------------------------------------------------
 6.11677 +
 6.11678 +    // expose chart's sub-components
 6.11679 +    chart.dispatch = dispatch;
 6.11680 +    chart.scatter = scatter;
 6.11681 +    chart.legend = legend;
 6.11682 +    chart.xAxis = xAxis;
 6.11683 +    chart.yAxis = yAxis;
 6.11684 +    chart.distX = distX;
 6.11685 +    chart.distY = distY;
 6.11686 +    chart.tooltip = tooltip;
 6.11687 +
 6.11688 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.11689 +    chart._options = Object.create({}, {
 6.11690 +        // simple options, just get/set the necessary values
 6.11691 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
 6.11692 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
 6.11693 +        container:  {get: function(){return container;}, set: function(_){container=_;}},
 6.11694 +        showDistX:  {get: function(){return showDistX;}, set: function(_){showDistX=_;}},
 6.11695 +        showDistY:  {get: function(){return showDistY;}, set: function(_){showDistY=_;}},
 6.11696 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
 6.11697 +        showXAxis:  {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
 6.11698 +        showYAxis:  {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
 6.11699 +        defaultState:     {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
 6.11700 +        noData:     {get: function(){return noData;}, set: function(_){noData=_;}},
 6.11701 +        duration:   {get: function(){return duration;}, set: function(_){duration=_;}},
 6.11702 +
 6.11703 +        // deprecated options
 6.11704 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
 6.11705 +            // deprecated after 1.7.1
 6.11706 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
 6.11707 +            tooltip.enabled(!!_);
 6.11708 +        }},
 6.11709 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
 6.11710 +            // deprecated after 1.7.1
 6.11711 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
 6.11712 +            tooltip.contentGenerator(_);
 6.11713 +        }},
 6.11714 +        tooltipXContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
 6.11715 +            // deprecated after 1.7.1
 6.11716 +            nv.deprecated('tooltipContent', 'This option is removed, put values into main tooltip.');
 6.11717 +        }},
 6.11718 +        tooltipYContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
 6.11719 +            // deprecated after 1.7.1
 6.11720 +            nv.deprecated('tooltipContent', 'This option is removed, put values into main tooltip.');
 6.11721 +        }},
 6.11722 +
 6.11723 +        // options that require extra logic in the setter
 6.11724 +        margin: {get: function(){return margin;}, set: function(_){
 6.11725 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.11726 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.11727 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.11728 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.11729 +        }},
 6.11730 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
 6.11731 +            rightAlignYAxis = _;
 6.11732 +            yAxis.orient( (_) ? 'right' : 'left');
 6.11733 +        }},
 6.11734 +        color: {get: function(){return color;}, set: function(_){
 6.11735 +            color = nv.utils.getColor(_);
 6.11736 +            legend.color(color);
 6.11737 +            distX.color(color);
 6.11738 +            distY.color(color);
 6.11739 +        }}
 6.11740 +    });
 6.11741 +
 6.11742 +    nv.utils.inheritOptions(chart, scatter);
 6.11743 +    nv.utils.initOptions(chart);
 6.11744 +    return chart;
 6.11745 +};
 6.11746 +
 6.11747 +nv.models.sparkline = function() {
 6.11748 +    "use strict";
 6.11749 +
 6.11750 +    //============================================================
 6.11751 +    // Public Variables with Default Settings
 6.11752 +    //------------------------------------------------------------
 6.11753 +
 6.11754 +    var margin = {top: 2, right: 0, bottom: 2, left: 0}
 6.11755 +        , width = 400
 6.11756 +        , height = 32
 6.11757 +        , container = null
 6.11758 +        , animate = true
 6.11759 +        , x = d3.scale.linear()
 6.11760 +        , y = d3.scale.linear()
 6.11761 +        , getX = function(d) { return d.x }
 6.11762 +        , getY = function(d) { return d.y }
 6.11763 +        , color = nv.utils.getColor(['#000'])
 6.11764 +        , xDomain
 6.11765 +        , yDomain
 6.11766 +        , xRange
 6.11767 +        , yRange
 6.11768 +        ;
 6.11769 +
 6.11770 +    function chart(selection) {
 6.11771 +        selection.each(function(data) {
 6.11772 +            var availableWidth = width - margin.left - margin.right,
 6.11773 +                availableHeight = height - margin.top - margin.bottom;
 6.11774 +
 6.11775 +            container = d3.select(this);
 6.11776 +            nv.utils.initSVG(container);
 6.11777 +
 6.11778 +            // Setup Scales
 6.11779 +            x   .domain(xDomain || d3.extent(data, getX ))
 6.11780 +                .range(xRange || [0, availableWidth]);
 6.11781 +
 6.11782 +            y   .domain(yDomain || d3.extent(data, getY ))
 6.11783 +                .range(yRange || [availableHeight, 0]);
 6.11784 +
 6.11785 +            // Setup containers and skeleton of chart
 6.11786 +            var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]);
 6.11787 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline');
 6.11788 +            var gEnter = wrapEnter.append('g');
 6.11789 +            var g = wrap.select('g');
 6.11790 +
 6.11791 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
 6.11792 +
 6.11793 +            var paths = wrap.selectAll('path')
 6.11794 +                .data(function(d) { return [d] });
 6.11795 +            paths.enter().append('path');
 6.11796 +            paths.exit().remove();
 6.11797 +            paths
 6.11798 +                .style('stroke', function(d,i) { return d.color || color(d, i) })
 6.11799 +                .attr('d', d3.svg.line()
 6.11800 +                    .x(function(d,i) { return x(getX(d,i)) })
 6.11801 +                    .y(function(d,i) { return y(getY(d,i)) })
 6.11802 +            );
 6.11803 +
 6.11804 +            // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
 6.11805 +            var points = wrap.selectAll('circle.nv-point')
 6.11806 +                .data(function(data) {
 6.11807 +                    var yValues = data.map(function(d, i) { return getY(d,i); });
 6.11808 +                    function pointIndex(index) {
 6.11809 +                        if (index != -1) {
 6.11810 +                            var result = data[index];
 6.11811 +                            result.pointIndex = index;
 6.11812 +                            return result;
 6.11813 +                        } else {
 6.11814 +                            return null;
 6.11815 +                        }
 6.11816 +                    }
 6.11817 +                    var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),
 6.11818 +                        minPoint = pointIndex(yValues.indexOf(y.domain()[0])),
 6.11819 +                        currentPoint = pointIndex(yValues.length - 1);
 6.11820 +                    return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});
 6.11821 +                });
 6.11822 +            points.enter().append('circle');
 6.11823 +            points.exit().remove();
 6.11824 +            points
 6.11825 +                .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })
 6.11826 +                .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })
 6.11827 +                .attr('r', 2)
 6.11828 +                .attr('class', function(d,i) {
 6.11829 +                    return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
 6.11830 +                            getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
 6.11831 +                });
 6.11832 +        });
 6.11833 +
 6.11834 +        return chart;
 6.11835 +    }
 6.11836 +
 6.11837 +    //============================================================
 6.11838 +    // Expose Public Variables
 6.11839 +    //------------------------------------------------------------
 6.11840 +
 6.11841 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.11842 +
 6.11843 +    chart._options = Object.create({}, {
 6.11844 +        // simple options, just get/set the necessary values
 6.11845 +        width:     {get: function(){return width;}, set: function(_){width=_;}},
 6.11846 +        height:    {get: function(){return height;}, set: function(_){height=_;}},
 6.11847 +        xDomain:   {get: function(){return xDomain;}, set: function(_){xDomain=_;}},
 6.11848 +        yDomain:   {get: function(){return yDomain;}, set: function(_){yDomain=_;}},
 6.11849 +        xRange:    {get: function(){return xRange;}, set: function(_){xRange=_;}},
 6.11850 +        yRange:    {get: function(){return yRange;}, set: function(_){yRange=_;}},
 6.11851 +        xScale:    {get: function(){return x;}, set: function(_){x=_;}},
 6.11852 +        yScale:    {get: function(){return y;}, set: function(_){y=_;}},
 6.11853 +        animate:   {get: function(){return animate;}, set: function(_){animate=_;}},
 6.11854 +
 6.11855 +        //functor options
 6.11856 +        x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}},
 6.11857 +        y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}},
 6.11858 +
 6.11859 +        // options that require extra logic in the setter
 6.11860 +        margin: {get: function(){return margin;}, set: function(_){
 6.11861 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.11862 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.11863 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.11864 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.11865 +        }},
 6.11866 +        color:  {get: function(){return color;}, set: function(_){
 6.11867 +            color = nv.utils.getColor(_);
 6.11868 +        }}
 6.11869 +    });
 6.11870 +
 6.11871 +    nv.utils.initOptions(chart);
 6.11872 +    return chart;
 6.11873 +};
 6.11874 +
 6.11875 +nv.models.sparklinePlus = function() {
 6.11876 +    "use strict";
 6.11877 +
 6.11878 +    //============================================================
 6.11879 +    // Public Variables with Default Settings
 6.11880 +    //------------------------------------------------------------
 6.11881 +
 6.11882 +    var sparkline = nv.models.sparkline();
 6.11883 +
 6.11884 +    var margin = {top: 15, right: 100, bottom: 10, left: 50}
 6.11885 +        , width = null
 6.11886 +        , height = null
 6.11887 +        , x
 6.11888 +        , y
 6.11889 +        , index = []
 6.11890 +        , paused = false
 6.11891 +        , xTickFormat = d3.format(',r')
 6.11892 +        , yTickFormat = d3.format(',.2f')
 6.11893 +        , showLastValue = true
 6.11894 +        , alignValue = true
 6.11895 +        , rightAlignValue = false
 6.11896 +        , noData = null
 6.11897 +        ;
 6.11898 +
 6.11899 +    function chart(selection) {
 6.11900 +        selection.each(function(data) {
 6.11901 +            var container = d3.select(this);
 6.11902 +            nv.utils.initSVG(container);
 6.11903 +
 6.11904 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.11905 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.11906 +
 6.11907 +            chart.update = function() { container.call(chart); };
 6.11908 +            chart.container = this;
 6.11909 +
 6.11910 +            // Display No Data message if there's nothing to show.
 6.11911 +            if (!data || !data.length) {
 6.11912 +                nv.utils.noData(chart, container)
 6.11913 +                return chart;
 6.11914 +            } else {
 6.11915 +                container.selectAll('.nv-noData').remove();
 6.11916 +            }
 6.11917 +
 6.11918 +            var currentValue = sparkline.y()(data[data.length-1], data.length-1);
 6.11919 +
 6.11920 +            // Setup Scales
 6.11921 +            x = sparkline.xScale();
 6.11922 +            y = sparkline.yScale();
 6.11923 +
 6.11924 +            // Setup containers and skeleton of chart
 6.11925 +            var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]);
 6.11926 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus');
 6.11927 +            var gEnter = wrapEnter.append('g');
 6.11928 +            var g = wrap.select('g');
 6.11929 +
 6.11930 +            gEnter.append('g').attr('class', 'nv-sparklineWrap');
 6.11931 +            gEnter.append('g').attr('class', 'nv-valueWrap');
 6.11932 +            gEnter.append('g').attr('class', 'nv-hoverArea');
 6.11933 +
 6.11934 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.11935 +
 6.11936 +            // Main Chart Component(s)
 6.11937 +            var sparklineWrap = g.select('.nv-sparklineWrap');
 6.11938 +
 6.11939 +            sparkline.width(availableWidth).height(availableHeight);
 6.11940 +            sparklineWrap.call(sparkline);
 6.11941 +
 6.11942 +            if (showLastValue) {
 6.11943 +                var valueWrap = g.select('.nv-valueWrap');
 6.11944 +                var value = valueWrap.selectAll('.nv-currentValue')
 6.11945 +                    .data([currentValue]);
 6.11946 +
 6.11947 +                value.enter().append('text').attr('class', 'nv-currentValue')
 6.11948 +                    .attr('dx', rightAlignValue ? -8 : 8)
 6.11949 +                    .attr('dy', '.9em')
 6.11950 +                    .style('text-anchor', rightAlignValue ? 'end' : 'start');
 6.11951 +
 6.11952 +                value
 6.11953 +                    .attr('x', availableWidth + (rightAlignValue ? margin.right : 0))
 6.11954 +                    .attr('y', alignValue ? function (d) {
 6.11955 +                        return y(d)
 6.11956 +                    } : 0)
 6.11957 +                    .style('fill', sparkline.color()(data[data.length - 1], data.length - 1))
 6.11958 +                    .text(yTickFormat(currentValue));
 6.11959 +            }
 6.11960 +
 6.11961 +            gEnter.select('.nv-hoverArea').append('rect')
 6.11962 +                .on('mousemove', sparklineHover)
 6.11963 +                .on('click', function() { paused = !paused })
 6.11964 +                .on('mouseout', function() { index = []; updateValueLine(); });
 6.11965 +
 6.11966 +            g.select('.nv-hoverArea rect')
 6.11967 +                .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })
 6.11968 +                .attr('width', availableWidth + margin.left + margin.right)
 6.11969 +                .attr('height', availableHeight + margin.top);
 6.11970 +
 6.11971 +            //index is currently global (within the chart), may or may not keep it that way
 6.11972 +            function updateValueLine() {
 6.11973 +                if (paused) return;
 6.11974 +
 6.11975 +                var hoverValue = g.selectAll('.nv-hoverValue').data(index);
 6.11976 +
 6.11977 +                var hoverEnter = hoverValue.enter()
 6.11978 +                    .append('g').attr('class', 'nv-hoverValue')
 6.11979 +                    .style('stroke-opacity', 0)
 6.11980 +                    .style('fill-opacity', 0);
 6.11981 +
 6.11982 +                hoverValue.exit()
 6.11983 +                    .transition().duration(250)
 6.11984 +                    .style('stroke-opacity', 0)
 6.11985 +                    .style('fill-opacity', 0)
 6.11986 +                    .remove();
 6.11987 +
 6.11988 +                hoverValue
 6.11989 +                    .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
 6.11990 +                    .transition().duration(250)
 6.11991 +                    .style('stroke-opacity', 1)
 6.11992 +                    .style('fill-opacity', 1);
 6.11993 +
 6.11994 +                if (!index.length) return;
 6.11995 +
 6.11996 +                hoverEnter.append('line')
 6.11997 +                    .attr('x1', 0)
 6.11998 +                    .attr('y1', -margin.top)
 6.11999 +                    .attr('x2', 0)
 6.12000 +                    .attr('y2', availableHeight);
 6.12001 +
 6.12002 +                hoverEnter.append('text').attr('class', 'nv-xValue')
 6.12003 +                    .attr('x', -6)
 6.12004 +                    .attr('y', -margin.top)
 6.12005 +                    .attr('text-anchor', 'end')
 6.12006 +                    .attr('dy', '.9em');
 6.12007 +
 6.12008 +                g.select('.nv-hoverValue .nv-xValue')
 6.12009 +                    .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));
 6.12010 +
 6.12011 +                hoverEnter.append('text').attr('class', 'nv-yValue')
 6.12012 +                    .attr('x', 6)
 6.12013 +                    .attr('y', -margin.top)
 6.12014 +                    .attr('text-anchor', 'start')
 6.12015 +                    .attr('dy', '.9em');
 6.12016 +
 6.12017 +                g.select('.nv-hoverValue .nv-yValue')
 6.12018 +                    .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));
 6.12019 +            }
 6.12020 +
 6.12021 +            function sparklineHover() {
 6.12022 +                if (paused) return;
 6.12023 +
 6.12024 +                var pos = d3.mouse(this)[0] - margin.left;
 6.12025 +
 6.12026 +                function getClosestIndex(data, x) {
 6.12027 +                    var distance = Math.abs(sparkline.x()(data[0], 0) - x);
 6.12028 +                    var closestIndex = 0;
 6.12029 +                    for (var i = 0; i < data.length; i++){
 6.12030 +                        if (Math.abs(sparkline.x()(data[i], i) - x) < distance) {
 6.12031 +                            distance = Math.abs(sparkline.x()(data[i], i) - x);
 6.12032 +                            closestIndex = i;
 6.12033 +                        }
 6.12034 +                    }
 6.12035 +                    return closestIndex;
 6.12036 +                }
 6.12037 +
 6.12038 +                index = [getClosestIndex(data, Math.round(x.invert(pos)))];
 6.12039 +                updateValueLine();
 6.12040 +            }
 6.12041 +
 6.12042 +        });
 6.12043 +
 6.12044 +        return chart;
 6.12045 +    }
 6.12046 +
 6.12047 +    //============================================================
 6.12048 +    // Expose Public Variables
 6.12049 +    //------------------------------------------------------------
 6.12050 +
 6.12051 +    // expose chart's sub-components
 6.12052 +    chart.sparkline = sparkline;
 6.12053 +
 6.12054 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.12055 +
 6.12056 +    chart._options = Object.create({}, {
 6.12057 +        // simple options, just get/set the necessary values
 6.12058 +        width:           {get: function(){return width;}, set: function(_){width=_;}},
 6.12059 +        height:          {get: function(){return height;}, set: function(_){height=_;}},
 6.12060 +        xTickFormat:     {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}},
 6.12061 +        yTickFormat:     {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}},
 6.12062 +        showLastValue:   {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}},
 6.12063 +        alignValue:      {get: function(){return alignValue;}, set: function(_){alignValue=_;}},
 6.12064 +        rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}},
 6.12065 +        noData:          {get: function(){return noData;}, set: function(_){noData=_;}},
 6.12066 +
 6.12067 +        // options that require extra logic in the setter
 6.12068 +        margin: {get: function(){return margin;}, set: function(_){
 6.12069 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.12070 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.12071 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.12072 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.12073 +        }}
 6.12074 +    });
 6.12075 +
 6.12076 +    nv.utils.inheritOptions(chart, sparkline);
 6.12077 +    nv.utils.initOptions(chart);
 6.12078 +
 6.12079 +    return chart;
 6.12080 +};
 6.12081 +
 6.12082 +nv.models.stackedArea = function() {
 6.12083 +    "use strict";
 6.12084 +
 6.12085 +    //============================================================
 6.12086 +    // Public Variables with Default Settings
 6.12087 +    //------------------------------------------------------------
 6.12088 +
 6.12089 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
 6.12090 +        , width = 960
 6.12091 +        , height = 500
 6.12092 +        , color = nv.utils.defaultColor() // a function that computes the color
 6.12093 +        , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one
 6.12094 +        , container = null
 6.12095 +        , getX = function(d) { return d.x } // accessor to get the x value from a data point
 6.12096 +        , getY = function(d) { return d.y } // accessor to get the y value from a data point
 6.12097 +        , style = 'stack'
 6.12098 +        , offset = 'zero'
 6.12099 +        , order = 'default'
 6.12100 +        , interpolate = 'linear'  // controls the line interpolation
 6.12101 +        , clipEdge = false // if true, masks lines within x and y scale
 6.12102 +        , x //can be accessed via chart.xScale()
 6.12103 +        , y //can be accessed via chart.yScale()
 6.12104 +        , scatter = nv.models.scatter()
 6.12105 +        , duration = 250
 6.12106 +        , dispatch =  d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout')
 6.12107 +        ;
 6.12108 +
 6.12109 +    scatter
 6.12110 +        .pointSize(2.2) // default size
 6.12111 +        .pointDomain([2.2, 2.2]) // all the same size by default
 6.12112 +    ;
 6.12113 +
 6.12114 +    /************************************
 6.12115 +     * offset:
 6.12116 +     *   'wiggle' (stream)
 6.12117 +     *   'zero' (stacked)
 6.12118 +     *   'expand' (normalize to 100%)
 6.12119 +     *   'silhouette' (simple centered)
 6.12120 +     *
 6.12121 +     * order:
 6.12122 +     *   'inside-out' (stream)
 6.12123 +     *   'default' (input order)
 6.12124 +     ************************************/
 6.12125 +
 6.12126 +    var renderWatch = nv.utils.renderWatch(dispatch, duration);
 6.12127 +
 6.12128 +    function chart(selection) {
 6.12129 +        renderWatch.reset();
 6.12130 +        renderWatch.models(scatter);
 6.12131 +        selection.each(function(data) {
 6.12132 +            var availableWidth = width - margin.left - margin.right,
 6.12133 +                availableHeight = height - margin.top - margin.bottom;
 6.12134 +
 6.12135 +            container = d3.select(this);
 6.12136 +            nv.utils.initSVG(container);
 6.12137 +
 6.12138 +            // Setup Scales
 6.12139 +            x = scatter.xScale();
 6.12140 +            y = scatter.yScale();
 6.12141 +
 6.12142 +            var dataRaw = data;
 6.12143 +            // Injecting point index into each point because d3.layout.stack().out does not give index
 6.12144 +            data.forEach(function(aseries, i) {
 6.12145 +                aseries.seriesIndex = i;
 6.12146 +                aseries.values = aseries.values.map(function(d, j) {
 6.12147 +                    d.index = j;
 6.12148 +                    d.seriesIndex = i;
 6.12149 +                    return d;
 6.12150 +                });
 6.12151 +            });
 6.12152 +
 6.12153 +            var dataFiltered = data.filter(function(series) {
 6.12154 +                return !series.disabled;
 6.12155 +            });
 6.12156 +
 6.12157 +            data = d3.layout.stack()
 6.12158 +                .order(order)
 6.12159 +                .offset(offset)
 6.12160 +                .values(function(d) { return d.values })  //TODO: make values customizeable in EVERY model in this fashion
 6.12161 +                .x(getX)
 6.12162 +                .y(getY)
 6.12163 +                .out(function(d, y0, y) {
 6.12164 +                    d.display = {
 6.12165 +                        y: y,
 6.12166 +                        y0: y0
 6.12167 +                    };
 6.12168 +                })
 6.12169 +            (dataFiltered);
 6.12170 +
 6.12171 +            // Setup containers and skeleton of chart
 6.12172 +            var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);
 6.12173 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');
 6.12174 +            var defsEnter = wrapEnter.append('defs');
 6.12175 +            var gEnter = wrapEnter.append('g');
 6.12176 +            var g = wrap.select('g');
 6.12177 +
 6.12178 +            gEnter.append('g').attr('class', 'nv-areaWrap');
 6.12179 +            gEnter.append('g').attr('class', 'nv-scatterWrap');
 6.12180 +
 6.12181 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.12182 +            
 6.12183 +            // If the user has not specified forceY, make sure 0 is included in the domain
 6.12184 +            // Otherwise, use user-specified values for forceY
 6.12185 +            if (scatter.forceY().length == 0) {
 6.12186 +                scatter.forceY().push(0);
 6.12187 +            }
 6.12188 +            
 6.12189 +            scatter
 6.12190 +                .width(availableWidth)
 6.12191 +                .height(availableHeight)
 6.12192 +                .x(getX)
 6.12193 +                .y(function(d) { return d.display.y + d.display.y0 })
 6.12194 +                .forceY([0])
 6.12195 +                .color(data.map(function(d,i) {
 6.12196 +                    return d.color || color(d, d.seriesIndex);
 6.12197 +                }));
 6.12198 +
 6.12199 +            var scatterWrap = g.select('.nv-scatterWrap')
 6.12200 +                .datum(data);
 6.12201 +
 6.12202 +            scatterWrap.call(scatter);
 6.12203 +
 6.12204 +            defsEnter.append('clipPath')
 6.12205 +                .attr('id', 'nv-edge-clip-' + id)
 6.12206 +                .append('rect');
 6.12207 +
 6.12208 +            wrap.select('#nv-edge-clip-' + id + ' rect')
 6.12209 +                .attr('width', availableWidth)
 6.12210 +                .attr('height', availableHeight);
 6.12211 +
 6.12212 +            g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
 6.12213 +
 6.12214 +            var area = d3.svg.area()
 6.12215 +                .x(function(d,i)  { return x(getX(d,i)) })
 6.12216 +                .y0(function(d) {
 6.12217 +                    return y(d.display.y0)
 6.12218 +                })
 6.12219 +                .y1(function(d) {
 6.12220 +                    return y(d.display.y + d.display.y0)
 6.12221 +                })
 6.12222 +                .interpolate(interpolate);
 6.12223 +
 6.12224 +            var zeroArea = d3.svg.area()
 6.12225 +                .x(function(d,i)  { return x(getX(d,i)) })
 6.12226 +                .y0(function(d) { return y(d.display.y0) })
 6.12227 +                .y1(function(d) { return y(d.display.y0) });
 6.12228 +
 6.12229 +            var path = g.select('.nv-areaWrap').selectAll('path.nv-area')
 6.12230 +                .data(function(d) { return d });
 6.12231 +
 6.12232 +            path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })
 6.12233 +                .attr('d', function(d,i){
 6.12234 +                    return zeroArea(d.values, d.seriesIndex);
 6.12235 +                })
 6.12236 +                .on('mouseover', function(d,i) {
 6.12237 +                    d3.select(this).classed('hover', true);
 6.12238 +                    dispatch.areaMouseover({
 6.12239 +                        point: d,
 6.12240 +                        series: d.key,
 6.12241 +                        pos: [d3.event.pageX, d3.event.pageY],
 6.12242 +                        seriesIndex: d.seriesIndex
 6.12243 +                    });
 6.12244 +                })
 6.12245 +                .on('mouseout', function(d,i) {
 6.12246 +                    d3.select(this).classed('hover', false);
 6.12247 +                    dispatch.areaMouseout({
 6.12248 +                        point: d,
 6.12249 +                        series: d.key,
 6.12250 +                        pos: [d3.event.pageX, d3.event.pageY],
 6.12251 +                        seriesIndex: d.seriesIndex
 6.12252 +                    });
 6.12253 +                })
 6.12254 +                .on('click', function(d,i) {
 6.12255 +                    d3.select(this).classed('hover', false);
 6.12256 +                    dispatch.areaClick({
 6.12257 +                        point: d,
 6.12258 +                        series: d.key,
 6.12259 +                        pos: [d3.event.pageX, d3.event.pageY],
 6.12260 +                        seriesIndex: d.seriesIndex
 6.12261 +                    });
 6.12262 +                });
 6.12263 +
 6.12264 +            path.exit().remove();
 6.12265 +            path.style('fill', function(d,i){
 6.12266 +                    return d.color || color(d, d.seriesIndex)
 6.12267 +                })
 6.12268 +                .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });
 6.12269 +            path.watchTransition(renderWatch,'stackedArea path')
 6.12270 +                .attr('d', function(d,i) {
 6.12271 +                    return area(d.values,i)
 6.12272 +                });
 6.12273 +
 6.12274 +            //============================================================
 6.12275 +            // Event Handling/Dispatching (in chart's scope)
 6.12276 +            //------------------------------------------------------------
 6.12277 +
 6.12278 +            scatter.dispatch.on('elementMouseover.area', function(e) {
 6.12279 +                g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);
 6.12280 +            });
 6.12281 +            scatter.dispatch.on('elementMouseout.area', function(e) {
 6.12282 +                g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);
 6.12283 +            });
 6.12284 +
 6.12285 +            //Special offset functions
 6.12286 +            chart.d3_stackedOffset_stackPercent = function(stackData) {
 6.12287 +                var n = stackData.length,    //How many series
 6.12288 +                    m = stackData[0].length,     //how many points per series
 6.12289 +                    i,
 6.12290 +                    j,
 6.12291 +                    o,
 6.12292 +                    y0 = [];
 6.12293 +
 6.12294 +                for (j = 0; j < m; ++j) { //Looping through all points
 6.12295 +                    for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series
 6.12296 +                        o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time.
 6.12297 +                    }
 6.12298 +
 6.12299 +                    if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0
 6.12300 +                        stackData[i][j][1] /= o;
 6.12301 +                    } else { //(total y value of all series at point in time i) == 0
 6.12302 +                        for (i = 0; i < n; i++) {
 6.12303 +                            stackData[i][j][1] = 0;
 6.12304 +                        }
 6.12305 +                    }
 6.12306 +                }
 6.12307 +                for (j = 0; j < m; ++j) y0[j] = 0;
 6.12308 +                return y0;
 6.12309 +            };
 6.12310 +
 6.12311 +        });
 6.12312 +
 6.12313 +        renderWatch.renderEnd('stackedArea immediate');
 6.12314 +        return chart;
 6.12315 +    }
 6.12316 +
 6.12317 +    //============================================================
 6.12318 +    // Global getters and setters
 6.12319 +    //------------------------------------------------------------
 6.12320 +
 6.12321 +    chart.dispatch = dispatch;
 6.12322 +    chart.scatter = scatter;
 6.12323 +
 6.12324 +    scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });
 6.12325 +    scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });
 6.12326 +    scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });
 6.12327 +
 6.12328 +    chart.interpolate = function(_) {
 6.12329 +        if (!arguments.length) return interpolate;
 6.12330 +        interpolate = _;
 6.12331 +        return chart;
 6.12332 +    };
 6.12333 +
 6.12334 +    chart.duration = function(_) {
 6.12335 +        if (!arguments.length) return duration;
 6.12336 +        duration = _;
 6.12337 +        renderWatch.reset(duration);
 6.12338 +        scatter.duration(duration);
 6.12339 +        return chart;
 6.12340 +    };
 6.12341 +
 6.12342 +    chart.dispatch = dispatch;
 6.12343 +    chart.scatter = scatter;
 6.12344 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.12345 +
 6.12346 +    chart._options = Object.create({}, {
 6.12347 +        // simple options, just get/set the necessary values
 6.12348 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
 6.12349 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
 6.12350 +        clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
 6.12351 +        offset:      {get: function(){return offset;}, set: function(_){offset=_;}},
 6.12352 +        order:    {get: function(){return order;}, set: function(_){order=_;}},
 6.12353 +        interpolate:    {get: function(){return interpolate;}, set: function(_){interpolate=_;}},
 6.12354 +
 6.12355 +        // simple functor options
 6.12356 +        x:     {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},
 6.12357 +        y:     {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},
 6.12358 +
 6.12359 +        // options that require extra logic in the setter
 6.12360 +        margin: {get: function(){return margin;}, set: function(_){
 6.12361 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.12362 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.12363 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.12364 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.12365 +        }},
 6.12366 +        color:  {get: function(){return color;}, set: function(_){
 6.12367 +            color = nv.utils.getColor(_);
 6.12368 +        }},
 6.12369 +        style: {get: function(){return style;}, set: function(_){
 6.12370 +            style = _;
 6.12371 +            switch (style) {
 6.12372 +                case 'stack':
 6.12373 +                    chart.offset('zero');
 6.12374 +                    chart.order('default');
 6.12375 +                    break;
 6.12376 +                case 'stream':
 6.12377 +                    chart.offset('wiggle');
 6.12378 +                    chart.order('inside-out');
 6.12379 +                    break;
 6.12380 +                case 'stream-center':
 6.12381 +                    chart.offset('silhouette');
 6.12382 +                    chart.order('inside-out');
 6.12383 +                    break;
 6.12384 +                case 'expand':
 6.12385 +                    chart.offset('expand');
 6.12386 +                    chart.order('default');
 6.12387 +                    break;
 6.12388 +                case 'stack_percent':
 6.12389 +                    chart.offset(chart.d3_stackedOffset_stackPercent);
 6.12390 +                    chart.order('default');
 6.12391 +                    break;
 6.12392 +            }
 6.12393 +        }},
 6.12394 +        duration: {get: function(){return duration;}, set: function(_){
 6.12395 +            duration = _;
 6.12396 +            renderWatch.reset(duration);
 6.12397 +            scatter.duration(duration);
 6.12398 +        }}
 6.12399 +    });
 6.12400 +
 6.12401 +    nv.utils.inheritOptions(chart, scatter);
 6.12402 +    nv.utils.initOptions(chart);
 6.12403 +
 6.12404 +    return chart;
 6.12405 +};
 6.12406 +
 6.12407 +nv.models.stackedAreaChart = function() {
 6.12408 +    "use strict";
 6.12409 +
 6.12410 +    //============================================================
 6.12411 +    // Public Variables with Default Settings
 6.12412 +    //------------------------------------------------------------
 6.12413 +
 6.12414 +    var stacked = nv.models.stackedArea()
 6.12415 +        , xAxis = nv.models.axis()
 6.12416 +        , yAxis = nv.models.axis()
 6.12417 +        , legend = nv.models.legend()
 6.12418 +        , controls = nv.models.legend()
 6.12419 +        , interactiveLayer = nv.interactiveGuideline()
 6.12420 +        , tooltip = nv.models.tooltip()
 6.12421 +        ;
 6.12422 +
 6.12423 +    var margin = {top: 30, right: 25, bottom: 50, left: 60}
 6.12424 +        , width = null
 6.12425 +        , height = null
 6.12426 +        , color = nv.utils.defaultColor()
 6.12427 +        , showControls = true
 6.12428 +        , showLegend = true
 6.12429 +        , showXAxis = true
 6.12430 +        , showYAxis = true
 6.12431 +        , rightAlignYAxis = false
 6.12432 +        , useInteractiveGuideline = false
 6.12433 +        , x //can be accessed via chart.xScale()
 6.12434 +        , y //can be accessed via chart.yScale()
 6.12435 +        , state = nv.utils.state()
 6.12436 +        , defaultState = null
 6.12437 +        , noData = null
 6.12438 +        , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')
 6.12439 +        , controlWidth = 250
 6.12440 +        , controlOptions = ['Stacked','Stream','Expanded']
 6.12441 +        , controlLabels = {}
 6.12442 +        , duration = 250
 6.12443 +        ;
 6.12444 +
 6.12445 +    state.style = stacked.style();
 6.12446 +    xAxis.orient('bottom').tickPadding(7);
 6.12447 +    yAxis.orient((rightAlignYAxis) ? 'right' : 'left');
 6.12448 +
 6.12449 +    tooltip
 6.12450 +        .headerFormatter(function(d, i) {
 6.12451 +            return xAxis.tickFormat()(d, i);
 6.12452 +        })
 6.12453 +        .valueFormatter(function(d, i) {
 6.12454 +            return yAxis.tickFormat()(d, i);
 6.12455 +        });
 6.12456 +
 6.12457 +    interactiveLayer.tooltip
 6.12458 +        .headerFormatter(function(d, i) {
 6.12459 +            return xAxis.tickFormat()(d, i);
 6.12460 +        })
 6.12461 +        .valueFormatter(function(d, i) {
 6.12462 +            return yAxis.tickFormat()(d, i);
 6.12463 +        });
 6.12464 +
 6.12465 +    var oldYTickFormat = null,
 6.12466 +        oldValueFormatter = null;
 6.12467 +
 6.12468 +    controls.updateState(false);
 6.12469 +
 6.12470 +    //============================================================
 6.12471 +    // Private Variables
 6.12472 +    //------------------------------------------------------------
 6.12473 +
 6.12474 +    var renderWatch = nv.utils.renderWatch(dispatch);
 6.12475 +    var style = stacked.style();
 6.12476 +
 6.12477 +    var stateGetter = function(data) {
 6.12478 +        return function(){
 6.12479 +            return {
 6.12480 +                active: data.map(function(d) { return !d.disabled }),
 6.12481 +                style: stacked.style()
 6.12482 +            };
 6.12483 +        }
 6.12484 +    };
 6.12485 +
 6.12486 +    var stateSetter = function(data) {
 6.12487 +        return function(state) {
 6.12488 +            if (state.style !== undefined)
 6.12489 +                style = state.style;
 6.12490 +            if (state.active !== undefined)
 6.12491 +                data.forEach(function(series,i) {
 6.12492 +                    series.disabled = !state.active[i];
 6.12493 +                });
 6.12494 +        }
 6.12495 +    };
 6.12496 +
 6.12497 +    var percentFormatter = d3.format('%');
 6.12498 +
 6.12499 +    function chart(selection) {
 6.12500 +        renderWatch.reset();
 6.12501 +        renderWatch.models(stacked);
 6.12502 +        if (showXAxis) renderWatch.models(xAxis);
 6.12503 +        if (showYAxis) renderWatch.models(yAxis);
 6.12504 +
 6.12505 +        selection.each(function(data) {
 6.12506 +            var container = d3.select(this),
 6.12507 +                that = this;
 6.12508 +            nv.utils.initSVG(container);
 6.12509 +
 6.12510 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.12511 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.12512 +
 6.12513 +            chart.update = function() { container.transition().duration(duration).call(chart); };
 6.12514 +            chart.container = this;
 6.12515 +
 6.12516 +            state
 6.12517 +                .setter(stateSetter(data), chart.update)
 6.12518 +                .getter(stateGetter(data))
 6.12519 +                .update();
 6.12520 +
 6.12521 +            // DEPRECATED set state.disabled
 6.12522 +            state.disabled = data.map(function(d) { return !!d.disabled });
 6.12523 +
 6.12524 +            if (!defaultState) {
 6.12525 +                var key;
 6.12526 +                defaultState = {};
 6.12527 +                for (key in state) {
 6.12528 +                    if (state[key] instanceof Array)
 6.12529 +                        defaultState[key] = state[key].slice(0);
 6.12530 +                    else
 6.12531 +                        defaultState[key] = state[key];
 6.12532 +                }
 6.12533 +            }
 6.12534 +
 6.12535 +            // Display No Data message if there's nothing to show.
 6.12536 +            if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
 6.12537 +                nv.utils.noData(chart, container)
 6.12538 +                return chart;
 6.12539 +            } else {
 6.12540 +                container.selectAll('.nv-noData').remove();
 6.12541 +            }
 6.12542 +
 6.12543 +            // Setup Scales
 6.12544 +            x = stacked.xScale();
 6.12545 +            y = stacked.yScale();
 6.12546 +
 6.12547 +            // Setup containers and skeleton of chart
 6.12548 +            var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);
 6.12549 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');
 6.12550 +            var g = wrap.select('g');
 6.12551 +
 6.12552 +            gEnter.append("rect").style("opacity",0);
 6.12553 +            gEnter.append('g').attr('class', 'nv-x nv-axis');
 6.12554 +            gEnter.append('g').attr('class', 'nv-y nv-axis');
 6.12555 +            gEnter.append('g').attr('class', 'nv-stackedWrap');
 6.12556 +            gEnter.append('g').attr('class', 'nv-legendWrap');
 6.12557 +            gEnter.append('g').attr('class', 'nv-controlsWrap');
 6.12558 +            gEnter.append('g').attr('class', 'nv-interactive');
 6.12559 +
 6.12560 +            g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
 6.12561 +
 6.12562 +            // Legend
 6.12563 +            if (showLegend) {
 6.12564 +                var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth;
 6.12565 +
 6.12566 +                legend.width(legendWidth);
 6.12567 +                g.select('.nv-legendWrap').datum(data).call(legend);
 6.12568 +
 6.12569 +                if ( margin.top != legend.height()) {
 6.12570 +                    margin.top = legend.height();
 6.12571 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
 6.12572 +                }
 6.12573 +
 6.12574 +                g.select('.nv-legendWrap')
 6.12575 +                    .attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');
 6.12576 +            }
 6.12577 +
 6.12578 +            // Controls
 6.12579 +            if (showControls) {
 6.12580 +                var controlsData = [
 6.12581 +                    {
 6.12582 +                        key: controlLabels.stacked || 'Stacked',
 6.12583 +                        metaKey: 'Stacked',
 6.12584 +                        disabled: stacked.style() != 'stack',
 6.12585 +                        style: 'stack'
 6.12586 +                    },
 6.12587 +                    {
 6.12588 +                        key: controlLabels.stream || 'Stream',
 6.12589 +                        metaKey: 'Stream',
 6.12590 +                        disabled: stacked.style() != 'stream',
 6.12591 +                        style: 'stream'
 6.12592 +                    },
 6.12593 +                    {
 6.12594 +                        key: controlLabels.expanded || 'Expanded',
 6.12595 +                        metaKey: 'Expanded',
 6.12596 +                        disabled: stacked.style() != 'expand',
 6.12597 +                        style: 'expand'
 6.12598 +                    },
 6.12599 +                    {
 6.12600 +                        key: controlLabels.stack_percent || 'Stack %',
 6.12601 +                        metaKey: 'Stack_Percent',
 6.12602 +                        disabled: stacked.style() != 'stack_percent',
 6.12603 +                        style: 'stack_percent'
 6.12604 +                    }
 6.12605 +                ];
 6.12606 +
 6.12607 +                controlWidth = (controlOptions.length/3) * 260;
 6.12608 +                controlsData = controlsData.filter(function(d) {
 6.12609 +                    return controlOptions.indexOf(d.metaKey) !== -1;
 6.12610 +                });
 6.12611 +
 6.12612 +                controls
 6.12613 +                    .width( controlWidth )
 6.12614 +                    .color(['#444', '#444', '#444']);
 6.12615 +
 6.12616 +                g.select('.nv-controlsWrap')
 6.12617 +                    .datum(controlsData)
 6.12618 +                    .call(controls);
 6.12619 +
 6.12620 +                if ( margin.top != Math.max(controls.height(), legend.height()) ) {
 6.12621 +                    margin.top = Math.max(controls.height(), legend.height());
 6.12622 +                    availableHeight = nv.utils.availableHeight(height, container, margin);
 6.12623 +                }
 6.12624 +
 6.12625 +                g.select('.nv-controlsWrap')
 6.12626 +                    .attr('transform', 'translate(0,' + (-margin.top) +')');
 6.12627 +            }
 6.12628 +
 6.12629 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.12630 +
 6.12631 +            if (rightAlignYAxis) {
 6.12632 +                g.select(".nv-y.nv-axis")
 6.12633 +                    .attr("transform", "translate(" + availableWidth + ",0)");
 6.12634 +            }
 6.12635 +
 6.12636 +            //Set up interactive layer
 6.12637 +            if (useInteractiveGuideline) {
 6.12638 +                interactiveLayer
 6.12639 +                    .width(availableWidth)
 6.12640 +                    .height(availableHeight)
 6.12641 +                    .margin({left: margin.left, top: margin.top})
 6.12642 +                    .svgContainer(container)
 6.12643 +                    .xScale(x);
 6.12644 +                wrap.select(".nv-interactive").call(interactiveLayer);
 6.12645 +            }
 6.12646 +
 6.12647 +            stacked
 6.12648 +                .width(availableWidth)
 6.12649 +                .height(availableHeight);
 6.12650 +
 6.12651 +            var stackedWrap = g.select('.nv-stackedWrap')
 6.12652 +                .datum(data);
 6.12653 +
 6.12654 +            stackedWrap.transition().call(stacked);
 6.12655 +
 6.12656 +            // Setup Axes
 6.12657 +            if (showXAxis) {
 6.12658 +                xAxis.scale(x)
 6.12659 +                    ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
 6.12660 +                    .tickSize( -availableHeight, 0);
 6.12661 +
 6.12662 +                g.select('.nv-x.nv-axis')
 6.12663 +                    .attr('transform', 'translate(0,' + availableHeight + ')');
 6.12664 +
 6.12665 +                g.select('.nv-x.nv-axis')
 6.12666 +                    .transition().duration(0)
 6.12667 +                    .call(xAxis);
 6.12668 +            }
 6.12669 +
 6.12670 +            if (showYAxis) {
 6.12671 +                var ticks;
 6.12672 +                if (stacked.offset() === 'wiggle') {
 6.12673 +                    ticks = 0;
 6.12674 +                }
 6.12675 +                else {
 6.12676 +                    ticks = nv.utils.calcTicksY(availableHeight/36, data);
 6.12677 +                }
 6.12678 +                yAxis.scale(y)
 6.12679 +                    ._ticks(ticks)
 6.12680 +                    .tickSize(-availableWidth, 0);
 6.12681 +
 6.12682 +                    if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
 6.12683 +                        var currentFormat = yAxis.tickFormat();
 6.12684 +
 6.12685 +                        if ( !oldYTickFormat || currentFormat !== percentFormatter )
 6.12686 +                            oldYTickFormat = currentFormat;
 6.12687 +
 6.12688 +                        //Forces the yAxis to use percentage in 'expand' mode.
 6.12689 +                        yAxis.tickFormat(percentFormatter);
 6.12690 +                    }
 6.12691 +                    else {
 6.12692 +                        if (oldYTickFormat) {
 6.12693 +                            yAxis.tickFormat(oldYTickFormat);
 6.12694 +                            oldYTickFormat = null;
 6.12695 +                        }
 6.12696 +                    }
 6.12697 +
 6.12698 +                g.select('.nv-y.nv-axis')
 6.12699 +                    .transition().duration(0)
 6.12700 +                    .call(yAxis);
 6.12701 +            }
 6.12702 +
 6.12703 +            //============================================================
 6.12704 +            // Event Handling/Dispatching (in chart's scope)
 6.12705 +            //------------------------------------------------------------
 6.12706 +
 6.12707 +            stacked.dispatch.on('areaClick.toggle', function(e) {
 6.12708 +                if (data.filter(function(d) { return !d.disabled }).length === 1)
 6.12709 +                    data.forEach(function(d) {
 6.12710 +                        d.disabled = false;
 6.12711 +                    });
 6.12712 +                else
 6.12713 +                    data.forEach(function(d,i) {
 6.12714 +                        d.disabled = (i != e.seriesIndex);
 6.12715 +                    });
 6.12716 +
 6.12717 +                state.disabled = data.map(function(d) { return !!d.disabled });
 6.12718 +                dispatch.stateChange(state);
 6.12719 +
 6.12720 +                chart.update();
 6.12721 +            });
 6.12722 +
 6.12723 +            legend.dispatch.on('stateChange', function(newState) {
 6.12724 +                for (var key in newState)
 6.12725 +                    state[key] = newState[key];
 6.12726 +                dispatch.stateChange(state);
 6.12727 +                chart.update();
 6.12728 +            });
 6.12729 +
 6.12730 +            controls.dispatch.on('legendClick', function(d,i) {
 6.12731 +                if (!d.disabled) return;
 6.12732 +
 6.12733 +                controlsData = controlsData.map(function(s) {
 6.12734 +                    s.disabled = true;
 6.12735 +                    return s;
 6.12736 +                });
 6.12737 +                d.disabled = false;
 6.12738 +
 6.12739 +                stacked.style(d.style);
 6.12740 +
 6.12741 +
 6.12742 +                state.style = stacked.style();
 6.12743 +                dispatch.stateChange(state);
 6.12744 +
 6.12745 +                chart.update();
 6.12746 +            });
 6.12747 +
 6.12748 +            interactiveLayer.dispatch.on('elementMousemove', function(e) {
 6.12749 +                stacked.clearHighlights();
 6.12750 +                var singlePoint, pointIndex, pointXLocation, allData = [];
 6.12751 +                data
 6.12752 +                    .filter(function(series, i) {
 6.12753 +                        series.seriesIndex = i;
 6.12754 +                        return !series.disabled;
 6.12755 +                    })
 6.12756 +                    .forEach(function(series,i) {
 6.12757 +                        pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
 6.12758 +                        var point = series.values[pointIndex];
 6.12759 +                        var pointYValue = chart.y()(point, pointIndex);
 6.12760 +                        if (pointYValue != null) {
 6.12761 +                            stacked.highlightPoint(i, pointIndex, true);
 6.12762 +                        }
 6.12763 +                        if (typeof point === 'undefined') return;
 6.12764 +                        if (typeof singlePoint === 'undefined') singlePoint = point;
 6.12765 +                        if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));
 6.12766 +
 6.12767 +                        //If we are in 'expand' mode, use the stacked percent value instead of raw value.
 6.12768 +                        var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex);
 6.12769 +                        allData.push({
 6.12770 +                            key: series.key,
 6.12771 +                            value: tooltipValue,
 6.12772 +                            color: color(series,series.seriesIndex),
 6.12773 +                            stackedValue: point.display
 6.12774 +                        });
 6.12775 +                    });
 6.12776 +
 6.12777 +                allData.reverse();
 6.12778 +
 6.12779 +                //Highlight the tooltip entry based on which stack the mouse is closest to.
 6.12780 +                if (allData.length > 2) {
 6.12781 +                    var yValue = chart.yScale().invert(e.mouseY);
 6.12782 +                    var yDistMax = Infinity, indexToHighlight = null;
 6.12783 +                    allData.forEach(function(series,i) {
 6.12784 +
 6.12785 +                        //To handle situation where the stacked area chart is negative, we need to use absolute values
 6.12786 +                        //when checking if the mouse Y value is within the stack area.
 6.12787 +                        yValue = Math.abs(yValue);
 6.12788 +                        var stackedY0 = Math.abs(series.stackedValue.y0);
 6.12789 +                        var stackedY = Math.abs(series.stackedValue.y);
 6.12790 +                        if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0))
 6.12791 +                        {
 6.12792 +                            indexToHighlight = i;
 6.12793 +                            return;
 6.12794 +                        }
 6.12795 +                    });
 6.12796 +                    if (indexToHighlight != null)
 6.12797 +                        allData[indexToHighlight].highlight = true;
 6.12798 +                }
 6.12799 +
 6.12800 +                var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
 6.12801 +
 6.12802 +                var valueFormatter = interactiveLayer.tooltip.valueFormatter();
 6.12803 +                // Keeps track of the tooltip valueFormatter if the chart changes to expanded view
 6.12804 +                if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
 6.12805 +                    if ( !oldValueFormatter ) {
 6.12806 +                        oldValueFormatter = valueFormatter;
 6.12807 +                    }
 6.12808 +                    //Forces the tooltip to use percentage in 'expand' mode.
 6.12809 +                    valueFormatter = d3.format(".1%");
 6.12810 +                }
 6.12811 +                else {
 6.12812 +                    if (oldValueFormatter) {
 6.12813 +                        valueFormatter = oldValueFormatter;
 6.12814 +                        oldValueFormatter = null;
 6.12815 +                    }
 6.12816 +                }
 6.12817 +
 6.12818 +                interactiveLayer.tooltip
 6.12819 +                    .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
 6.12820 +                    .chartContainer(that.parentNode)
 6.12821 +                    .valueFormatter(valueFormatter)
 6.12822 +                    .data(
 6.12823 +                    {
 6.12824 +                        value: xValue,
 6.12825 +                        series: allData
 6.12826 +                    }
 6.12827 +                )();
 6.12828 +
 6.12829 +                interactiveLayer.renderGuideLine(pointXLocation);
 6.12830 +
 6.12831 +            });
 6.12832 +
 6.12833 +            interactiveLayer.dispatch.on("elementMouseout",function(e) {
 6.12834 +                stacked.clearHighlights();
 6.12835 +            });
 6.12836 +
 6.12837 +            // Update chart from a state object passed to event handler
 6.12838 +            dispatch.on('changeState', function(e) {
 6.12839 +
 6.12840 +                if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {
 6.12841 +                    data.forEach(function(series,i) {
 6.12842 +                        series.disabled = e.disabled[i];
 6.12843 +                    });
 6.12844 +
 6.12845 +                    state.disabled = e.disabled;
 6.12846 +                }
 6.12847 +
 6.12848 +                if (typeof e.style !== 'undefined') {
 6.12849 +                    stacked.style(e.style);
 6.12850 +                    style = e.style;
 6.12851 +                }
 6.12852 +
 6.12853 +                chart.update();
 6.12854 +            });
 6.12855 +
 6.12856 +        });
 6.12857 +
 6.12858 +        renderWatch.renderEnd('stacked Area chart immediate');
 6.12859 +        return chart;
 6.12860 +    }
 6.12861 +
 6.12862 +    //============================================================
 6.12863 +    // Event Handling/Dispatching (out of chart's scope)
 6.12864 +    //------------------------------------------------------------
 6.12865 +
 6.12866 +    stacked.dispatch.on('elementMouseover.tooltip', function(evt) {
 6.12867 +        evt.point['x'] = stacked.x()(evt.point);
 6.12868 +        evt.point['y'] = stacked.y()(evt.point);
 6.12869 +        tooltip.data(evt).position(evt.pos).hidden(false);
 6.12870 +    });
 6.12871 +
 6.12872 +    stacked.dispatch.on('elementMouseout.tooltip', function(evt) {
 6.12873 +        tooltip.hidden(true)
 6.12874 +    });
 6.12875 +
 6.12876 +    //============================================================
 6.12877 +    // Expose Public Variables
 6.12878 +    //------------------------------------------------------------
 6.12879 +
 6.12880 +    // expose chart's sub-components
 6.12881 +    chart.dispatch = dispatch;
 6.12882 +    chart.stacked = stacked;
 6.12883 +    chart.legend = legend;
 6.12884 +    chart.controls = controls;
 6.12885 +    chart.xAxis = xAxis;
 6.12886 +    chart.yAxis = yAxis;
 6.12887 +    chart.interactiveLayer = interactiveLayer;
 6.12888 +    chart.tooltip = tooltip;
 6.12889 +
 6.12890 +    chart.dispatch = dispatch;
 6.12891 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.12892 +
 6.12893 +    chart._options = Object.create({}, {
 6.12894 +        // simple options, just get/set the necessary values
 6.12895 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
 6.12896 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
 6.12897 +        showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
 6.12898 +        showXAxis:      {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
 6.12899 +        showYAxis:    {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
 6.12900 +        defaultState:    {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
 6.12901 +        noData:    {get: function(){return noData;}, set: function(_){noData=_;}},
 6.12902 +        showControls:    {get: function(){return showControls;}, set: function(_){showControls=_;}},
 6.12903 +        controlLabels:    {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
 6.12904 +        controlOptions:    {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}},
 6.12905 +
 6.12906 +        // deprecated options
 6.12907 +        tooltips:    {get: function(){return tooltip.enabled();}, set: function(_){
 6.12908 +            // deprecated after 1.7.1
 6.12909 +            nv.deprecated('tooltips', 'use chart.tooltip.enabled() instead');
 6.12910 +            tooltip.enabled(!!_);
 6.12911 +        }},
 6.12912 +        tooltipContent:    {get: function(){return tooltip.contentGenerator();}, set: function(_){
 6.12913 +            // deprecated after 1.7.1
 6.12914 +            nv.deprecated('tooltipContent', 'use chart.tooltip.contentGenerator() instead');
 6.12915 +            tooltip.contentGenerator(_);
 6.12916 +        }},
 6.12917 +
 6.12918 +        // options that require extra logic in the setter
 6.12919 +        margin: {get: function(){return margin;}, set: function(_){
 6.12920 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.12921 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.12922 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.12923 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.12924 +        }},
 6.12925 +        duration: {get: function(){return duration;}, set: function(_){
 6.12926 +            duration = _;
 6.12927 +            renderWatch.reset(duration);
 6.12928 +            stacked.duration(duration);
 6.12929 +            xAxis.duration(duration);
 6.12930 +            yAxis.duration(duration);
 6.12931 +        }},
 6.12932 +        color:  {get: function(){return color;}, set: function(_){
 6.12933 +            color = nv.utils.getColor(_);
 6.12934 +            legend.color(color);
 6.12935 +            stacked.color(color);
 6.12936 +        }},
 6.12937 +        rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
 6.12938 +            rightAlignYAxis = _;
 6.12939 +            yAxis.orient( rightAlignYAxis ? 'right' : 'left');
 6.12940 +        }},
 6.12941 +        useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
 6.12942 +            useInteractiveGuideline = !!_;
 6.12943 +            chart.interactive(!_);
 6.12944 +            chart.useVoronoi(!_);
 6.12945 +            stacked.scatter.interactive(!_);
 6.12946 +        }}
 6.12947 +    });
 6.12948 +
 6.12949 +    nv.utils.inheritOptions(chart, stacked);
 6.12950 +    nv.utils.initOptions(chart);
 6.12951 +
 6.12952 +    return chart;
 6.12953 +};
 6.12954 +// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad
 6.12955 +nv.models.sunburst = function() {
 6.12956 +    "use strict";
 6.12957 +
 6.12958 +    //============================================================
 6.12959 +    // Public Variables with Default Settings
 6.12960 +    //------------------------------------------------------------
 6.12961 +
 6.12962 +    var margin = {top: 0, right: 0, bottom: 0, left: 0}
 6.12963 +        , width = null
 6.12964 +        , height = null
 6.12965 +        , mode = "count"
 6.12966 +        , modes = {count: function(d) { return 1; }, size: function(d) { return d.size }}
 6.12967 +        , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
 6.12968 +        , container = null
 6.12969 +        , color = nv.utils.defaultColor()
 6.12970 +        , duration = 500
 6.12971 +        , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd')
 6.12972 +        ;
 6.12973 +
 6.12974 +    var x = d3.scale.linear().range([0, 2 * Math.PI]);
 6.12975 +    var y = d3.scale.sqrt();
 6.12976 +
 6.12977 +    var partition = d3.layout.partition()
 6.12978 +        .sort(null)
 6.12979 +        .value(function(d) { return 1; });
 6.12980 +
 6.12981 +    var arc = d3.svg.arc()
 6.12982 +        .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
 6.12983 +        .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
 6.12984 +        .innerRadius(function(d) { return Math.max(0, y(d.y)); })
 6.12985 +        .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
 6.12986 +
 6.12987 +    // Keep track of the current and previous node being displayed as the root.
 6.12988 +    var node, prevNode;
 6.12989 +    // Keep track of the root node
 6.12990 +    var rootNode;
 6.12991 +
 6.12992 +    //============================================================
 6.12993 +    // chart function
 6.12994 +    //------------------------------------------------------------
 6.12995 +
 6.12996 +    var renderWatch = nv.utils.renderWatch(dispatch);
 6.12997 +
 6.12998 +    function chart(selection) {
 6.12999 +        renderWatch.reset();
 6.13000 +        selection.each(function(data) {
 6.13001 +            container = d3.select(this);
 6.13002 +            var availableWidth = nv.utils.availableWidth(width, container, margin);
 6.13003 +            var availableHeight = nv.utils.availableHeight(height, container, margin);
 6.13004 +            var radius = Math.min(availableWidth, availableHeight) / 2;
 6.13005 +            var path;
 6.13006 +
 6.13007 +            nv.utils.initSVG(container);
 6.13008 +
 6.13009 +            // Setup containers and skeleton of chart
 6.13010 +            var wrap = container.selectAll('.nv-wrap.nv-sunburst').data(data);
 6.13011 +            var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id);
 6.13012 +
 6.13013 +            var g = wrapEnter.selectAll('nv-sunburst');
 6.13014 +
 6.13015 +            wrap.attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
 6.13016 +
 6.13017 +            container.on('click', function (d, i) {
 6.13018 +                dispatch.chartClick({
 6.13019 +                    data: d,
 6.13020 +                    index: i,
 6.13021 +                    pos: d3.event,
 6.13022 +                    id: id
 6.13023 +                });
 6.13024 +            });
 6.13025 +
 6.13026 +            y.range([0, radius]);
 6.13027 +
 6.13028 +            node = node || data;
 6.13029 +            rootNode = data[0];
 6.13030 +            partition.value(modes[mode] || modes["count"]);
 6.13031 +            path = g.data(partition.nodes).enter()
 6.13032 +                .append("path")
 6.13033 +                .attr("d", arc)
 6.13034 +                .style("fill", function (d) {
 6.13035 +                    return color((d.children ? d : d.parent).name);
 6.13036 +                })
 6.13037 +                .style("stroke", "#FFF")
 6.13038 +                .on("click", function(d) {
 6.13039 +                    if (prevNode !== node && node !== d) prevNode = node;
 6.13040 +                    node = d;
 6.13041 +                    path.transition()
 6.13042 +                        .duration(duration)
 6.13043 +                        .attrTween("d", arcTweenZoom(d));
 6.13044 +                })
 6.13045 +                .each(stash)
 6.13046 +                .on("dblclick", function(d) {
 6.13047 +                    if (prevNode.parent == d) {
 6.13048 +                        path.transition()
 6.13049 +                            .duration(duration)
 6.13050 +                            .attrTween("d", arcTweenZoom(rootNode));
 6.13051 +                    }
 6.13052 +                })
 6.13053 +                .each(stash)
 6.13054 +                .on('mouseover', function(d,i){
 6.13055 +                    d3.select(this).classed('hover', true).style('opacity', 0.8);
 6.13056 +                    dispatch.elementMouseover({
 6.13057 +                        data: d,
 6.13058 +                        color: d3.select(this).style("fill")
 6.13059 +                    });
 6.13060 +                })
 6.13061 +                .on('mouseout', function(d,i){
 6.13062 +                    d3.select(this).classed('hover', false).style('opacity', 1);
 6.13063 +                    dispatch.elementMouseout({
 6.13064 +                        data: d
 6.13065 +                    });
 6.13066 +                })
 6.13067 +                .on('mousemove', function(d,i){
 6.13068 +                    dispatch.elementMousemove({
 6.13069 +                        data: d
 6.13070 +                    });
 6.13071 +                });
 6.13072 +
 6.13073 +
 6.13074 +
 6.13075 +            // Setup for switching data: stash the old values for transition.
 6.13076 +            function stash(d) {
 6.13077 +                d.x0 = d.x;
 6.13078 +                d.dx0 = d.dx;
 6.13079 +            }
 6.13080 +
 6.13081 +            // When switching data: interpolate the arcs in data space.
 6.13082 +            function arcTweenData(a, i) {
 6.13083 +                var oi = d3.interpolate({x: a.x0, dx: a.dx0}, a);
 6.13084 +
 6.13085 +                function tween(t) {
 6.13086 +                    var b = oi(t);
 6.13087 +                    a.x0 = b.x;
 6.13088 +                    a.dx0 = b.dx;
 6.13089 +                    return arc(b);
 6.13090 +                }
 6.13091 +
 6.13092 +                if (i == 0) {
 6.13093 +                    // If we are on the first arc, adjust the x domain to match the root node
 6.13094 +                    // at the current zoom level. (We only need to do this once.)
 6.13095 +                    var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]);
 6.13096 +                    return function (t) {
 6.13097 +                        x.domain(xd(t));
 6.13098 +                        return tween(t);
 6.13099 +                    };
 6.13100 +                } else {
 6.13101 +                    return tween;
 6.13102 +                }
 6.13103 +            }
 6.13104 +
 6.13105 +            // When zooming: interpolate the scales.
 6.13106 +            function arcTweenZoom(d) {
 6.13107 +                var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
 6.13108 +                    yd = d3.interpolate(y.domain(), [d.y, 1]),
 6.13109 +                    yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
 6.13110 +                return function (d, i) {
 6.13111 +                    return i
 6.13112 +                        ? function (t) {
 6.13113 +                        return arc(d);
 6.13114 +                    }
 6.13115 +                        : function (t) {
 6.13116 +                        x.domain(xd(t));
 6.13117 +                        y.domain(yd(t)).range(yr(t));
 6.13118 +                        return arc(d);
 6.13119 +                    };
 6.13120 +                };
 6.13121 +            }
 6.13122 +
 6.13123 +        });
 6.13124 +
 6.13125 +        renderWatch.renderEnd('sunburst immediate');
 6.13126 +        return chart;
 6.13127 +    }
 6.13128 +
 6.13129 +    //============================================================
 6.13130 +    // Expose Public Variables
 6.13131 +    //------------------------------------------------------------
 6.13132 +
 6.13133 +    chart.dispatch = dispatch;
 6.13134 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.13135 +
 6.13136 +    chart._options = Object.create({}, {
 6.13137 +        // simple options, just get/set the necessary values
 6.13138 +        width:      {get: function(){return width;}, set: function(_){width=_;}},
 6.13139 +        height:     {get: function(){return height;}, set: function(_){height=_;}},
 6.13140 +        mode:       {get: function(){return mode;}, set: function(_){mode=_;}},
 6.13141 +        id:         {get: function(){return id;}, set: function(_){id=_;}},
 6.13142 +        duration:   {get: function(){return duration;}, set: function(_){duration=_;}},
 6.13143 +
 6.13144 +        // options that require extra logic in the setter
 6.13145 +        margin: {get: function(){return margin;}, set: function(_){
 6.13146 +            margin.top    = _.top    != undefined ? _.top    : margin.top;
 6.13147 +            margin.right  = _.right  != undefined ? _.right  : margin.right;
 6.13148 +            margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;
 6.13149 +            margin.left   = _.left   != undefined ? _.left   : margin.left;
 6.13150 +        }},
 6.13151 +        color: {get: function(){return color;}, set: function(_){
 6.13152 +            color=nv.utils.getColor(_);
 6.13153 +        }}
 6.13154 +    });
 6.13155 +
 6.13156 +    nv.utils.initOptions(chart);
 6.13157 +    return chart;
 6.13158 +};
 6.13159 +nv.models.sunburstChart = function() {
 6.13160 +    "use strict";
 6.13161 +
 6.13162 +    //============================================================
 6.13163 +    // Public Variables with Default Settings
 6.13164 +    //------------------------------------------------------------
 6.13165 +
 6.13166 +    var sunburst = nv.models.sunburst();
 6.13167 +    var tooltip = nv.models.tooltip();
 6.13168 +
 6.13169 +    var margin = {top: 30, right: 20, bottom: 20, left: 20}
 6.13170 +        , width = null
 6.13171 +        , height = null
 6.13172 +        , color = nv.utils.defaultColor()
 6.13173 +        , id = Math.round(Math.random() * 100000)
 6.13174 +        , defaultState = null
 6.13175 +        , noData = null
 6.13176 +        , duration = 250
 6.13177 +        , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd')
 6.13178 +        ;
 6.13179 +
 6.13180 +    //============================================================
 6.13181 +    // Private Variables
 6.13182 +    //------------------------------------------------------------
 6.13183 +
 6.13184 +    var renderWatch = nv.utils.renderWatch(dispatch);
 6.13185 +    tooltip.headerEnabled(false).duration(0).valueFormatter(function(d, i) {
 6.13186 +        return d;
 6.13187 +    });
 6.13188 +
 6.13189 +    //============================================================
 6.13190 +    // Chart function
 6.13191 +    //------------------------------------------------------------
 6.13192 +
 6.13193 +    function chart(selection) {
 6.13194 +        renderWatch.reset();
 6.13195 +        renderWatch.models(sunburst);
 6.13196 +
 6.13197 +        selection.each(function(data) {
 6.13198 +            var container = d3.select(this);
 6.13199 +            nv.utils.initSVG(container);
 6.13200 +
 6.13201 +            var that = this;
 6.13202 +            var availableWidth = nv.utils.availableWidth(width, container, margin),
 6.13203 +                availableHeight = nv.utils.availableHeight(height, container, margin);
 6.13204 +
 6.13205 +            chart.update = function() {
 6.13206 +                if (duration === 0)
 6.13207 +                    container.call(chart);
 6.13208 +                else
 6.13209 +                    container.transition().duration(duration).call(chart)
 6.13210 +            };
 6.13211 +            chart.container = this;
 6.13212 +
 6.13213 +            // Display No Data message if there's nothing to show.
 6.13214 +            if (!data || !data.length) {
 6.13215 +                nv.utils.noData(chart, container);
 6.13216 +                return chart;
 6.13217 +            } else {
 6.13218 +                container.selectAll('.nv-noData').remove();
 6.13219 +            }
 6.13220 +
 6.13221 +            // Setup containers and skeleton of chart
 6.13222 +            var wrap = container.selectAll('g.nv-wrap.nv-sunburstChart').data(data);
 6.13223 +            var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburstChart').append('g');
 6.13224 +            var g = wrap.select('g');
 6.13225 +
 6.13226 +            gEnter.append('g').attr('class', 'nv-sunburstWrap');
 6.13227 +
 6.13228 +            wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
 6.13229 +
 6.13230 +            // Main Chart Component(s)
 6.13231 +            sunburst.width(availableWidth).height(availableHeight);
 6.13232 +            var sunWrap = g.select('.nv-sunburstWrap').datum(data);
 6.13233 +            d3.transition(sunWrap).call(sunburst);
 6.13234 +
 6.13235 +        });
 6.13236 +
 6.13237 +        renderWatch.renderEnd('sunburstChart immediate');
 6.13238 +        return chart;
 6.13239 +    }
 6.13240 +
 6.13241 +    //============================================================
 6.13242 +    // Event Handling/Dispatching (out of chart's scope)
 6.13243 +    //------------------------------------------------------------
 6.13244 +
 6.13245 +    sunburst.dispatch.on('elementMouseover.tooltip', function(evt) {
 6.13246 +        evt['series'] = {
 6.13247 +            key: evt.data.name,
 6.13248 +            value: evt.data.size,
 6.13249 +            color: evt.color
 6.13250 +        };
 6.13251 +        tooltip.data(evt).hidden(false);
 6.13252 +    });
 6.13253 +
 6.13254 +    sunburst.dispatch.on('elementMouseout.tooltip', function(evt) {
 6.13255 +        tooltip.hidden(true);
 6.13256 +    });
 6.13257 +
 6.13258 +    sunburst.dispatch.on('elementMousemove.tooltip', function(evt) {
 6.13259 +        tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
 6.13260 +    });
 6.13261 +
 6.13262 +    //============================================================
 6.13263 +    // Expose Public Variables
 6.13264 +    //------------------------------------------------------------
 6.13265 +
 6.13266 +    // expose chart's sub-components
 6.13267 +    chart.dispatch = dispatch;
 6.13268 +    chart.sunburst = sunburst;
 6.13269 +    chart.tooltip = tooltip;
 6.13270 +    chart.options = nv.utils.optionsFunc.bind(chart);
 6.13271 +
 6.13272 +    // use Object get/set functionality to map between vars and chart functions
 6.13273 +    chart._options = Object.create({}, {
 6.13274 +        // simple options, just get/set the necessary values
 6.13275 +        noData:         {get: function(){return noData;},         set: function(_){noData=_;}},
 6.13276 +        defaultState:   {get: function(){return defaultState;},   set: function(_){defaultState=_;}},
 6.13277 +
 6.13278 +        // options that require extra logic in the setter
 6.13279 +        color: {get: function(){return color;}, set: function(_){
 6.13280 +            color = _;
 6.13281 +            sunburst.color(color);
 6.13282 +        }},
 6.13283 +        duration: {get: function(){return duration;}, set: function(_){
 6.13284 +            duration = _;
 6.13285 +            renderWatch.reset(duration);
 6.13286 +            sunburst.duration(duration);
 6.13287 +        }},
 6.13288 +        margin: {get: function(){return margin;}, set: function(_){
 6.13289 +            margin.top    = _.top    !== undefined ? _.top    : margin.top;
 6.13290 +            margin.right  = _.right  !== undefined ? _.right  : margin.right;
 6.13291 +            margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
 6.13292 +            margin.left   = _.left   !== undefined ? _.left   : margin.left;
 6.13293 +        }}
 6.13294 +    });
 6.13295 +    nv.utils.inheritOptions(chart, sunburst);
 6.13296 +    nv.utils.initOptions(chart);
 6.13297 +    return chart;
 6.13298 +};
 6.13299 +
 6.13300 +nv.version = "1.8.1";
 6.13301 +})();
 6.13302 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/gtc/simple-statistics.js	Sun Feb 19 19:45:31 2017 -0800
     7.3 @@ -0,0 +1,3514 @@
     7.4 +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ss = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
     7.5 +/* @flow */
     7.6 +'use strict';
     7.7 +
     7.8 +// # simple-statistics
     7.9 +//
    7.10 +// A simple, literate statistics system.
    7.11 +
    7.12 +var ss = module.exports = {};
    7.13 +
    7.14 +// Linear Regression
    7.15 +ss.linearRegression = require(21);
    7.16 +ss.linearRegressionLine = require(22);
    7.17 +ss.standardDeviation = require(54);
    7.18 +ss.rSquared = require(43);
    7.19 +ss.mode = require(32);
    7.20 +ss.modeSorted = require(33);
    7.21 +ss.min = require(29);
    7.22 +ss.max = require(23);
    7.23 +ss.minSorted = require(30);
    7.24 +ss.maxSorted = require(24);
    7.25 +ss.sum = require(56);
    7.26 +ss.sumSimple = require(58);
    7.27 +ss.product = require(39);
    7.28 +ss.quantile = require(40);
    7.29 +ss.quantileSorted = require(41);
    7.30 +ss.iqr = ss.interquartileRange = require(19);
    7.31 +ss.medianAbsoluteDeviation = ss.mad = require(27);
    7.32 +ss.chunk = require(8);
    7.33 +ss.shuffle = require(51);
    7.34 +ss.shuffleInPlace = require(52);
    7.35 +ss.sample = require(45);
    7.36 +ss.ckmeans = require(9);
    7.37 +ss.uniqueCountSorted = require(61);
    7.38 +ss.sumNthPowerDeviations = require(57);
    7.39 +ss.equalIntervalBreaks = require(14);
    7.40 +
    7.41 +// sample statistics
    7.42 +ss.sampleCovariance = require(47);
    7.43 +ss.sampleCorrelation = require(46);
    7.44 +ss.sampleVariance = require(50);
    7.45 +ss.sampleStandardDeviation = require(49);
    7.46 +ss.sampleSkewness = require(48);
    7.47 +
    7.48 +// combinatorics
    7.49 +ss.permutationsHeap = require(36);
    7.50 +ss.combinations = require(10);
    7.51 +ss.combinationsReplacement = require(11);
    7.52 +
    7.53 +// measures of centrality
    7.54 +ss.geometricMean = require(17);
    7.55 +ss.harmonicMean = require(18);
    7.56 +ss.mean = ss.average = require(25);
    7.57 +ss.median = require(26);
    7.58 +ss.medianSorted = require(28);
    7.59 +
    7.60 +ss.rootMeanSquare = ss.rms = require(44);
    7.61 +ss.variance = require(62);
    7.62 +ss.tTest = require(59);
    7.63 +ss.tTestTwoSample = require(60);
    7.64 +// ss.jenks = require('./src/jenks');
    7.65 +
    7.66 +// Classifiers
    7.67 +ss.bayesian = require(2);
    7.68 +ss.perceptron = require(35);
    7.69 +
    7.70 +// Distribution-related methods
    7.71 +ss.epsilon = require(13); // We make ε available to the test suite.
    7.72 +ss.factorial = require(16);
    7.73 +ss.bernoulliDistribution = require(3);
    7.74 +ss.binomialDistribution = require(4);
    7.75 +ss.poissonDistribution = require(37);
    7.76 +ss.chiSquaredGoodnessOfFit = require(7);
    7.77 +
    7.78 +// Normal distribution
    7.79 +ss.zScore = require(63);
    7.80 +ss.cumulativeStdNormalProbability = require(12);
    7.81 +ss.standardNormalTable = require(55);
    7.82 +ss.errorFunction = ss.erf = require(15);
    7.83 +ss.inverseErrorFunction = require(20);
    7.84 +ss.probit = require(38);
    7.85 +ss.mixin = require(31);
    7.86 +
    7.87 +// Root-finding methods
    7.88 +ss.bisect = require(5);
    7.89 +
    7.90 +},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"2":2,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"3":3,"30":30,"31":31,"32":32,"33":33,"35":35,"36":36,"37":37,"38":38,"39":39,"4":4,"40":40,"41":41,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"49":49,"5":5,"50":50,"51":51,"52":52,"54":54,"55":55,"56":56,"57":57,"58":58,"59":59,"60":60,"61":61,"62":62,"63":63,"7":7,"8":8,"9":9}],2:[function(require,module,exports){
    7.91 +'use strict';
    7.92 +/* @flow */
    7.93 +
    7.94 +/**
    7.95 + * [Bayesian Classifier](http://en.wikipedia.org/wiki/Naive_Bayes_classifier)
    7.96 + *
    7.97 + * This is a naïve bayesian classifier that takes
    7.98 + * singly-nested objects.
    7.99 + *
   7.100 + * @class
   7.101 + * @example
   7.102 + * var bayes = new BayesianClassifier();
   7.103 + * bayes.train({
   7.104 + *   species: 'Cat'
   7.105 + * }, 'animal');
   7.106 + * var result = bayes.score({
   7.107 + *   species: 'Cat'
   7.108 + * })
   7.109 + * // result
   7.110 + * // {
   7.111 + * //   animal: 1
   7.112 + * // }
   7.113 + */
   7.114 +function BayesianClassifier() {
   7.115 +    // The number of items that are currently
   7.116 +    // classified in the model
   7.117 +    this.totalCount = 0;
   7.118 +    // Every item classified in the model
   7.119 +    this.data = {};
   7.120 +}
   7.121 +
   7.122 +/**
   7.123 + * Train the classifier with a new item, which has a single
   7.124 + * dimension of Javascript literal keys and values.
   7.125 + *
   7.126 + * @param {Object} item an object with singly-deep properties
   7.127 + * @param {string} category the category this item belongs to
   7.128 + * @return {undefined} adds the item to the classifier
   7.129 + */
   7.130 +BayesianClassifier.prototype.train = function(item, category) {
   7.131 +    // If the data object doesn't have any values
   7.132 +    // for this category, create a new object for it.
   7.133 +    if (!this.data[category]) {
   7.134 +        this.data[category] = {};
   7.135 +    }
   7.136 +
   7.137 +    // Iterate through each key in the item.
   7.138 +    for (var k in item) {
   7.139 +        var v = item[k];
   7.140 +        // Initialize the nested object `data[category][k][item[k]]`
   7.141 +        // with an object of keys that equal 0.
   7.142 +        if (this.data[category][k] === undefined) {
   7.143 +            this.data[category][k] = {};
   7.144 +        }
   7.145 +        if (this.data[category][k][v] === undefined) {
   7.146 +            this.data[category][k][v] = 0;
   7.147 +        }
   7.148 +
   7.149 +        // And increment the key for this key/value combination.
   7.150 +        this.data[category][k][v]++;
   7.151 +    }
   7.152 +
   7.153 +    // Increment the number of items classified
   7.154 +    this.totalCount++;
   7.155 +};
   7.156 +
   7.157 +/**
   7.158 + * Generate a score of how well this item matches all
   7.159 + * possible categories based on its attributes
   7.160 + *
   7.161 + * @param {Object} item an item in the same format as with train
   7.162 + * @returns {Object} of probabilities that this item belongs to a
   7.163 + * given category.
   7.164 + */
   7.165 +BayesianClassifier.prototype.score = function(item) {
   7.166 +    // Initialize an empty array of odds per category.
   7.167 +    var odds = {}, category;
   7.168 +    // Iterate through each key in the item,
   7.169 +    // then iterate through each category that has been used
   7.170 +    // in previous calls to `.train()`
   7.171 +    for (var k in item) {
   7.172 +        var v = item[k];
   7.173 +        for (category in this.data) {
   7.174 +            // Create an empty object for storing key - value combinations
   7.175 +            // for this category.
   7.176 +            odds[category] = {};
   7.177 +
   7.178 +            // If this item doesn't even have a property, it counts for nothing,
   7.179 +            // but if it does have the property that we're looking for from
   7.180 +            // the item to categorize, it counts based on how popular it is
   7.181 +            // versus the whole population.
   7.182 +            if (this.data[category][k]) {
   7.183 +                odds[category][k + '_' + v] = (this.data[category][k][v] || 0) / this.totalCount;
   7.184 +            } else {
   7.185 +                odds[category][k + '_' + v] = 0;
   7.186 +            }
   7.187 +        }
   7.188 +    }
   7.189 +
   7.190 +    // Set up a new object that will contain sums of these odds by category
   7.191 +    var oddsSums = {};
   7.192 +
   7.193 +    for (category in odds) {
   7.194 +        // Tally all of the odds for each category-combination pair -
   7.195 +        // the non-existence of a category does not add anything to the
   7.196 +        // score.
   7.197 +        oddsSums[category] = 0;
   7.198 +        for (var combination in odds[category]) {
   7.199 +            oddsSums[category] += odds[category][combination];
   7.200 +        }
   7.201 +    }
   7.202 +
   7.203 +    return oddsSums;
   7.204 +};
   7.205 +
   7.206 +module.exports = BayesianClassifier;
   7.207 +
   7.208 +},{}],3:[function(require,module,exports){
   7.209 +'use strict';
   7.210 +/* @flow */
   7.211 +
   7.212 +var binomialDistribution = require(4);
   7.213 +
   7.214 +/**
   7.215 + * The [Bernoulli distribution](http://en.wikipedia.org/wiki/Bernoulli_distribution)
   7.216 + * is the probability discrete
   7.217 + * distribution of a random variable which takes value 1 with success
   7.218 + * probability `p` and value 0 with failure
   7.219 + * probability `q` = 1 - `p`. It can be used, for example, to represent the
   7.220 + * toss of a coin, where "1" is defined to mean "heads" and "0" is defined
   7.221 + * to mean "tails" (or vice versa). It is
   7.222 + * a special case of a Binomial Distribution
   7.223 + * where `n` = 1.
   7.224 + *
   7.225 + * @param {number} p input value, between 0 and 1 inclusive
   7.226 + * @returns {number} value of bernoulli distribution at this point
   7.227 + * @example
   7.228 + * bernoulliDistribution(0.5); // => { '0': 0.5, '1': 0.5 }
   7.229 + */
   7.230 +function bernoulliDistribution(p/*: number */) {
   7.231 +    // Check that `p` is a valid probability (0 ≤ p ≤ 1)
   7.232 +    if (p < 0 || p > 1 ) { return NaN; }
   7.233 +
   7.234 +    return binomialDistribution(1, p);
   7.235 +}
   7.236 +
   7.237 +module.exports = bernoulliDistribution;
   7.238 +
   7.239 +},{"4":4}],4:[function(require,module,exports){
   7.240 +'use strict';
   7.241 +/* @flow */
   7.242 +
   7.243 +var epsilon = require(13);
   7.244 +var factorial = require(16);
   7.245 +
   7.246 +/**
   7.247 + * The [Binomial Distribution](http://en.wikipedia.org/wiki/Binomial_distribution) is the discrete probability
   7.248 + * distribution of the number of successes in a sequence of n independent yes/no experiments, each of which yields
   7.249 + * success with probability `probability`. Such a success/failure experiment is also called a Bernoulli experiment or
   7.250 + * Bernoulli trial; when trials = 1, the Binomial Distribution is a Bernoulli Distribution.
   7.251 + *
   7.252 + * @param {number} trials number of trials to simulate
   7.253 + * @param {number} probability
   7.254 + * @returns {Object} output
   7.255 + */
   7.256 +function binomialDistribution(
   7.257 +    trials/*: number */,
   7.258 +    probability/*: number */)/*: ?Object */ {
   7.259 +    // Check that `p` is a valid probability (0 ≤ p ≤ 1),
   7.260 +    // that `n` is an integer, strictly positive.
   7.261 +    if (probability < 0 || probability > 1 ||
   7.262 +        trials <= 0 || trials % 1 !== 0) {
   7.263 +        return undefined;
   7.264 +    }
   7.265 +
   7.266 +    // We initialize `x`, the random variable, and `accumulator`, an accumulator
   7.267 +    // for the cumulative distribution function to 0. `distribution_functions`
   7.268 +    // is the object we'll return with the `probability_of_x` and the
   7.269 +    // `cumulativeProbability_of_x`, as well as the calculated mean &
   7.270 +    // variance. We iterate until the `cumulativeProbability_of_x` is
   7.271 +    // within `epsilon` of 1.0.
   7.272 +    var x = 0,
   7.273 +        cumulativeProbability = 0,
   7.274 +        cells = {};
   7.275 +
   7.276 +    // This algorithm iterates through each potential outcome,
   7.277 +    // until the `cumulativeProbability` is very close to 1, at
   7.278 +    // which point we've defined the vast majority of outcomes
   7.279 +    do {
   7.280 +        // a [probability mass function](https://en.wikipedia.org/wiki/Probability_mass_function)
   7.281 +        cells[x] = factorial(trials) /
   7.282 +            (factorial(x) * factorial(trials - x)) *
   7.283 +            (Math.pow(probability, x) * Math.pow(1 - probability, trials - x));
   7.284 +        cumulativeProbability += cells[x];
   7.285 +        x++;
   7.286 +    // when the cumulativeProbability is nearly 1, we've calculated
   7.287 +    // the useful range of this distribution
   7.288 +    } while (cumulativeProbability < 1 - epsilon);
   7.289 +
   7.290 +    return cells;
   7.291 +}
   7.292 +
   7.293 +module.exports = binomialDistribution;
   7.294 +
   7.295 +},{"13":13,"16":16}],5:[function(require,module,exports){
   7.296 +'use strict';
   7.297 +/* @flow */
   7.298 +
   7.299 +var sign = require(53);
   7.300 +/**
   7.301 + * [Bisection method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding 
   7.302 + * method that repeatedly bisects an interval to find the root.
   7.303 + * 
   7.304 + * This function returns a numerical approximation to the exact value.
   7.305 + * 
   7.306 + * @param {Function} func input function
   7.307 + * @param {Number} start - start of interval
   7.308 + * @param {Number} end - end of interval
   7.309 + * @param {Number} maxIterations - the maximum number of iterations
   7.310 + * @param {Number} errorTolerance - the error tolerance
   7.311 + * @returns {Number} estimated root value
   7.312 + * @throws {TypeError} Argument func must be a function
   7.313 + * 
   7.314 + * @example
   7.315 + * bisect(Math.cos,0,4,100,0.003); // => 1.572265625
   7.316 + */
   7.317 +function bisect(
   7.318 +    func/*: (x: any) => number */,
   7.319 +    start/*: number */,
   7.320 +    end/*: number */,
   7.321 +    maxIterations/*: number */,
   7.322 +    errorTolerance/*: number */)/*:number*/ {
   7.323 +
   7.324 +    if (typeof func !== 'function') throw new TypeError('func must be a function');
   7.325 +    
   7.326 +    for (var i = 0; i < maxIterations; i++) {
   7.327 +        var output = (start + end) / 2;
   7.328 +
   7.329 +        if (func(output) === 0 || Math.abs((end - start) / 2) < errorTolerance) {
   7.330 +            return output;
   7.331 +        }
   7.332 +
   7.333 +        if (sign(func(output)) === sign(func(start))) {
   7.334 +            start = output;
   7.335 +        } else {
   7.336 +            end = output;
   7.337 +        }
   7.338 +    }
   7.339 +    
   7.340 +    throw new Error('maximum number of iterations exceeded');
   7.341 +}
   7.342 +
   7.343 +module.exports = bisect;
   7.344 +
   7.345 +},{"53":53}],6:[function(require,module,exports){
   7.346 +'use strict';
   7.347 +/* @flow */
   7.348 +
   7.349 +/**
   7.350 + * **Percentage Points of the χ2 (Chi-Squared) Distribution**
   7.351 + *
   7.352 + * The [χ2 (Chi-Squared) Distribution](http://en.wikipedia.org/wiki/Chi-squared_distribution) is used in the common
   7.353 + * chi-squared tests for goodness of fit of an observed distribution to a theoretical one, the independence of two
   7.354 + * criteria of classification of qualitative data, and in confidence interval estimation for a population standard
   7.355 + * deviation of a normal distribution from a sample standard deviation.
   7.356 + *
   7.357 + * Values from Appendix 1, Table III of William W. Hines & Douglas C. Montgomery, "Probability and Statistics in
   7.358 + * Engineering and Management Science", Wiley (1980).
   7.359 + */
   7.360 +var chiSquaredDistributionTable = { '1':
   7.361 +   { '0.995': 0,
   7.362 +     '0.99': 0,
   7.363 +     '0.975': 0,
   7.364 +     '0.95': 0,
   7.365 +     '0.9': 0.02,
   7.366 +     '0.5': 0.45,
   7.367 +     '0.1': 2.71,
   7.368 +     '0.05': 3.84,
   7.369 +     '0.025': 5.02,
   7.370 +     '0.01': 6.63,
   7.371 +     '0.005': 7.88 },
   7.372 +  '2':
   7.373 +   { '0.995': 0.01,
   7.374 +     '0.99': 0.02,
   7.375 +     '0.975': 0.05,
   7.376 +     '0.95': 0.1,
   7.377 +     '0.9': 0.21,
   7.378 +     '0.5': 1.39,
   7.379 +     '0.1': 4.61,
   7.380 +     '0.05': 5.99,
   7.381 +     '0.025': 7.38,
   7.382 +     '0.01': 9.21,
   7.383 +     '0.005': 10.6 },
   7.384 +  '3':
   7.385 +   { '0.995': 0.07,
   7.386 +     '0.99': 0.11,
   7.387 +     '0.975': 0.22,
   7.388 +     '0.95': 0.35,
   7.389 +     '0.9': 0.58,
   7.390 +     '0.5': 2.37,
   7.391 +     '0.1': 6.25,
   7.392 +     '0.05': 7.81,
   7.393 +     '0.025': 9.35,
   7.394 +     '0.01': 11.34,
   7.395 +     '0.005': 12.84 },
   7.396 +  '4':
   7.397 +   { '0.995': 0.21,
   7.398 +     '0.99': 0.3,
   7.399 +     '0.975': 0.48,
   7.400 +     '0.95': 0.71,
   7.401 +     '0.9': 1.06,
   7.402 +     '0.5': 3.36,
   7.403 +     '0.1': 7.78,
   7.404 +     '0.05': 9.49,
   7.405 +     '0.025': 11.14,
   7.406 +     '0.01': 13.28,
   7.407 +     '0.005': 14.86 },
   7.408 +  '5':
   7.409 +   { '0.995': 0.41,
   7.410 +     '0.99': 0.55,
   7.411 +     '0.975': 0.83,
   7.412 +     '0.95': 1.15,
   7.413 +     '0.9': 1.61,
   7.414 +     '0.5': 4.35,
   7.415 +     '0.1': 9.24,
   7.416 +     '0.05': 11.07,
   7.417 +     '0.025': 12.83,
   7.418 +     '0.01': 15.09,
   7.419 +     '0.005': 16.75 },
   7.420 +  '6':
   7.421 +   { '0.995': 0.68,
   7.422 +     '0.99': 0.87,
   7.423 +     '0.975': 1.24,
   7.424 +     '0.95': 1.64,
   7.425 +     '0.9': 2.2,
   7.426 +     '0.5': 5.35,
   7.427 +     '0.1': 10.65,
   7.428 +     '0.05': 12.59,
   7.429 +     '0.025': 14.45,
   7.430 +     '0.01': 16.81,
   7.431 +     '0.005': 18.55 },
   7.432 +  '7':
   7.433 +   { '0.995': 0.99,
   7.434 +     '0.99': 1.25,
   7.435 +     '0.975': 1.69,
   7.436 +     '0.95': 2.17,
   7.437 +     '0.9': 2.83,
   7.438 +     '0.5': 6.35,
   7.439 +     '0.1': 12.02,
   7.440 +     '0.05': 14.07,
   7.441 +     '0.025': 16.01,
   7.442 +     '0.01': 18.48,
   7.443 +     '0.005': 20.28 },
   7.444 +  '8':
   7.445 +   { '0.995': 1.34,
   7.446 +     '0.99': 1.65,
   7.447 +     '0.975': 2.18,
   7.448 +     '0.95': 2.73,
   7.449 +     '0.9': 3.49,
   7.450 +     '0.5': 7.34,
   7.451 +     '0.1': 13.36,
   7.452 +     '0.05': 15.51,
   7.453 +     '0.025': 17.53,
   7.454 +     '0.01': 20.09,
   7.455 +     '0.005': 21.96 },
   7.456 +  '9':
   7.457 +   { '0.995': 1.73,
   7.458 +     '0.99': 2.09,
   7.459 +     '0.975': 2.7,
   7.460 +     '0.95': 3.33,
   7.461 +     '0.9': 4.17,
   7.462 +     '0.5': 8.34,
   7.463 +     '0.1': 14.68,
   7.464 +     '0.05': 16.92,
   7.465 +     '0.025': 19.02,
   7.466 +     '0.01': 21.67,
   7.467 +     '0.005': 23.59 },
   7.468 +  '10':
   7.469 +   { '0.995': 2.16,
   7.470 +     '0.99': 2.56,
   7.471 +     '0.975': 3.25,
   7.472 +     '0.95': 3.94,
   7.473 +     '0.9': 4.87,
   7.474 +     '0.5': 9.34,
   7.475 +     '0.1': 15.99,
   7.476 +     '0.05': 18.31,
   7.477 +     '0.025': 20.48,
   7.478 +     '0.01': 23.21,
   7.479 +     '0.005': 25.19 },
   7.480 +  '11':
   7.481 +   { '0.995': 2.6,
   7.482 +     '0.99': 3.05,
   7.483 +     '0.975': 3.82,
   7.484 +     '0.95': 4.57,
   7.485 +     '0.9': 5.58,
   7.486 +     '0.5': 10.34,
   7.487 +     '0.1': 17.28,
   7.488 +     '0.05': 19.68,
   7.489 +     '0.025': 21.92,
   7.490 +     '0.01': 24.72,
   7.491 +     '0.005': 26.76 },
   7.492 +  '12':
   7.493 +   { '0.995': 3.07,
   7.494 +     '0.99': 3.57,
   7.495 +     '0.975': 4.4,
   7.496 +     '0.95': 5.23,
   7.497 +     '0.9': 6.3,
   7.498 +     '0.5': 11.34,
   7.499 +     '0.1': 18.55,
   7.500 +     '0.05': 21.03,
   7.501 +     '0.025': 23.34,
   7.502 +     '0.01': 26.22,
   7.503 +     '0.005': 28.3 },
   7.504 +  '13':
   7.505 +   { '0.995': 3.57,
   7.506 +     '0.99': 4.11,
   7.507 +     '0.975': 5.01,
   7.508 +     '0.95': 5.89,
   7.509 +     '0.9': 7.04,
   7.510 +     '0.5': 12.34,
   7.511 +     '0.1': 19.81,
   7.512 +     '0.05': 22.36,
   7.513 +     '0.025': 24.74,
   7.514 +     '0.01': 27.69,
   7.515 +     '0.005': 29.82 },
   7.516 +  '14':
   7.517 +   { '0.995': 4.07,
   7.518 +     '0.99': 4.66,
   7.519 +     '0.975': 5.63,
   7.520 +     '0.95': 6.57,
   7.521 +     '0.9': 7.79,
   7.522 +     '0.5': 13.34,
   7.523 +     '0.1': 21.06,
   7.524 +     '0.05': 23.68,
   7.525 +     '0.025': 26.12,
   7.526 +     '0.01': 29.14,
   7.527 +     '0.005': 31.32 },
   7.528 +  '15':
   7.529 +   { '0.995': 4.6,
   7.530 +     '0.99': 5.23,
   7.531 +     '0.975': 6.27,
   7.532 +     '0.95': 7.26,
   7.533 +     '0.9': 8.55,
   7.534 +     '0.5': 14.34,
   7.535 +     '0.1': 22.31,
   7.536 +     '0.05': 25,
   7.537 +     '0.025': 27.49,
   7.538 +     '0.01': 30.58,
   7.539 +     '0.005': 32.8 },
   7.540 +  '16':
   7.541 +   { '0.995': 5.14,
   7.542 +     '0.99': 5.81,
   7.543 +     '0.975': 6.91,
   7.544 +     '0.95': 7.96,
   7.545 +     '0.9': 9.31,
   7.546 +     '0.5': 15.34,
   7.547 +     '0.1': 23.54,
   7.548 +     '0.05': 26.3,
   7.549 +     '0.025': 28.85,
   7.550 +     '0.01': 32,
   7.551 +     '0.005': 34.27 },
   7.552 +  '17':
   7.553 +   { '0.995': 5.7,
   7.554 +     '0.99': 6.41,
   7.555 +     '0.975': 7.56,
   7.556 +     '0.95': 8.67,
   7.557 +     '0.9': 10.09,
   7.558 +     '0.5': 16.34,
   7.559 +     '0.1': 24.77,
   7.560 +     '0.05': 27.59,
   7.561 +     '0.025': 30.19,
   7.562 +     '0.01': 33.41,
   7.563 +     '0.005': 35.72 },
   7.564 +  '18':
   7.565 +   { '0.995': 6.26,
   7.566 +     '0.99': 7.01,
   7.567 +     '0.975': 8.23,
   7.568 +     '0.95': 9.39,
   7.569 +     '0.9': 10.87,
   7.570 +     '0.5': 17.34,
   7.571 +     '0.1': 25.99,
   7.572 +     '0.05': 28.87,
   7.573 +     '0.025': 31.53,
   7.574 +     '0.01': 34.81,
   7.575 +     '0.005': 37.16 },
   7.576 +  '19':
   7.577 +   { '0.995': 6.84,
   7.578 +     '0.99': 7.63,
   7.579 +     '0.975': 8.91,
   7.580 +     '0.95': 10.12,
   7.581 +     '0.9': 11.65,
   7.582 +     '0.5': 18.34,
   7.583 +     '0.1': 27.2,
   7.584 +     '0.05': 30.14,
   7.585 +     '0.025': 32.85,
   7.586 +     '0.01': 36.19,
   7.587 +     '0.005': 38.58 },
   7.588 +  '20':
   7.589 +   { '0.995': 7.43,
   7.590 +     '0.99': 8.26,
   7.591 +     '0.975': 9.59,
   7.592 +     '0.95': 10.85,
   7.593 +     '0.9': 12.44,
   7.594 +     '0.5': 19.34,
   7.595 +     '0.1': 28.41,
   7.596 +     '0.05': 31.41,
   7.597 +     '0.025': 34.17,
   7.598 +     '0.01': 37.57,
   7.599 +     '0.005': 40 },
   7.600 +  '21':
   7.601 +   { '0.995': 8.03,
   7.602 +     '0.99': 8.9,
   7.603 +     '0.975': 10.28,
   7.604 +     '0.95': 11.59,
   7.605 +     '0.9': 13.24,
   7.606 +     '0.5': 20.34,
   7.607 +     '0.1': 29.62,
   7.608 +     '0.05': 32.67,
   7.609 +     '0.025': 35.48,
   7.610 +     '0.01': 38.93,
   7.611 +     '0.005': 41.4 },
   7.612 +  '22':
   7.613 +   { '0.995': 8.64,
   7.614 +     '0.99': 9.54,
   7.615 +     '0.975': 10.98,
   7.616 +     '0.95': 12.34,
   7.617 +     '0.9': 14.04,
   7.618 +     '0.5': 21.34,
   7.619 +     '0.1': 30.81,
   7.620 +     '0.05': 33.92,
   7.621 +     '0.025': 36.78,
   7.622 +     '0.01': 40.29,
   7.623 +     '0.005': 42.8 },
   7.624 +  '23':
   7.625 +   { '0.995': 9.26,
   7.626 +     '0.99': 10.2,
   7.627 +     '0.975': 11.69,
   7.628 +     '0.95': 13.09,
   7.629 +     '0.9': 14.85,
   7.630 +     '0.5': 22.34,
   7.631 +     '0.1': 32.01,
   7.632 +     '0.05': 35.17,
   7.633 +     '0.025': 38.08,
   7.634 +     '0.01': 41.64,
   7.635 +     '0.005': 44.18 },
   7.636 +  '24':
   7.637 +   { '0.995': 9.89,
   7.638 +     '0.99': 10.86,
   7.639 +     '0.975': 12.4,
   7.640 +     '0.95': 13.85,
   7.641 +     '0.9': 15.66,
   7.642 +     '0.5': 23.34,
   7.643 +     '0.1': 33.2,
   7.644 +     '0.05': 36.42,
   7.645 +     '0.025': 39.36,
   7.646 +     '0.01': 42.98,
   7.647 +     '0.005': 45.56 },
   7.648 +  '25':
   7.649 +   { '0.995': 10.52,
   7.650 +     '0.99': 11.52,
   7.651 +     '0.975': 13.12,
   7.652 +     '0.95': 14.61,
   7.653 +     '0.9': 16.47,
   7.654 +     '0.5': 24.34,
   7.655 +     '0.1': 34.28,
   7.656 +     '0.05': 37.65,
   7.657 +     '0.025': 40.65,
   7.658 +     '0.01': 44.31,
   7.659 +     '0.005': 46.93 },
   7.660 +  '26':
   7.661 +   { '0.995': 11.16,
   7.662 +     '0.99': 12.2,
   7.663 +     '0.975': 13.84,
   7.664 +     '0.95': 15.38,
   7.665 +     '0.9': 17.29,
   7.666 +     '0.5': 25.34,
   7.667 +     '0.1': 35.56,
   7.668 +     '0.05': 38.89,
   7.669 +     '0.025': 41.92,
   7.670 +     '0.01': 45.64,
   7.671 +     '0.005': 48.29 },
   7.672 +  '27':
   7.673 +   { '0.995': 11.81,
   7.674 +     '0.99': 12.88,
   7.675 +     '0.975': 14.57,
   7.676 +     '0.95': 16.15,
   7.677 +     '0.9': 18.11,
   7.678 +     '0.5': 26.34,
   7.679 +     '0.1': 36.74,
   7.680 +     '0.05': 40.11,
   7.681 +     '0.025': 43.19,
   7.682 +     '0.01': 46.96,
   7.683 +     '0.005': 49.65 },
   7.684 +  '28':
   7.685 +   { '0.995': 12.46,
   7.686 +     '0.99': 13.57,
   7.687 +     '0.975': 15.31,
   7.688 +     '0.95': 16.93,
   7.689 +     '0.9': 18.94,
   7.690 +     '0.5': 27.34,
   7.691 +     '0.1': 37.92,
   7.692 +     '0.05': 41.34,
   7.693 +     '0.025': 44.46,
   7.694 +     '0.01': 48.28,
   7.695 +     '0.005': 50.99 },
   7.696 +  '29':
   7.697 +   { '0.995': 13.12,
   7.698 +     '0.99': 14.26,
   7.699 +     '0.975': 16.05,
   7.700 +     '0.95': 17.71,
   7.701 +     '0.9': 19.77,
   7.702 +     '0.5': 28.34,
   7.703 +     '0.1': 39.09,
   7.704 +     '0.05': 42.56,
   7.705 +     '0.025': 45.72,
   7.706 +     '0.01': 49.59,
   7.707 +     '0.005': 52.34 },
   7.708 +  '30':
   7.709 +   { '0.995': 13.79,
   7.710 +     '0.99': 14.95,
   7.711 +     '0.975': 16.79,
   7.712 +     '0.95': 18.49,
   7.713 +     '0.9': 20.6,
   7.714 +     '0.5': 29.34,
   7.715 +     '0.1': 40.26,
   7.716 +     '0.05': 43.77,
   7.717 +     '0.025': 46.98,
   7.718 +     '0.01': 50.89,
   7.719 +     '0.005': 53.67 },
   7.720 +  '40':
   7.721 +   { '0.995': 20.71,
   7.722 +     '0.99': 22.16,
   7.723 +     '0.975': 24.43,
   7.724 +     '0.95': 26.51,
   7.725 +     '0.9': 29.05,
   7.726 +     '0.5': 39.34,
   7.727 +     '0.1': 51.81,
   7.728 +     '0.05': 55.76,
   7.729 +     '0.025': 59.34,
   7.730 +     '0.01': 63.69,
   7.731 +     '0.005': 66.77 },
   7.732 +  '50':
   7.733 +   { '0.995': 27.99,
   7.734 +     '0.99': 29.71,
   7.735 +     '0.975': 32.36,
   7.736 +     '0.95': 34.76,
   7.737 +     '0.9': 37.69,
   7.738 +     '0.5': 49.33,
   7.739 +     '0.1': 63.17,
   7.740 +     '0.05': 67.5,
   7.741 +     '0.025': 71.42,
   7.742 +     '0.01': 76.15,
   7.743 +     '0.005': 79.49 },
   7.744 +  '60':
   7.745 +   { '0.995': 35.53,
   7.746 +     '0.99': 37.48,
   7.747 +     '0.975': 40.48,
   7.748 +     '0.95': 43.19,
   7.749 +     '0.9': 46.46,
   7.750 +     '0.5': 59.33,
   7.751 +     '0.1': 74.4,
   7.752 +     '0.05': 79.08,
   7.753 +     '0.025': 83.3,
   7.754 +     '0.01': 88.38,
   7.755 +     '0.005': 91.95 },
   7.756 +  '70':
   7.757 +   { '0.995': 43.28,
   7.758 +     '0.99': 45.44,
   7.759 +     '0.975': 48.76,
   7.760 +     '0.95': 51.74,
   7.761 +     '0.9': 55.33,
   7.762 +     '0.5': 69.33,
   7.763 +     '0.1': 85.53,
   7.764 +     '0.05': 90.53,
   7.765 +     '0.025': 95.02,
   7.766 +     '0.01': 100.42,
   7.767 +     '0.005': 104.22 },
   7.768 +  '80':
   7.769 +   { '0.995': 51.17,
   7.770 +     '0.99': 53.54,
   7.771 +     '0.975': 57.15,
   7.772 +     '0.95': 60.39,
   7.773 +     '0.9': 64.28,
   7.774 +     '0.5': 79.33,
   7.775 +     '0.1': 96.58,
   7.776 +     '0.05': 101.88,
   7.777 +     '0.025': 106.63,
   7.778 +     '0.01': 112.33,
   7.779 +     '0.005': 116.32 },
   7.780 +  '90':
   7.781 +   { '0.995': 59.2,
   7.782 +     '0.99': 61.75,
   7.783 +     '0.975': 65.65,
   7.784 +     '0.95': 69.13,
   7.785 +     '0.9': 73.29,
   7.786 +     '0.5': 89.33,
   7.787 +     '0.1': 107.57,
   7.788 +     '0.05': 113.14,
   7.789 +     '0.025': 118.14,
   7.790 +     '0.01': 124.12,
   7.791 +     '0.005': 128.3 },
   7.792 +  '100':
   7.793 +   { '0.995': 67.33,
   7.794 +     '0.99': 70.06,
   7.795 +     '0.975': 74.22,
   7.796 +     '0.95': 77.93,
   7.797 +     '0.9': 82.36,
   7.798 +     '0.5': 99.33,
   7.799 +     '0.1': 118.5,
   7.800 +     '0.05': 124.34,
   7.801 +     '0.025': 129.56,
   7.802 +     '0.01': 135.81,
   7.803 +     '0.005': 140.17 } };
   7.804 +
   7.805 +module.exports = chiSquaredDistributionTable;
   7.806 +
   7.807 +},{}],7:[function(require,module,exports){
   7.808 +'use strict';
   7.809 +/* @flow */
   7.810 +
   7.811 +var mean = require(25);
   7.812 +var chiSquaredDistributionTable = require(6);
   7.813 +
   7.814 +/**
   7.815 + * The [χ2 (Chi-Squared) Goodness-of-Fit Test](http://en.wikipedia.org/wiki/Goodness_of_fit#Pearson.27s_chi-squared_test)
   7.816 + * uses a measure of goodness of fit which is the sum of differences between observed and expected outcome frequencies
   7.817 + * (that is, counts of observations), each squared and divided by the number of observations expected given the
   7.818 + * hypothesized distribution. The resulting χ2 statistic, `chiSquared`, can be compared to the chi-squared distribution
   7.819 + * to determine the goodness of fit. In order to determine the degrees of freedom of the chi-squared distribution, one
   7.820 + * takes the total number of observed frequencies and subtracts the number of estimated parameters. The test statistic
   7.821 + * follows, approximately, a chi-square distribution with (k − c) degrees of freedom where `k` is the number of non-empty
   7.822 + * cells and `c` is the number of estimated parameters for the distribution.
   7.823 + *
   7.824 + * @param {Array<number>} data
   7.825 + * @param {Function} distributionType a function that returns a point in a distribution:
   7.826 + * for instance, binomial, bernoulli, or poisson
   7.827 + * @param {number} significance
   7.828 + * @returns {number} chi squared goodness of fit
   7.829 + * @example
   7.830 + * // Data from Poisson goodness-of-fit example 10-19 in William W. Hines & Douglas C. Montgomery,
   7.831 + * // "Probability and Statistics in Engineering and Management Science", Wiley (1980).
   7.832 + * var data1019 = [
   7.833 + *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   7.834 + *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   7.835 + *     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   7.836 + *     2, 2, 2, 2, 2, 2, 2, 2, 2,
   7.837 + *     3, 3, 3, 3
   7.838 + * ];
   7.839 + * ss.chiSquaredGoodnessOfFit(data1019, ss.poissonDistribution, 0.05)); //= false
   7.840 + */
   7.841 +function chiSquaredGoodnessOfFit(
   7.842 +    data/*: Array<number> */,
   7.843 +    distributionType/*: Function */,
   7.844 +    significance/*: number */)/*: boolean */ {
   7.845 +    // Estimate from the sample data, a weighted mean.
   7.846 +    var inputMean = mean(data),
   7.847 +        // Calculated value of the χ2 statistic.
   7.848 +        chiSquared = 0,
   7.849 +        // Degrees of freedom, calculated as (number of class intervals -
   7.850 +        // number of hypothesized distribution parameters estimated - 1)
   7.851 +        degreesOfFreedom,
   7.852 +        // Number of hypothesized distribution parameters estimated, expected to be supplied in the distribution test.
   7.853 +        // Lose one degree of freedom for estimating `lambda` from the sample data.
   7.854 +        c = 1,
   7.855 +        // The hypothesized distribution.
   7.856 +        // Generate the hypothesized distribution.
   7.857 +        hypothesizedDistribution = distributionType(inputMean),
   7.858 +        observedFrequencies = [],
   7.859 +        expectedFrequencies = [],
   7.860 +        k;
   7.861 +
   7.862 +    // Create an array holding a histogram from the sample data, of
   7.863 +    // the form `{ value: numberOfOcurrences }`
   7.864 +    for (var i = 0; i < data.length; i++) {
   7.865 +        if (observedFrequencies[data[i]] === undefined) {
   7.866 +            observedFrequencies[data[i]] = 0;
   7.867 +        }
   7.868 +        observedFrequencies[data[i]]++;
   7.869 +    }
   7.870 +
   7.871 +    // The histogram we created might be sparse - there might be gaps
   7.872 +    // between values. So we iterate through the histogram, making
   7.873 +    // sure that instead of undefined, gaps have 0 values.
   7.874 +    for (i = 0; i < observedFrequencies.length; i++) {
   7.875 +        if (observedFrequencies[i] === undefined) {
   7.876 +            observedFrequencies[i] = 0;
   7.877 +        }
   7.878 +    }
   7.879 +
   7.880 +    // Create an array holding a histogram of expected data given the
   7.881 +    // sample size and hypothesized distribution.
   7.882 +    for (k in hypothesizedDistribution) {
   7.883 +        if (k in observedFrequencies) {
   7.884 +            expectedFrequencies[+k] = hypothesizedDistribution[k] * data.length;
   7.885 +        }
   7.886 +    }
   7.887 +
   7.888 +    // Working backward through the expected frequencies, collapse classes
   7.889 +    // if less than three observations are expected for a class.
   7.890 +    // This transformation is applied to the observed frequencies as well.
   7.891 +    for (k = expectedFrequencies.length - 1; k >= 0; k--) {
   7.892 +        if (expectedFrequencies[k] < 3) {
   7.893 +            expectedFrequencies[k - 1] += expectedFrequencies[k];
   7.894 +            expectedFrequencies.pop();
   7.895 +
   7.896 +            observedFrequencies[k - 1] += observedFrequencies[k];
   7.897 +            observedFrequencies.pop();
   7.898 +        }
   7.899 +    }
   7.900 +
   7.901 +    // Iterate through the squared differences between observed & expected
   7.902 +    // frequencies, accumulating the `chiSquared` statistic.
   7.903 +    for (k = 0; k < observedFrequencies.length; k++) {
   7.904 +        chiSquared += Math.pow(
   7.905 +            observedFrequencies[k] - expectedFrequencies[k], 2) /
   7.906 +            expectedFrequencies[k];
   7.907 +    }
   7.908 +
   7.909 +    // Calculate degrees of freedom for this test and look it up in the
   7.910 +    // `chiSquaredDistributionTable` in order to
   7.911 +    // accept or reject the goodness-of-fit of the hypothesized distribution.
   7.912 +    degreesOfFreedom = observedFrequencies.length - c - 1;
   7.913 +    return chiSquaredDistributionTable[degreesOfFreedom][significance] < chiSquared;
   7.914 +}
   7.915 +
   7.916 +module.exports = chiSquaredGoodnessOfFit;
   7.917 +
   7.918 +},{"25":25,"6":6}],8:[function(require,module,exports){
   7.919 +'use strict';
   7.920 +/* @flow */
   7.921 +
   7.922 +/**
   7.923 + * Split an array into chunks of a specified size. This function
   7.924 + * has the same behavior as [PHP's array_chunk](http://php.net/manual/en/function.array-chunk.php)
   7.925 + * function, and thus will insert smaller-sized chunks at the end if
   7.926 + * the input size is not divisible by the chunk size.
   7.927 + *
   7.928 + * `sample` is expected to be an array, and `chunkSize` a number.
   7.929 + * The `sample` array can contain any kind of data.
   7.930 + *
   7.931 + * @param {Array} sample any array of values
   7.932 + * @param {number} chunkSize size of each output array
   7.933 + * @returns {Array<Array>} a chunked array
   7.934 + * @example
   7.935 + * chunk([1, 2, 3, 4, 5, 6], 2);
   7.936 + * // => [[1, 2], [3, 4], [5, 6]]
   7.937 + */
   7.938 +function chunk(sample/*:Array<any>*/, chunkSize/*:number*/)/*:?Array<Array<any>>*/ {
   7.939 +
   7.940 +    // a list of result chunks, as arrays in an array
   7.941 +    var output = [];
   7.942 +
   7.943 +    // `chunkSize` must be zero or higher - otherwise the loop below,
   7.944 +    // in which we call `start += chunkSize`, will loop infinitely.
   7.945 +    // So, we'll detect and throw in that case to indicate
   7.946 +    // invalid input.
   7.947 +    if (chunkSize <= 0) {
   7.948 +        throw new Error('chunk size must be a positive integer');
   7.949 +    }
   7.950 +
   7.951 +    // `start` is the index at which `.slice` will start selecting
   7.952 +    // new array elements
   7.953 +    for (var start = 0; start < sample.length; start += chunkSize) {
   7.954 +
   7.955 +        // for each chunk, slice that part of the array and add it
   7.956 +        // to the output. The `.slice` function does not change
   7.957 +        // the original array.
   7.958 +        output.push(sample.slice(start, start + chunkSize));
   7.959 +    }
   7.960 +    return output;
   7.961 +}
   7.962 +
   7.963 +module.exports = chunk;
   7.964 +
   7.965 +},{}],9:[function(require,module,exports){
   7.966 +'use strict';
   7.967 +/* @flow */
   7.968 +
   7.969 +var uniqueCountSorted = require(61),
   7.970 +    numericSort = require(34);
   7.971 +
   7.972 +/**
   7.973 + * Create a new column x row matrix.
   7.974 + *
   7.975 + * @private
   7.976 + * @param {number} columns
   7.977 + * @param {number} rows
   7.978 + * @return {Array<Array<number>>} matrix
   7.979 + * @example
   7.980 + * makeMatrix(10, 10);
   7.981 + */
   7.982 +function makeMatrix(columns, rows) {
   7.983 +    var matrix = [];
   7.984 +    for (var i = 0; i < columns; i++) {
   7.985 +        var column = [];
   7.986 +        for (var j = 0; j < rows; j++) {
   7.987 +            column.push(0);
   7.988 +        }
   7.989 +        matrix.push(column);
   7.990 +    }
   7.991 +    return matrix;
   7.992 +}
   7.993 +
   7.994 +/**
   7.995 + * Generates incrementally computed values based on the sums and sums of
   7.996 + * squares for the data array
   7.997 + *
   7.998 + * @private
   7.999 + * @param {number} j
  7.1000 + * @param {number} i
  7.1001 + * @param {Array<number>} sums
  7.1002 + * @param {Array<number>} sumsOfSquares
  7.1003 + * @return {number}
  7.1004 + * @example
  7.1005 + * ssq(0, 1, [-1, 0, 2], [1, 1, 5]);
  7.1006 + */
  7.1007 +function ssq(j, i, sums, sumsOfSquares) {
  7.1008 +    var sji; // s(j, i)
  7.1009 +    if (j > 0) {
  7.1010 +        var muji = (sums[i] - sums[j - 1]) / (i - j + 1); // mu(j, i)
  7.1011 +        sji = sumsOfSquares[i] - sumsOfSquares[j - 1] - (i - j + 1) * muji * muji;
  7.1012 +    } else {
  7.1013 +        sji = sumsOfSquares[i] - sums[i] * sums[i] / (i + 1);
  7.1014 +    }
  7.1015 +    if (sji < 0) {
  7.1016 +        return 0;
  7.1017 +    }
  7.1018 +    return sji;
  7.1019 +}
  7.1020 +
  7.1021 +/**
  7.1022 + * Function that recursively divides and conquers computations
  7.1023 + * for cluster j
  7.1024 + *
  7.1025 + * @private
  7.1026 + * @param {number} iMin Minimum index in cluster to be computed
  7.1027 + * @param {number} iMax Maximum index in cluster to be computed
  7.1028 + * @param {number} cluster Index of the cluster currently being computed
  7.1029 + * @param {Array<Array<number>>} matrix
  7.1030 + * @param {Array<Array<number>>} backtrackMatrix
  7.1031 + * @param {Array<number>} sums
  7.1032 + * @param {Array<number>} sumsOfSquares
  7.1033 + */
  7.1034 +function fillMatrixColumn(iMin, iMax, cluster, matrix, backtrackMatrix, sums, sumsOfSquares) {
  7.1035 +    if (iMin > iMax) {
  7.1036 +        return;
  7.1037 +    }
  7.1038 +
  7.1039 +    // Start at midpoint between iMin and iMax
  7.1040 +    var i = Math.floor((iMin + iMax) / 2);
  7.1041 +
  7.1042 +    matrix[cluster][i] = matrix[cluster - 1][i - 1];
  7.1043 +    backtrackMatrix[cluster][i] = i;
  7.1044 +
  7.1045 +    var jlow = cluster; // the lower end for j
  7.1046 +
  7.1047 +    if (iMin > cluster) {
  7.1048 +        jlow = Math.max(jlow, backtrackMatrix[cluster][iMin - 1] || 0);
  7.1049 +    }
  7.1050 +    jlow = Math.max(jlow, backtrackMatrix[cluster - 1][i] || 0);
  7.1051 +
  7.1052 +    var jhigh = i - 1; // the upper end for j
  7.1053 +    if (iMax < matrix.length - 1) {
  7.1054 +        jhigh = Math.min(jhigh, backtrackMatrix[cluster][iMax + 1] || 0);
  7.1055 +    }
  7.1056 +
  7.1057 +    var sji;
  7.1058 +    var sjlowi;
  7.1059 +    var ssqjlow;
  7.1060 +    var ssqj;
  7.1061 +    for (var j = jhigh; j >= jlow; --j) {
  7.1062 +        sji = ssq(j, i, sums, sumsOfSquares);
  7.1063 +
  7.1064 +        if (sji + matrix[cluster - 1][jlow - 1] >= matrix[cluster][i]) {
  7.1065 +            break;
  7.1066 +        }
  7.1067 +
  7.1068 +        // Examine the lower bound of the cluster border
  7.1069 +        sjlowi = ssq(jlow, i, sums, sumsOfSquares);
  7.1070 +
  7.1071 +        ssqjlow = sjlowi + matrix[cluster - 1][jlow - 1];
  7.1072 +
  7.1073 +        if (ssqjlow < matrix[cluster][i]) {
  7.1074 +            // Shrink the lower bound
  7.1075 +            matrix[cluster][i] = ssqjlow;
  7.1076 +            backtrackMatrix[cluster][i] = jlow;
  7.1077 +        }
  7.1078 +        jlow++;
  7.1079 +
  7.1080 +        ssqj = sji + matrix[cluster - 1][j - 1];
  7.1081 +        if (ssqj < matrix[cluster][i]) {
  7.1082 +            matrix[cluster][i] = ssqj;
  7.1083 +            backtrackMatrix[cluster][i] = j;
  7.1084 +        }
  7.1085 +    }
  7.1086 +
  7.1087 +    fillMatrixColumn(iMin, i - 1, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
  7.1088 +    fillMatrixColumn(i + 1, iMax, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
  7.1089 +}
  7.1090 +
  7.1091 +/**
  7.1092 + * Initializes the main matrices used in Ckmeans and kicks
  7.1093 + * off the divide and conquer cluster computation strategy
  7.1094 + *
  7.1095 + * @private
  7.1096 + * @param {Array<number>} data sorted array of values
  7.1097 + * @param {Array<Array<number>>} matrix
  7.1098 + * @param {Array<Array<number>>} backtrackMatrix
  7.1099 + */
  7.1100 +function fillMatrices(data, matrix, backtrackMatrix) {
  7.1101 +    var nValues = matrix[0].length;
  7.1102 +
  7.1103 +    // Shift values by the median to improve numeric stability
  7.1104 +    var shift = data[Math.floor(nValues / 2)];
  7.1105 +
  7.1106 +    // Cumulative sum and cumulative sum of squares for all values in data array
  7.1107 +    var sums = [];
  7.1108 +    var sumsOfSquares = [];
  7.1109 +
  7.1110 +    // Initialize first column in matrix & backtrackMatrix
  7.1111 +    for (var i = 0, shiftedValue; i < nValues; ++i) {
  7.1112 +        shiftedValue = data[i] - shift;
  7.1113 +        if (i === 0) {
  7.1114 +            sums.push(shiftedValue);
  7.1115 +            sumsOfSquares.push(shiftedValue * shiftedValue);
  7.1116 +        } else {
  7.1117 +            sums.push(sums[i - 1] + shiftedValue);
  7.1118 +            sumsOfSquares.push(sumsOfSquares[i - 1] + shiftedValue * shiftedValue);
  7.1119 +        }
  7.1120 +
  7.1121 +        // Initialize for cluster = 0
  7.1122 +        matrix[0][i] = ssq(0, i, sums, sumsOfSquares);
  7.1123 +        backtrackMatrix[0][i] = 0;
  7.1124 +    }
  7.1125 +
  7.1126 +    // Initialize the rest of the columns
  7.1127 +    var iMin;
  7.1128 +    for (var cluster = 1; cluster < matrix.length; ++cluster) {
  7.1129 +        if (cluster < matrix.length - 1) {
  7.1130 +            iMin = cluster;
  7.1131 +        } else {
  7.1132 +            // No need to compute matrix[K-1][0] ... matrix[K-1][N-2]
  7.1133 +            iMin = nValues - 1;
  7.1134 +        }
  7.1135 +
  7.1136 +        fillMatrixColumn(iMin, nValues - 1, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
  7.1137 +    }
  7.1138 +}
  7.1139 +
  7.1140 +/**
  7.1141 + * Ckmeans clustering is an improvement on heuristic-based clustering
  7.1142 + * approaches like Jenks. The algorithm was developed in
  7.1143 + * [Haizhou Wang and Mingzhou Song](http://journal.r-project.org/archive/2011-2/RJournal_2011-2_Wang+Song.pdf)
  7.1144 + * as a [dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming) approach
  7.1145 + * to the problem of clustering numeric data into groups with the least
  7.1146 + * within-group sum-of-squared-deviations.
  7.1147 + *
  7.1148 + * Minimizing the difference within groups - what Wang & Song refer to as
  7.1149 + * `withinss`, or within sum-of-squares, means that groups are optimally
  7.1150 + * homogenous within and the data is split into representative groups.
  7.1151 + * This is very useful for visualization, where you may want to represent
  7.1152 + * a continuous variable in discrete color or style groups. This function
  7.1153 + * can provide groups that emphasize differences between data.
  7.1154 + *
  7.1155 + * Being a dynamic approach, this algorithm is based on two matrices that
  7.1156 + * store incrementally-computed values for squared deviations and backtracking
  7.1157 + * indexes.
  7.1158 + *
  7.1159 + * This implementation is based on Ckmeans 3.4.6, which introduced a new divide
  7.1160 + * and conquer approach that improved runtime from O(kn^2) to O(kn log(n)).
  7.1161 + *
  7.1162 + * Unlike the [original implementation](https://cran.r-project.org/web/packages/Ckmeans.1d.dp/index.html),
  7.1163 + * this implementation does not include any code to automatically determine
  7.1164 + * the optimal number of clusters: this information needs to be explicitly
  7.1165 + * provided.
  7.1166 + *
  7.1167 + * ### References
  7.1168 + * _Ckmeans.1d.dp: Optimal k-means Clustering in One Dimension by Dynamic
  7.1169 + * Programming_ Haizhou Wang and Mingzhou Song ISSN 2073-4859
  7.1170 + *
  7.1171 + * from The R Journal Vol. 3/2, December 2011
  7.1172 + * @param {Array<number>} data input data, as an array of number values
  7.1173 + * @param {number} nClusters number of desired classes. This cannot be
  7.1174 + * greater than the number of values in the data array.
  7.1175 + * @returns {Array<Array<number>>} clustered input
  7.1176 + * @example
  7.1177 + * ckmeans([-1, 2, -1, 2, 4, 5, 6, -1, 2, -1], 3);
  7.1178 + * // The input, clustered into groups of similar numbers.
  7.1179 + * //= [[-1, -1, -1, -1], [2, 2, 2], [4, 5, 6]]);
  7.1180 + */
  7.1181 +function ckmeans(data/*: Array<number> */, nClusters/*: number */)/*: Array<Array<number>> */ {
  7.1182 +
  7.1183 +    if (nClusters > data.length) {
  7.1184 +        throw new Error('Cannot generate more classes than there are data values');
  7.1185 +    }
  7.1186 +
  7.1187 +    var sorted = numericSort(data),
  7.1188 +        // we'll use this as the maximum number of clusters
  7.1189 +        uniqueCount = uniqueCountSorted(sorted);
  7.1190 +
  7.1191 +    // if all of the input values are identical, there's one cluster
  7.1192 +    // with all of the input in it.
  7.1193 +    if (uniqueCount === 1) {
  7.1194 +        return [sorted];
  7.1195 +    }
  7.1196 +
  7.1197 +    // named 'S' originally
  7.1198 +    var matrix = makeMatrix(nClusters, sorted.length),
  7.1199 +        // named 'J' originally
  7.1200 +        backtrackMatrix = makeMatrix(nClusters, sorted.length);
  7.1201 +
  7.1202 +    // This is a dynamic programming way to solve the problem of minimizing
  7.1203 +    // within-cluster sum of squares. It's similar to linear regression
  7.1204 +    // in this way, and this calculation incrementally computes the
  7.1205 +    // sum of squares that are later read.
  7.1206 +    fillMatrices(sorted, matrix, backtrackMatrix);
  7.1207 +
  7.1208 +    // The real work of Ckmeans clustering happens in the matrix generation:
  7.1209 +    // the generated matrices encode all possible clustering combinations, and
  7.1210 +    // once they're generated we can solve for the best clustering groups
  7.1211 +    // very quickly.
  7.1212 +    var clusters = [],
  7.1213 +        clusterRight = backtrackMatrix[0].length - 1;
  7.1214 +
  7.1215 +    // Backtrack the clusters from the dynamic programming matrix. This
  7.1216 +    // starts at the bottom-right corner of the matrix (if the top-left is 0, 0),
  7.1217 +    // and moves the cluster target with the loop.
  7.1218 +    for (var cluster = backtrackMatrix.length - 1; cluster >= 0; cluster--) {
  7.1219 +
  7.1220 +        var clusterLeft = backtrackMatrix[cluster][clusterRight];
  7.1221 +
  7.1222 +        // fill the cluster from the sorted input by taking a slice of the
  7.1223 +        // array. the backtrack matrix makes this easy - it stores the
  7.1224 +        // indexes where the cluster should start and end.
  7.1225 +        clusters[cluster] = sorted.slice(clusterLeft, clusterRight + 1);
  7.1226 +
  7.1227 +        if (cluster > 0) {
  7.1228 +            clusterRight = clusterLeft - 1;
  7.1229 +        }
  7.1230 +    }
  7.1231 +
  7.1232 +    return clusters;
  7.1233 +}
  7.1234 +
  7.1235 +module.exports = ckmeans;
  7.1236 +
  7.1237 +},{"34":34,"61":61}],10:[function(require,module,exports){
  7.1238 +/* @flow */
  7.1239 +'use strict';
  7.1240 +/**
  7.1241 + * Implementation of Combinations
  7.1242 + * Combinations are unique subsets of a collection - in this case, k elements from a collection at a time.
  7.1243 + * https://en.wikipedia.org/wiki/Combination
  7.1244 + * @param {Array} elements any type of data
  7.1245 + * @param {int} k the number of objects in each group (without replacement)
  7.1246 + * @returns {Array<Array>} array of permutations
  7.1247 + * @example
  7.1248 + * combinations([1, 2, 3], 2); // => [[1,2], [1,3], [2,3]]
  7.1249 + */
  7.1250 +
  7.1251 +function combinations(elements /*: Array<any> */, k/*: number */) {
  7.1252 +    var i;
  7.1253 +    var subI;
  7.1254 +    var combinationList = [];
  7.1255 +    var subsetCombinations;
  7.1256 +    var next;
  7.1257 +
  7.1258 +    for (i = 0; i < elements.length; i++) {
  7.1259 +        if (k === 1) {
  7.1260 +            combinationList.push([elements[i]])
  7.1261 +        } else {
  7.1262 +            subsetCombinations = combinations(elements.slice( i + 1, elements.length ), k - 1);
  7.1263 +            for (subI = 0; subI < subsetCombinations.length; subI++) {
  7.1264 +                next = subsetCombinations[subI];
  7.1265 +                next.unshift(elements[i]);
  7.1266 +                combinationList.push(next);
  7.1267 +            }
  7.1268 +        }
  7.1269 +    }
  7.1270 +    return combinationList;
  7.1271 +}
  7.1272 +
  7.1273 +module.exports = combinations;
  7.1274 +
  7.1275 +},{}],11:[function(require,module,exports){
  7.1276 +/* @flow */
  7.1277 +'use strict';
  7.1278 +
  7.1279 +/**
  7.1280 + * Implementation of [Combinations](https://en.wikipedia.org/wiki/Combination) with replacement
  7.1281 + * Combinations are unique subsets of a collection - in this case, k elements from a collection at a time.
  7.1282 + * 'With replacement' means that a given element can be chosen multiple times.
  7.1283 + * Unlike permutation, order doesn't matter for combinations.
  7.1284 + * 
  7.1285 + * @param {Array} elements any type of data
  7.1286 + * @param {int} k the number of objects in each group (without replacement)
  7.1287 + * @returns {Array<Array>} array of permutations
  7.1288 + * @example
  7.1289 + * combinationsReplacement([1, 2], 2); // => [[1, 1], [1, 2], [2, 2]]
  7.1290 + */
  7.1291 +function combinationsReplacement(
  7.1292 +    elements /*: Array<any> */,
  7.1293 +    k /*: number */) {
  7.1294 +
  7.1295 +    var combinationList = [];
  7.1296 +
  7.1297 +    for (var i = 0; i < elements.length; i++) {
  7.1298 +        if (k === 1) {
  7.1299 +            // If we're requested to find only one element, we don't need
  7.1300 +            // to recurse: just push `elements[i]` onto the list of combinations.
  7.1301 +            combinationList.push([elements[i]])
  7.1302 +        } else {
  7.1303 +            // Otherwise, recursively find combinations, given `k - 1`. Note that
  7.1304 +            // we request `k - 1`, so if you were looking for k=3 combinations, we're
  7.1305 +            // requesting k=2. This -1 gets reversed in the for loop right after this
  7.1306 +            // code, since we concatenate `elements[i]` onto the selected combinations,
  7.1307 +            // bringing `k` back up to your requested level.
  7.1308 +            // This recursion may go many levels deep, since it only stops once
  7.1309 +            // k=1.
  7.1310 +            var subsetCombinations = combinationsReplacement(
  7.1311 +                elements.slice(i, elements.length),
  7.1312 +                k - 1);
  7.1313 +
  7.1314 +            for (var j = 0; j < subsetCombinations.length; j++) {
  7.1315 +                combinationList.push([elements[i]]
  7.1316 +                    .concat(subsetCombinations[j]));
  7.1317 +            }
  7.1318 +        }
  7.1319 +    }
  7.1320 +
  7.1321 +    return combinationList;
  7.1322 +}
  7.1323 +
  7.1324 +module.exports = combinationsReplacement;
  7.1325 +
  7.1326 +},{}],12:[function(require,module,exports){
  7.1327 +'use strict';
  7.1328 +/* @flow */
  7.1329 +
  7.1330 +var standardNormalTable = require(55);
  7.1331 +
  7.1332 +/**
  7.1333 + * **[Cumulative Standard Normal Probability](http://en.wikipedia.org/wiki/Standard_normal_table)**
  7.1334 + *
  7.1335 + * Since probability tables cannot be
  7.1336 + * printed for every normal distribution, as there are an infinite variety
  7.1337 + * of normal distributions, it is common practice to convert a normal to a
  7.1338 + * standard normal and then use the standard normal table to find probabilities.
  7.1339 + *
  7.1340 + * You can use `.5 + .5 * errorFunction(x / Math.sqrt(2))` to calculate the probability
  7.1341 + * instead of looking it up in a table.
  7.1342 + *
  7.1343 + * @param {number} z
  7.1344 + * @returns {number} cumulative standard normal probability
  7.1345 + */
  7.1346 +function cumulativeStdNormalProbability(z /*:number */)/*:number */ {
  7.1347 +
  7.1348 +    // Calculate the position of this value.
  7.1349 +    var absZ = Math.abs(z),
  7.1350 +        // Each row begins with a different
  7.1351 +        // significant digit: 0.5, 0.6, 0.7, and so on. Each value in the table
  7.1352 +        // corresponds to a range of 0.01 in the input values, so the value is
  7.1353 +        // multiplied by 100.
  7.1354 +        index = Math.min(Math.round(absZ * 100), standardNormalTable.length - 1);
  7.1355 +
  7.1356 +    // The index we calculate must be in the table as a positive value,
  7.1357 +    // but we still pay attention to whether the input is positive
  7.1358 +    // or negative, and flip the output value as a last step.
  7.1359 +    if (z >= 0) {
  7.1360 +        return standardNormalTable[index];
  7.1361 +    } else {
  7.1362 +        // due to floating-point arithmetic, values in the table with
  7.1363 +        // 4 significant figures can nevertheless end up as repeating
  7.1364 +        // fractions when they're computed here.
  7.1365 +        return +(1 - standardNormalTable[index]).toFixed(4);
  7.1366 +    }
  7.1367 +}
  7.1368 +
  7.1369 +module.exports = cumulativeStdNormalProbability;
  7.1370 +
  7.1371 +},{"55":55}],13:[function(require,module,exports){
  7.1372 +'use strict';
  7.1373 +/* @flow */
  7.1374 +
  7.1375 +/**
  7.1376 + * We use `ε`, epsilon, as a stopping criterion when we want to iterate
  7.1377 + * until we're "close enough". Epsilon is a very small number: for
  7.1378 + * simple statistics, that number is **0.0001**
  7.1379 + *
  7.1380 + * This is used in calculations like the binomialDistribution, in which
  7.1381 + * the process of finding a value is [iterative](https://en.wikipedia.org/wiki/Iterative_method):
  7.1382 + * it progresses until it is close enough.
  7.1383 + *
  7.1384 + * Below is an example of using epsilon in [gradient descent](https://en.wikipedia.org/wiki/Gradient_descent),
  7.1385 + * where we're trying to find a local minimum of a function's derivative,
  7.1386 + * given by the `fDerivative` method.
  7.1387 + *
  7.1388 + * @example
  7.1389 + * // From calculation, we expect that the local minimum occurs at x=9/4
  7.1390 + * var x_old = 0;
  7.1391 + * // The algorithm starts at x=6
  7.1392 + * var x_new = 6;
  7.1393 + * var stepSize = 0.01;
  7.1394 + *
  7.1395 + * function fDerivative(x) {
  7.1396 + *   return 4 * Math.pow(x, 3) - 9 * Math.pow(x, 2);
  7.1397 + * }
  7.1398 + *
  7.1399 + * // The loop runs until the difference between the previous
  7.1400 + * // value and the current value is smaller than epsilon - a rough
  7.1401 + * // meaure of 'close enough'
  7.1402 + * while (Math.abs(x_new - x_old) > ss.epsilon) {
  7.1403 + *   x_old = x_new;
  7.1404 + *   x_new = x_old - stepSize * fDerivative(x_old);
  7.1405 + * }
  7.1406 + *
  7.1407 + * console.log('Local minimum occurs at', x_new);
  7.1408 + */
  7.1409 +var epsilon = 0.0001;
  7.1410 +
  7.1411 +module.exports = epsilon;
  7.1412 +
  7.1413 +},{}],14:[function(require,module,exports){
  7.1414 +'use strict';
  7.1415 +/* @flow */
  7.1416 +
  7.1417 +var max = require(23),
  7.1418 +    min = require(29);
  7.1419 +
  7.1420 +/**
  7.1421 + * Given an array of data, this will find the extent of the
  7.1422 + * data and return an array of breaks that can be used
  7.1423 + * to categorize the data into a number of classes. The
  7.1424 + * returned array will always be 1 longer than the number of
  7.1425 + * classes because it includes the minimum value.
  7.1426 + *
  7.1427 + * @param {Array<number>} data input data, as an array of number values
  7.1428 + * @param {number} nClasses number of desired classes
  7.1429 + * @returns {Array<number>} array of class break positions
  7.1430 + * @example
  7.1431 + * equalIntervalBreaks([1, 2, 3, 4, 5, 6], 4); //= [1, 2.25, 3.5, 4.75, 6]
  7.1432 + */
  7.1433 +function equalIntervalBreaks(data/*: Array<number> */, nClasses/*:number*/)/*: Array<number> */ {
  7.1434 +
  7.1435 +    if (data.length <= 1) {
  7.1436 +        return data;
  7.1437 +    }
  7.1438 +
  7.1439 +    var theMin = min(data),
  7.1440 +        theMax = max(data); 
  7.1441 +
  7.1442 +    // the first break will always be the minimum value
  7.1443 +    // in the dataset
  7.1444 +    var breaks = [theMin];
  7.1445 +
  7.1446 +    // The size of each break is the full range of the data
  7.1447 +    // divided by the number of classes requested
  7.1448 +    var breakSize = (theMax - theMin) / nClasses;
  7.1449 +
  7.1450 +    // In the case of nClasses = 1, this loop won't run
  7.1451 +    // and the returned breaks will be [min, max]
  7.1452 +    for (var i = 1; i < nClasses; i++) {
  7.1453 +        breaks.push(breaks[0] + breakSize * i);
  7.1454 +    }
  7.1455 +
  7.1456 +    // the last break will always be the
  7.1457 +    // maximum.
  7.1458 +    breaks.push(theMax);
  7.1459 +
  7.1460 +    return breaks;
  7.1461 +}
  7.1462 +
  7.1463 +module.exports = equalIntervalBreaks;
  7.1464 +
  7.1465 +},{"23":23,"29":29}],15:[function(require,module,exports){
  7.1466 +'use strict';
  7.1467 +/* @flow */
  7.1468 +
  7.1469 +/**
  7.1470 + * **[Gaussian error function](http://en.wikipedia.org/wiki/Error_function)**
  7.1471 + *
  7.1472 + * The `errorFunction(x/(sd * Math.sqrt(2)))` is the probability that a value in a
  7.1473 + * normal distribution with standard deviation sd is within x of the mean.
  7.1474 + *
  7.1475 + * This function returns a numerical approximation to the exact value.
  7.1476 + *
  7.1477 + * @param {number} x input
  7.1478 + * @return {number} error estimation
  7.1479 + * @example
  7.1480 + * errorFunction(1).toFixed(2); // => '0.84'
  7.1481 + */
  7.1482 +function errorFunction(x/*: number */)/*: number */ {
  7.1483 +    var t = 1 / (1 + 0.5 * Math.abs(x));
  7.1484 +    var tau = t * Math.exp(-Math.pow(x, 2) -
  7.1485 +        1.26551223 +
  7.1486 +        1.00002368 * t +
  7.1487 +        0.37409196 * Math.pow(t, 2) +
  7.1488 +        0.09678418 * Math.pow(t, 3) -
  7.1489 +        0.18628806 * Math.pow(t, 4) +
  7.1490 +        0.27886807 * Math.pow(t, 5) -
  7.1491 +        1.13520398 * Math.pow(t, 6) +
  7.1492 +        1.48851587 * Math.pow(t, 7) -
  7.1493 +        0.82215223 * Math.pow(t, 8) +
  7.1494 +        0.17087277 * Math.pow(t, 9));
  7.1495 +    if (x >= 0) {
  7.1496 +        return 1 - tau;
  7.1497 +    } else {
  7.1498 +        return tau - 1;
  7.1499 +    }
  7.1500 +}
  7.1501 +
  7.1502 +module.exports = errorFunction;
  7.1503 +
  7.1504 +},{}],16:[function(require,module,exports){
  7.1505 +'use strict';
  7.1506 +/* @flow */
  7.1507 +
  7.1508 +/**
  7.1509 + * A [Factorial](https://en.wikipedia.org/wiki/Factorial), usually written n!, is the product of all positive
  7.1510 + * integers less than or equal to n. Often factorial is implemented
  7.1511 + * recursively, but this iterative approach is significantly faster
  7.1512 + * and simpler.
  7.1513 + *
  7.1514 + * @param {number} n input
  7.1515 + * @returns {number} factorial: n!
  7.1516 + * @example
  7.1517 + * factorial(5); // => 120
  7.1518 + */
  7.1519 +function factorial(n /*: number */)/*: number */ {
  7.1520 +
  7.1521 +    // factorial is mathematically undefined for negative numbers
  7.1522 +    if (n < 0) { return NaN; }
  7.1523 +
  7.1524 +    // typically you'll expand the factorial function going down, like
  7.1525 +    // 5! = 5 * 4 * 3 * 2 * 1. This is going in the opposite direction,
  7.1526 +    // counting from 2 up to the number in question, and since anything
  7.1527 +    // multiplied by 1 is itself, the loop only needs to start at 2.
  7.1528 +    var accumulator = 1;
  7.1529 +    for (var i = 2; i <= n; i++) {
  7.1530 +        // for each number up to and including the number `n`, multiply
  7.1531 +        // the accumulator my that number.
  7.1532 +        accumulator *= i;
  7.1533 +    }
  7.1534 +    return accumulator;
  7.1535 +}
  7.1536 +
  7.1537 +module.exports = factorial;
  7.1538 +
  7.1539 +},{}],17:[function(require,module,exports){
  7.1540 +'use strict';
  7.1541 +/* @flow */
  7.1542 +
  7.1543 +/**
  7.1544 + * The [Geometric Mean](https://en.wikipedia.org/wiki/Geometric_mean) is
  7.1545 + * a mean function that is more useful for numbers in different
  7.1546 + * ranges.
  7.1547 + *
  7.1548 + * This is the nth root of the input numbers multiplied by each other.
  7.1549 + *
  7.1550 + * The geometric mean is often useful for
  7.1551 + * **[proportional growth](https://en.wikipedia.org/wiki/Geometric_mean#Proportional_growth)**: given
  7.1552 + * growth rates for multiple years, like _80%, 16.66% and 42.85%_, a simple
  7.1553 + * mean will incorrectly estimate an average growth rate, whereas a geometric
  7.1554 + * mean will correctly estimate a growth rate that, over those years,
  7.1555 + * will yield the same end value.
  7.1556 + *
  7.1557 + * This runs on `O(n)`, linear time in respect to the array
  7.1558 + *
  7.1559 + * @param {Array<number>} x input array
  7.1560 + * @returns {number} geometric mean
  7.1561 + * @example
  7.1562 + * var growthRates = [1.80, 1.166666, 1.428571];
  7.1563 + * var averageGrowth = geometricMean(growthRates);
  7.1564 + * var averageGrowthRates = [averageGrowth, averageGrowth, averageGrowth];
  7.1565 + * var startingValue = 10;
  7.1566 + * var startingValueMean = 10;
  7.1567 + * growthRates.forEach(function(rate) {
  7.1568 + *   startingValue *= rate;
  7.1569 + * });
  7.1570 + * averageGrowthRates.forEach(function(rate) {
  7.1571 + *   startingValueMean *= rate;
  7.1572 + * });
  7.1573 + * startingValueMean === startingValue;
  7.1574 + */
  7.1575 +function geometricMean(x /*: Array<number> */) {
  7.1576 +    // The mean of no numbers is null
  7.1577 +    if (x.length === 0) { return undefined; }
  7.1578 +
  7.1579 +    // the starting value.
  7.1580 +    var value = 1;
  7.1581 +
  7.1582 +    for (var i = 0; i < x.length; i++) {
  7.1583 +        // the geometric mean is only valid for positive numbers
  7.1584 +        if (x[i] <= 0) { return undefined; }
  7.1585 +
  7.1586 +        // repeatedly multiply the value by each number
  7.1587 +        value *= x[i];
  7.1588 +    }
  7.1589 +
  7.1590 +    return Math.pow(value, 1 / x.length);
  7.1591 +}
  7.1592 +
  7.1593 +module.exports = geometricMean;
  7.1594 +
  7.1595 +},{}],18:[function(require,module,exports){
  7.1596 +'use strict';
  7.1597 +/* @flow */
  7.1598 +
  7.1599 +/**
  7.1600 + * The [Harmonic Mean](https://en.wikipedia.org/wiki/Harmonic_mean) is
  7.1601 + * a mean function typically used to find the average of rates.
  7.1602 + * This mean is calculated by taking the reciprocal of the arithmetic mean
  7.1603 + * of the reciprocals of the input numbers.
  7.1604 + *
  7.1605 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.1606 + * a method of finding a typical or central value of a set of numbers.
  7.1607 + *
  7.1608 + * This runs on `O(n)`, linear time in respect to the array.
  7.1609 + *
  7.1610 + * @param {Array<number>} x input
  7.1611 + * @returns {number} harmonic mean
  7.1612 + * @example
  7.1613 + * harmonicMean([2, 3]).toFixed(2) // => '2.40'
  7.1614 + */
  7.1615 +function harmonicMean(x /*: Array<number> */) {
  7.1616 +    // The mean of no numbers is null
  7.1617 +    if (x.length === 0) { return undefined; }
  7.1618 +
  7.1619 +    var reciprocalSum = 0;
  7.1620 +
  7.1621 +    for (var i = 0; i < x.length; i++) {
  7.1622 +        // the harmonic mean is only valid for positive numbers
  7.1623 +        if (x[i] <= 0) { return undefined; }
  7.1624 +
  7.1625 +        reciprocalSum += 1 / x[i];
  7.1626 +    }
  7.1627 +
  7.1628 +    // divide n by the the reciprocal sum
  7.1629 +    return x.length / reciprocalSum;
  7.1630 +}
  7.1631 +
  7.1632 +module.exports = harmonicMean;
  7.1633 +
  7.1634 +},{}],19:[function(require,module,exports){
  7.1635 +'use strict';
  7.1636 +/* @flow */
  7.1637 +
  7.1638 +var quantile = require(40);
  7.1639 +
  7.1640 +/**
  7.1641 + * The [Interquartile range](http://en.wikipedia.org/wiki/Interquartile_range) is
  7.1642 + * a measure of statistical dispersion, or how scattered, spread, or
  7.1643 + * concentrated a distribution is. It's computed as the difference between
  7.1644 + * the third quartile and first quartile.
  7.1645 + *
  7.1646 + * @param {Array<number>} sample
  7.1647 + * @returns {number} interquartile range: the span between lower and upper quartile,
  7.1648 + * 0.25 and 0.75
  7.1649 + * @example
  7.1650 + * interquartileRange([0, 1, 2, 3]); // => 2
  7.1651 + */
  7.1652 +function interquartileRange(sample/*: Array<number> */) {
  7.1653 +    // Interquartile range is the span between the upper quartile,
  7.1654 +    // at `0.75`, and lower quartile, `0.25`
  7.1655 +    var q1 = quantile(sample, 0.75),
  7.1656 +        q2 = quantile(sample, 0.25);
  7.1657 +
  7.1658 +    if (typeof q1 === 'number' && typeof q2 === 'number') {
  7.1659 +        return q1 - q2;
  7.1660 +    }
  7.1661 +}
  7.1662 +
  7.1663 +module.exports = interquartileRange;
  7.1664 +
  7.1665 +},{"40":40}],20:[function(require,module,exports){
  7.1666 +'use strict';
  7.1667 +/* @flow */
  7.1668 +
  7.1669 +/**
  7.1670 + * The Inverse [Gaussian error function](http://en.wikipedia.org/wiki/Error_function)
  7.1671 + * returns a numerical approximation to the value that would have caused
  7.1672 + * `errorFunction()` to return x.
  7.1673 + *
  7.1674 + * @param {number} x value of error function
  7.1675 + * @returns {number} estimated inverted value
  7.1676 + */
  7.1677 +function inverseErrorFunction(x/*: number */)/*: number */ {
  7.1678 +    var a = (8 * (Math.PI - 3)) / (3 * Math.PI * (4 - Math.PI));
  7.1679 +
  7.1680 +    var inv = Math.sqrt(Math.sqrt(
  7.1681 +        Math.pow(2 / (Math.PI * a) + Math.log(1 - x * x) / 2, 2) -
  7.1682 +        Math.log(1 - x * x) / a) -
  7.1683 +        (2 / (Math.PI * a) + Math.log(1 - x * x) / 2));
  7.1684 +
  7.1685 +    if (x >= 0) {
  7.1686 +        return inv;
  7.1687 +    } else {
  7.1688 +        return -inv;
  7.1689 +    }
  7.1690 +}
  7.1691 +
  7.1692 +module.exports = inverseErrorFunction;
  7.1693 +
  7.1694 +},{}],21:[function(require,module,exports){
  7.1695 +'use strict';
  7.1696 +/* @flow */
  7.1697 +
  7.1698 +/**
  7.1699 + * [Simple linear regression](http://en.wikipedia.org/wiki/Simple_linear_regression)
  7.1700 + * is a simple way to find a fitted line
  7.1701 + * between a set of coordinates. This algorithm finds the slope and y-intercept of a regression line
  7.1702 + * using the least sum of squares.
  7.1703 + *
  7.1704 + * @param {Array<Array<number>>} data an array of two-element of arrays,
  7.1705 + * like `[[0, 1], [2, 3]]`
  7.1706 + * @returns {Object} object containing slope and intersect of regression line
  7.1707 + * @example
  7.1708 + * linearRegression([[0, 0], [1, 1]]); // => { m: 1, b: 0 }
  7.1709 + */
  7.1710 +function linearRegression(data/*: Array<Array<number>> */)/*: { m: number, b: number } */ {
  7.1711 +
  7.1712 +    var m, b;
  7.1713 +
  7.1714 +    // Store data length in a local variable to reduce
  7.1715 +    // repeated object property lookups
  7.1716 +    var dataLength = data.length;
  7.1717 +
  7.1718 +    //if there's only one point, arbitrarily choose a slope of 0
  7.1719 +    //and a y-intercept of whatever the y of the initial point is
  7.1720 +    if (dataLength === 1) {
  7.1721 +        m = 0;
  7.1722 +        b = data[0][1];
  7.1723 +    } else {
  7.1724 +        // Initialize our sums and scope the `m` and `b`
  7.1725 +        // variables that define the line.
  7.1726 +        var sumX = 0, sumY = 0,
  7.1727 +            sumXX = 0, sumXY = 0;
  7.1728 +
  7.1729 +        // Use local variables to grab point values
  7.1730 +        // with minimal object property lookups
  7.1731 +        var point, x, y;
  7.1732 +
  7.1733 +        // Gather the sum of all x values, the sum of all
  7.1734 +        // y values, and the sum of x^2 and (x*y) for each
  7.1735 +        // value.
  7.1736 +        //
  7.1737 +        // In math notation, these would be SS_x, SS_y, SS_xx, and SS_xy
  7.1738 +        for (var i = 0; i < dataLength; i++) {
  7.1739 +            point = data[i];
  7.1740 +            x = point[0];
  7.1741 +            y = point[1];
  7.1742 +
  7.1743 +            sumX += x;
  7.1744 +            sumY += y;
  7.1745 +
  7.1746 +            sumXX += x * x;
  7.1747 +            sumXY += x * y;
  7.1748 +        }
  7.1749 +
  7.1750 +        // `m` is the slope of the regression line
  7.1751 +        m = ((dataLength * sumXY) - (sumX * sumY)) /
  7.1752 +            ((dataLength * sumXX) - (sumX * sumX));
  7.1753 +
  7.1754 +        // `b` is the y-intercept of the line.
  7.1755 +        b = (sumY / dataLength) - ((m * sumX) / dataLength);
  7.1756 +    }
  7.1757 +
  7.1758 +    // Return both values as an object.
  7.1759 +    return {
  7.1760 +        m: m,
  7.1761 +        b: b
  7.1762 +    };
  7.1763 +}
  7.1764 +
  7.1765 +
  7.1766 +module.exports = linearRegression;
  7.1767 +
  7.1768 +},{}],22:[function(require,module,exports){
  7.1769 +'use strict';
  7.1770 +/* @flow */
  7.1771 +
  7.1772 +/**
  7.1773 + * Given the output of `linearRegression`: an object
  7.1774 + * with `m` and `b` values indicating slope and intercept,
  7.1775 + * respectively, generate a line function that translates
  7.1776 + * x values into y values.
  7.1777 + *
  7.1778 + * @param {Object} mb object with `m` and `b` members, representing
  7.1779 + * slope and intersect of desired line
  7.1780 + * @returns {Function} method that computes y-value at any given
  7.1781 + * x-value on the line.
  7.1782 + * @example
  7.1783 + * var l = linearRegressionLine(linearRegression([[0, 0], [1, 1]]));
  7.1784 + * l(0) // = 0
  7.1785 + * l(2) // = 2
  7.1786 + * linearRegressionLine({ b: 0, m: 1 })(1); // => 1
  7.1787 + * linearRegressionLine({ b: 1, m: 1 })(1); // => 2
  7.1788 + */
  7.1789 +function linearRegressionLine(mb/*: { b: number, m: number }*/)/*: Function */ {
  7.1790 +    // Return a function that computes a `y` value for each
  7.1791 +    // x value it is given, based on the values of `b` and `a`
  7.1792 +    // that we just computed.
  7.1793 +    return function(x) {
  7.1794 +        return mb.b + (mb.m * x);
  7.1795 +    };
  7.1796 +}
  7.1797 +
  7.1798 +module.exports = linearRegressionLine;
  7.1799 +
  7.1800 +},{}],23:[function(require,module,exports){
  7.1801 +'use strict';
  7.1802 +/* @flow */
  7.1803 +
  7.1804 +/**
  7.1805 + * This computes the maximum number in an array.
  7.1806 + *
  7.1807 + * This runs on `O(n)`, linear time in respect to the array
  7.1808 + *
  7.1809 + * @param {Array<number>} x input
  7.1810 + * @returns {number} maximum value
  7.1811 + * @example
  7.1812 + * max([1, 2, 3, 4]);
  7.1813 + * // => 4
  7.1814 + */
  7.1815 +function max(x /*: Array<number> */) /*:number*/ {
  7.1816 +    var value;
  7.1817 +    for (var i = 0; i < x.length; i++) {
  7.1818 +        // On the first iteration of this loop, max is
  7.1819 +        // NaN and is thus made the maximum element in the array
  7.1820 +        if (value === undefined || x[i] > value) {
  7.1821 +            value = x[i];
  7.1822 +        }
  7.1823 +    }
  7.1824 +    if (value === undefined) {
  7.1825 +        return NaN;
  7.1826 +    }
  7.1827 +    return value;
  7.1828 +}
  7.1829 +
  7.1830 +module.exports = max;
  7.1831 +
  7.1832 +},{}],24:[function(require,module,exports){
  7.1833 +'use strict';
  7.1834 +/* @flow */
  7.1835 +
  7.1836 +/**
  7.1837 + * The maximum is the highest number in the array. With a sorted array,
  7.1838 + * the last element in the array is always the largest, so this calculation
  7.1839 + * can be done in one step, or constant time.
  7.1840 + *
  7.1841 + * @param {Array<number>} x input
  7.1842 + * @returns {number} maximum value
  7.1843 + * @example
  7.1844 + * maxSorted([-100, -10, 1, 2, 5]); // => 5
  7.1845 + */
  7.1846 +function maxSorted(x /*: Array<number> */)/*:number*/ {
  7.1847 +    return x[x.length - 1];
  7.1848 +}
  7.1849 +
  7.1850 +module.exports = maxSorted;
  7.1851 +
  7.1852 +},{}],25:[function(require,module,exports){
  7.1853 +'use strict';
  7.1854 +/* @flow */
  7.1855 +
  7.1856 +var sum = require(56);
  7.1857 +
  7.1858 +/**
  7.1859 + * The mean, _also known as average_,
  7.1860 + * is the sum of all values over the number of values.
  7.1861 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.1862 + * a method of finding a typical or central value of a set of numbers.
  7.1863 + *
  7.1864 + * This runs on `O(n)`, linear time in respect to the array
  7.1865 + *
  7.1866 + * @param {Array<number>} x input values
  7.1867 + * @returns {number} mean
  7.1868 + * @example
  7.1869 + * mean([0, 10]); // => 5
  7.1870 + */
  7.1871 +function mean(x /*: Array<number> */)/*:number*/ {
  7.1872 +    // The mean of no numbers is null
  7.1873 +    if (x.length === 0) { return NaN; }
  7.1874 +
  7.1875 +    return sum(x) / x.length;
  7.1876 +}
  7.1877 +
  7.1878 +module.exports = mean;
  7.1879 +
  7.1880 +},{"56":56}],26:[function(require,module,exports){
  7.1881 +'use strict';
  7.1882 +/* @flow */
  7.1883 +
  7.1884 +var quantile = require(40);
  7.1885 +
  7.1886 +/**
  7.1887 + * The [median](http://en.wikipedia.org/wiki/Median) is
  7.1888 + * the middle number of a list. This is often a good indicator of 'the middle'
  7.1889 + * when there are outliers that skew the `mean()` value.
  7.1890 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.1891 + * a method of finding a typical or central value of a set of numbers.
  7.1892 + *
  7.1893 + * The median isn't necessarily one of the elements in the list: the value
  7.1894 + * can be the average of two elements if the list has an even length
  7.1895 + * and the two central values are different.
  7.1896 + *
  7.1897 + * @param {Array<number>} x input
  7.1898 + * @returns {number} median value
  7.1899 + * @example
  7.1900 + * median([10, 2, 5, 100, 2, 1]); // => 3.5
  7.1901 + */
  7.1902 +function median(x /*: Array<number> */)/*:number*/ {
  7.1903 +    return +quantile(x, 0.5);
  7.1904 +}
  7.1905 +
  7.1906 +module.exports = median;
  7.1907 +
  7.1908 +},{"40":40}],27:[function(require,module,exports){
  7.1909 +'use strict';
  7.1910 +/* @flow */
  7.1911 +
  7.1912 +var median = require(26);
  7.1913 +
  7.1914 +/**
  7.1915 + * The [Median Absolute Deviation](http://en.wikipedia.org/wiki/Median_absolute_deviation) is
  7.1916 + * a robust measure of statistical
  7.1917 + * dispersion. It is more resilient to outliers than the standard deviation.
  7.1918 + *
  7.1919 + * @param {Array<number>} x input array
  7.1920 + * @returns {number} median absolute deviation
  7.1921 + * @example
  7.1922 + * medianAbsoluteDeviation([1, 1, 2, 2, 4, 6, 9]); // => 1
  7.1923 + */
  7.1924 +function medianAbsoluteDeviation(x /*: Array<number> */) {
  7.1925 +    // The mad of nothing is null
  7.1926 +    var medianValue = median(x),
  7.1927 +        medianAbsoluteDeviations = [];
  7.1928 +
  7.1929 +    // Make a list of absolute deviations from the median
  7.1930 +    for (var i = 0; i < x.length; i++) {
  7.1931 +        medianAbsoluteDeviations.push(Math.abs(x[i] - medianValue));
  7.1932 +    }
  7.1933 +
  7.1934 +    // Find the median value of that list
  7.1935 +    return median(medianAbsoluteDeviations);
  7.1936 +}
  7.1937 +
  7.1938 +module.exports = medianAbsoluteDeviation;
  7.1939 +
  7.1940 +},{"26":26}],28:[function(require,module,exports){
  7.1941 +'use strict';
  7.1942 +/* @flow */
  7.1943 +
  7.1944 +var quantileSorted = require(41);
  7.1945 +
  7.1946 +/**
  7.1947 + * The [median](http://en.wikipedia.org/wiki/Median) is
  7.1948 + * the middle number of a list. This is often a good indicator of 'the middle'
  7.1949 + * when there are outliers that skew the `mean()` value.
  7.1950 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.1951 + * a method of finding a typical or central value of a set of numbers.
  7.1952 + *
  7.1953 + * The median isn't necessarily one of the elements in the list: the value
  7.1954 + * can be the average of two elements if the list has an even length
  7.1955 + * and the two central values are different.
  7.1956 + *
  7.1957 + * @param {Array<number>} sorted input
  7.1958 + * @returns {number} median value
  7.1959 + * @example
  7.1960 + * medianSorted([10, 2, 5, 100, 2, 1]); // => 52.5
  7.1961 + */
  7.1962 +function medianSorted(sorted /*: Array<number> */)/*:number*/ {
  7.1963 +    return quantileSorted(sorted, 0.5);
  7.1964 +}
  7.1965 +
  7.1966 +module.exports = medianSorted;
  7.1967 +
  7.1968 +},{"41":41}],29:[function(require,module,exports){
  7.1969 +'use strict';
  7.1970 +/* @flow */
  7.1971 +
  7.1972 +/**
  7.1973 + * The min is the lowest number in the array. This runs on `O(n)`, linear time in respect to the array
  7.1974 + *
  7.1975 + * @param {Array<number>} x input
  7.1976 + * @returns {number} minimum value
  7.1977 + * @example
  7.1978 + * min([1, 5, -10, 100, 2]); // => -10
  7.1979 + */
  7.1980 +function min(x /*: Array<number> */)/*:number*/ {
  7.1981 +    var value;
  7.1982 +    for (var i = 0; i < x.length; i++) {
  7.1983 +        // On the first iteration of this loop, min is
  7.1984 +        // NaN and is thus made the minimum element in the array
  7.1985 +        if (value === undefined || x[i] < value) {
  7.1986 +            value = x[i];
  7.1987 +        }
  7.1988 +    }
  7.1989 +    if (value === undefined) {
  7.1990 +        return NaN;
  7.1991 +    }
  7.1992 +    return value;
  7.1993 +}
  7.1994 +
  7.1995 +module.exports = min;
  7.1996 +
  7.1997 +},{}],30:[function(require,module,exports){
  7.1998 +'use strict';
  7.1999 +/* @flow */
  7.2000 +
  7.2001 +/**
  7.2002 + * The minimum is the lowest number in the array. With a sorted array,
  7.2003 + * the first element in the array is always the smallest, so this calculation
  7.2004 + * can be done in one step, or constant time.
  7.2005 + *
  7.2006 + * @param {Array<number>} x input
  7.2007 + * @returns {number} minimum value
  7.2008 + * @example
  7.2009 + * minSorted([-100, -10, 1, 2, 5]); // => -100
  7.2010 + */
  7.2011 +function minSorted(x /*: Array<number> */)/*:number*/ {
  7.2012 +    return x[0];
  7.2013 +}
  7.2014 +
  7.2015 +module.exports = minSorted;
  7.2016 +
  7.2017 +},{}],31:[function(require,module,exports){
  7.2018 +'use strict';
  7.2019 +/* @flow */
  7.2020 +
  7.2021 +/**
  7.2022 + * **Mixin** simple_statistics to a single Array instance if provided
  7.2023 + * or the Array native object if not. This is an optional
  7.2024 + * feature that lets you treat simple_statistics as a native feature
  7.2025 + * of Javascript.
  7.2026 + *
  7.2027 + * @param {Object} ss simple statistics
  7.2028 + * @param {Array} [array=] a single array instance which will be augmented
  7.2029 + * with the extra methods. If omitted, mixin will apply to all arrays
  7.2030 + * by changing the global `Array.prototype`.
  7.2031 + * @returns {*} the extended Array, or Array.prototype if no object
  7.2032 + * is given.
  7.2033 + *
  7.2034 + * @example
  7.2035 + * var myNumbers = [1, 2, 3];
  7.2036 + * mixin(ss, myNumbers);
  7.2037 + * console.log(myNumbers.sum()); // 6
  7.2038 + */
  7.2039 +function mixin(ss /*: Object */, array /*: ?Array<any> */)/*: any */ {
  7.2040 +    var support = !!(Object.defineProperty && Object.defineProperties);
  7.2041 +    // Coverage testing will never test this error.
  7.2042 +    /* istanbul ignore next */
  7.2043 +    if (!support) {
  7.2044 +        throw new Error('without defineProperty, simple-statistics cannot be mixed in');
  7.2045 +    }
  7.2046 +
  7.2047 +    // only methods which work on basic arrays in a single step
  7.2048 +    // are supported
  7.2049 +    var arrayMethods = ['median', 'standardDeviation', 'sum', 'product',
  7.2050 +        'sampleSkewness',
  7.2051 +        'mean', 'min', 'max', 'quantile', 'geometricMean',
  7.2052 +        'harmonicMean', 'root_mean_square'];
  7.2053 +
  7.2054 +    // create a closure with a method name so that a reference
  7.2055 +    // like `arrayMethods[i]` doesn't follow the loop increment
  7.2056 +    function wrap(method) {
  7.2057 +        return function() {
  7.2058 +            // cast any arguments into an array, since they're
  7.2059 +            // natively objects
  7.2060 +            var args = Array.prototype.slice.apply(arguments);
  7.2061 +            // make the first argument the array itself
  7.2062 +            args.unshift(this);
  7.2063 +            // return the result of the ss method
  7.2064 +            return ss[method].apply(ss, args);
  7.2065 +        };
  7.2066 +    }
  7.2067 +
  7.2068 +    // select object to extend
  7.2069 +    var extending;
  7.2070 +    if (array) {
  7.2071 +        // create a shallow copy of the array so that our internal
  7.2072 +        // operations do not change it by reference
  7.2073 +        extending = array.slice();
  7.2074 +    } else {
  7.2075 +        extending = Array.prototype;
  7.2076 +    }
  7.2077 +
  7.2078 +    // for each array function, define a function that gets
  7.2079 +    // the array as the first argument.
  7.2080 +    // We use [defineProperty](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty)
  7.2081 +    // because it allows these properties to be non-enumerable:
  7.2082 +    // `for (var in x)` loops will not run into problems with this
  7.2083 +    // implementation.
  7.2084 +    for (var i = 0; i < arrayMethods.length; i++) {
  7.2085 +        Object.defineProperty(extending, arrayMethods[i], {
  7.2086 +            value: wrap(arrayMethods[i]),
  7.2087 +            configurable: true,
  7.2088 +            enumerable: false,
  7.2089 +            writable: true
  7.2090 +        });
  7.2091 +    }
  7.2092 +
  7.2093 +    return extending;
  7.2094 +}
  7.2095 +
  7.2096 +module.exports = mixin;
  7.2097 +
  7.2098 +},{}],32:[function(require,module,exports){
  7.2099 +'use strict';
  7.2100 +/* @flow */
  7.2101 +
  7.2102 +var numericSort = require(34),
  7.2103 +    modeSorted = require(33);
  7.2104 +
  7.2105 +/**
  7.2106 + * The [mode](http://bit.ly/W5K4Yt) is the number that appears in a list the highest number of times.
  7.2107 + * There can be multiple modes in a list: in the event of a tie, this
  7.2108 + * algorithm will return the most recently seen mode.
  7.2109 + *
  7.2110 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.2111 + * a method of finding a typical or central value of a set of numbers.
  7.2112 + *
  7.2113 + * This runs on `O(nlog(n))` because it needs to sort the array internally
  7.2114 + * before running an `O(n)` search to find the mode.
  7.2115 + *
  7.2116 + * @param {Array<number>} x input
  7.2117 + * @returns {number} mode
  7.2118 + * @example
  7.2119 + * mode([0, 0, 1]); // => 0
  7.2120 + */
  7.2121 +function mode(x /*: Array<number> */)/*:number*/ {
  7.2122 +    // Sorting the array lets us iterate through it below and be sure
  7.2123 +    // that every time we see a new number it's new and we'll never
  7.2124 +    // see the same number twice
  7.2125 +    return modeSorted(numericSort(x));
  7.2126 +}
  7.2127 +
  7.2128 +module.exports = mode;
  7.2129 +
  7.2130 +},{"33":33,"34":34}],33:[function(require,module,exports){
  7.2131 +'use strict';
  7.2132 +/* @flow */
  7.2133 +
  7.2134 +/**
  7.2135 + * The [mode](http://bit.ly/W5K4Yt) is the number that appears in a list the highest number of times.
  7.2136 + * There can be multiple modes in a list: in the event of a tie, this
  7.2137 + * algorithm will return the most recently seen mode.
  7.2138 + *
  7.2139 + * This is a [measure of central tendency](https://en.wikipedia.org/wiki/Central_tendency):
  7.2140 + * a method of finding a typical or central value of a set of numbers.
  7.2141 + *
  7.2142 + * This runs in `O(n)` because the input is sorted.
  7.2143 + *
  7.2144 + * @param {Array<number>} sorted input
  7.2145 + * @returns {number} mode
  7.2146 + * @example
  7.2147 + * modeSorted([0, 0, 1]); // => 0
  7.2148 + */
  7.2149 +function modeSorted(sorted /*: Array<number> */)/*:number*/ {
  7.2150 +
  7.2151 +    // Handle edge cases:
  7.2152 +    // The mode of an empty list is NaN
  7.2153 +    if (sorted.length === 0) { return NaN; }
  7.2154 +    else if (sorted.length === 1) { return sorted[0]; }
  7.2155 +
  7.2156 +    // This assumes it is dealing with an array of size > 1, since size
  7.2157 +    // 0 and 1 are handled immediately. Hence it starts at index 1 in the
  7.2158 +    // array.
  7.2159 +    var last = sorted[0],
  7.2160 +        // store the mode as we find new modes
  7.2161 +        value = NaN,
  7.2162 +        // store how many times we've seen the mode
  7.2163 +        maxSeen = 0,
  7.2164 +        // how many times the current candidate for the mode
  7.2165 +        // has been seen
  7.2166 +        seenThis = 1;
  7.2167 +
  7.2168 +    // end at sorted.length + 1 to fix the case in which the mode is
  7.2169 +    // the highest number that occurs in the sequence. the last iteration
  7.2170 +    // compares sorted[i], which is undefined, to the highest number
  7.2171 +    // in the series
  7.2172 +    for (var i = 1; i < sorted.length + 1; i++) {
  7.2173 +        // we're seeing a new number pass by
  7.2174 +        if (sorted[i] !== last) {
  7.2175 +            // the last number is the new mode since we saw it more
  7.2176 +            // often than the old one
  7.2177 +            if (seenThis > maxSeen) {
  7.2178 +                maxSeen = seenThis;
  7.2179 +                value = last;
  7.2180 +            }
  7.2181 +            seenThis = 1;
  7.2182 +            last = sorted[i];
  7.2183 +        // if this isn't a new number, it's one more occurrence of
  7.2184 +        // the potential mode
  7.2185 +        } else { seenThis++; }
  7.2186 +    }
  7.2187 +    return value;
  7.2188 +}
  7.2189 +
  7.2190 +module.exports = modeSorted;
  7.2191 +
  7.2192 +},{}],34:[function(require,module,exports){
  7.2193 +'use strict';
  7.2194 +/* @flow */
  7.2195 +
  7.2196 +/**
  7.2197 + * Sort an array of numbers by their numeric value, ensuring that the
  7.2198 + * array is not changed in place.
  7.2199 + *
  7.2200 + * This is necessary because the default behavior of .sort
  7.2201 + * in JavaScript is to sort arrays as string values
  7.2202 + *
  7.2203 + *     [1, 10, 12, 102, 20].sort()
  7.2204 + *     // output
  7.2205 + *     [1, 10, 102, 12, 20]
  7.2206 + *
  7.2207 + * @param {Array<number>} array input array
  7.2208 + * @return {Array<number>} sorted array
  7.2209 + * @private
  7.2210 + * @example
  7.2211 + * numericSort([3, 2, 1]) // => [1, 2, 3]
  7.2212 + */
  7.2213 +function numericSort(array /*: Array<number> */) /*: Array<number> */ {
  7.2214 +    return array
  7.2215 +        // ensure the array is not changed in-place
  7.2216 +        .slice()
  7.2217 +        // comparator function that treats input as numeric
  7.2218 +        .sort(function(a, b) {
  7.2219 +            return a - b;
  7.2220 +        });
  7.2221 +}
  7.2222 +
  7.2223 +module.exports = numericSort;
  7.2224 +
  7.2225 +},{}],35:[function(require,module,exports){
  7.2226 +'use strict';
  7.2227 +/* @flow */
  7.2228 +
  7.2229 +/**
  7.2230 + * This is a single-layer [Perceptron Classifier](http://en.wikipedia.org/wiki/Perceptron) that takes
  7.2231 + * arrays of numbers and predicts whether they should be classified
  7.2232 + * as either 0 or 1 (negative or positive examples).
  7.2233 + * @class
  7.2234 + * @example
  7.2235 + * // Create the model
  7.2236 + * var p = new PerceptronModel();
  7.2237 + * // Train the model with input with a diagonal boundary.
  7.2238 + * for (var i = 0; i < 5; i++) {
  7.2239 + *     p.train([1, 1], 1);
  7.2240 + *     p.train([0, 1], 0);
  7.2241 + *     p.train([1, 0], 0);
  7.2242 + *     p.train([0, 0], 0);
  7.2243 + * }
  7.2244 + * p.predict([0, 0]); // 0
  7.2245 + * p.predict([0, 1]); // 0
  7.2246 + * p.predict([1, 0]); // 0
  7.2247 + * p.predict([1, 1]); // 1
  7.2248 + */
  7.2249 +function PerceptronModel() {
  7.2250 +    // The weights, or coefficients of the model;
  7.2251 +    // weights are only populated when training with data.
  7.2252 +    this.weights = [];
  7.2253 +    // The bias term, or intercept; it is also a weight but
  7.2254 +    // it's stored separately for convenience as it is always
  7.2255 +    // multiplied by one.
  7.2256 +    this.bias = 0;
  7.2257 +}
  7.2258 +
  7.2259 +/**
  7.2260 + * **Predict**: Use an array of features with the weight array and bias
  7.2261 + * to predict whether an example is labeled 0 or 1.
  7.2262 + *
  7.2263 + * @param {Array<number>} features an array of features as numbers
  7.2264 + * @returns {number} 1 if the score is over 0, otherwise 0
  7.2265 + */
  7.2266 +PerceptronModel.prototype.predict = function(features) {
  7.2267 +
  7.2268 +    // Only predict if previously trained
  7.2269 +    // on the same size feature array(s).
  7.2270 +    if (features.length !== this.weights.length) { return null; }
  7.2271 +
  7.2272 +    // Calculate the sum of features times weights,
  7.2273 +    // with the bias added (implicitly times one).
  7.2274 +    var score = 0;
  7.2275 +    for (var i = 0; i < this.weights.length; i++) {
  7.2276 +        score += this.weights[i] * features[i];
  7.2277 +    }
  7.2278 +    score += this.bias;
  7.2279 +
  7.2280 +    // Classify as 1 if the score is over 0, otherwise 0.
  7.2281 +    if (score > 0) {
  7.2282 +        return 1;
  7.2283 +    } else {
  7.2284 +        return 0;
  7.2285 +    }
  7.2286 +};
  7.2287 +
  7.2288 +/**
  7.2289 + * **Train** the classifier with a new example, which is
  7.2290 + * a numeric array of features and a 0 or 1 label.
  7.2291 + *
  7.2292 + * @param {Array<number>} features an array of features as numbers
  7.2293 + * @param {number} label either 0 or 1
  7.2294 + * @returns {PerceptronModel} this
  7.2295 + */
  7.2296 +PerceptronModel.prototype.train = function(features, label) {
  7.2297 +    // Require that only labels of 0 or 1 are considered.
  7.2298 +    if (label !== 0 && label !== 1) { return null; }
  7.2299 +    // The length of the feature array determines
  7.2300 +    // the length of the weight array.
  7.2301 +    // The perceptron will continue learning as long as
  7.2302 +    // it keeps seeing feature arrays of the same length.
  7.2303 +    // When it sees a new data shape, it initializes.
  7.2304 +    if (features.length !== this.weights.length) {
  7.2305 +        this.weights = features;
  7.2306 +        this.bias = 1;
  7.2307 +    }
  7.2308 +    // Make a prediction based on current weights.
  7.2309 +    var prediction = this.predict(features);
  7.2310 +    // Update the weights if the prediction is wrong.
  7.2311 +    if (prediction !== label) {
  7.2312 +        var gradient = label - prediction;
  7.2313 +        for (var i = 0; i < this.weights.length; i++) {
  7.2314 +            this.weights[i] += gradient * features[i];
  7.2315 +        }
  7.2316 +        this.bias += gradient;
  7.2317 +    }
  7.2318 +    return this;
  7.2319 +};
  7.2320 +
  7.2321 +module.exports = PerceptronModel;
  7.2322 +
  7.2323 +},{}],36:[function(require,module,exports){
  7.2324 +/* @flow */
  7.2325 +
  7.2326 +'use strict';
  7.2327 +
  7.2328 +/**
  7.2329 + * Implementation of [Heap's Algorithm](https://en.wikipedia.org/wiki/Heap%27s_algorithm)
  7.2330 + * for generating permutations.
  7.2331 + *
  7.2332 + * @param {Array} elements any type of data
  7.2333 + * @returns {Array<Array>} array of permutations
  7.2334 + */
  7.2335 +function permutationsHeap/*:: <T> */(elements /*: Array<T> */)/*: Array<Array<T>> */ {
  7.2336 +    var indexes = new Array(elements.length);
  7.2337 +    var permutations = [elements.slice()];
  7.2338 +
  7.2339 +    for (var i = 0; i < elements.length; i++) {
  7.2340 +        indexes[i] = 0;
  7.2341 +    }
  7.2342 +
  7.2343 +    for (i = 0; i < elements.length;) {
  7.2344 +        if (indexes[i] < i) {
  7.2345 +
  7.2346 +            // At odd indexes, swap from indexes[i] instead
  7.2347 +            // of from the beginning of the array
  7.2348 +            var swapFrom = 0;
  7.2349 +            if (i % 2 !== 0) {
  7.2350 +                swapFrom = indexes[i];
  7.2351 +            }
  7.2352 +
  7.2353 +            // swap between swapFrom and i, using
  7.2354 +            // a temporary variable as storage.
  7.2355 +            var temp = elements[swapFrom];
  7.2356 +            elements[swapFrom] = elements[i];
  7.2357 +            elements[i] = temp;
  7.2358 +
  7.2359 +            permutations.push(elements.slice());
  7.2360 +            indexes[i]++;
  7.2361 +            i = 0;
  7.2362 +
  7.2363 +        } else {
  7.2364 +            indexes[i] = 0;
  7.2365 +            i++;
  7.2366 +        }
  7.2367 +    }
  7.2368 +
  7.2369 +    return permutations;
  7.2370 +}
  7.2371 +
  7.2372 +module.exports = permutationsHeap;
  7.2373 +
  7.2374 +},{}],37:[function(require,module,exports){
  7.2375 +'use strict';
  7.2376 +/* @flow */
  7.2377 +
  7.2378 +var epsilon = require(13);
  7.2379 +var factorial = require(16);
  7.2380 +
  7.2381 +/**
  7.2382 + * The [Poisson Distribution](http://en.wikipedia.org/wiki/Poisson_distribution)
  7.2383 + * is a discrete probability distribution that expresses the probability
  7.2384 + * of a given number of events occurring in a fixed interval of time
  7.2385 + * and/or space if these events occur with a known average rate and
  7.2386 + * independently of the time since the last event.
  7.2387 + *
  7.2388 + * The Poisson Distribution is characterized by the strictly positive
  7.2389 + * mean arrival or occurrence rate, `λ`.
  7.2390 + *
  7.2391 + * @param {number} lambda location poisson distribution
  7.2392 + * @returns {number} value of poisson distribution at that point
  7.2393 + */
  7.2394 +function poissonDistribution(lambda/*: number */) {
  7.2395 +    // Check that lambda is strictly positive
  7.2396 +    if (lambda <= 0) { return undefined; }
  7.2397 +
  7.2398 +    // our current place in the distribution
  7.2399 +    var x = 0,
  7.2400 +        // and we keep track of the current cumulative probability, in
  7.2401 +        // order to know when to stop calculating chances.
  7.2402 +        cumulativeProbability = 0,
  7.2403 +        // the calculated cells to be returned
  7.2404 +        cells = {};
  7.2405 +
  7.2406 +    // This algorithm iterates through each potential outcome,
  7.2407 +    // until the `cumulativeProbability` is very close to 1, at
  7.2408 +    // which point we've defined the vast majority of outcomes
  7.2409 +    do {
  7.2410 +        // a [probability mass function](https://en.wikipedia.org/wiki/Probability_mass_function)
  7.2411 +        cells[x] = (Math.pow(Math.E, -lambda) * Math.pow(lambda, x)) / factorial(x);
  7.2412 +        cumulativeProbability += cells[x];
  7.2413 +        x++;
  7.2414 +    // when the cumulativeProbability is nearly 1, we've calculated
  7.2415 +    // the useful range of this distribution
  7.2416 +    } while (cumulativeProbability < 1 - epsilon);
  7.2417 +
  7.2418 +    return cells;
  7.2419 +}
  7.2420 +
  7.2421 +module.exports = poissonDistribution;
  7.2422 +
  7.2423 +},{"13":13,"16":16}],38:[function(require,module,exports){
  7.2424 +'use strict';
  7.2425 +/* @flow */
  7.2426 +
  7.2427 +var epsilon = require(13);
  7.2428 +var inverseErrorFunction = require(20);
  7.2429 +
  7.2430 +/**
  7.2431 + * The [Probit](http://en.wikipedia.org/wiki/Probit)
  7.2432 + * is the inverse of cumulativeStdNormalProbability(),
  7.2433 + * and is also known as the normal quantile function.
  7.2434 + *
  7.2435 + * It returns the number of standard deviations from the mean
  7.2436 + * where the p'th quantile of values can be found in a normal distribution.
  7.2437 + * So, for example, probit(0.5 + 0.6827/2) ≈ 1 because 68.27% of values are
  7.2438 + * normally found within 1 standard deviation above or below the mean.
  7.2439 + *
  7.2440 + * @param {number} p
  7.2441 + * @returns {number} probit
  7.2442 + */
  7.2443 +function probit(p /*: number */)/*: number */ {
  7.2444 +    if (p === 0) {
  7.2445 +        p = epsilon;
  7.2446 +    } else if (p >= 1) {
  7.2447 +        p = 1 - epsilon;
  7.2448 +    }
  7.2449 +    return Math.sqrt(2) * inverseErrorFunction(2 * p - 1);
  7.2450 +}
  7.2451 +
  7.2452 +module.exports = probit;
  7.2453 +
  7.2454 +},{"13":13,"20":20}],39:[function(require,module,exports){
  7.2455 +'use strict';
  7.2456 +/* @flow */
  7.2457 +
  7.2458 +/**
  7.2459 + * The [product](https://en.wikipedia.org/wiki/Product_(mathematics)) of an array
  7.2460 + * is the result of multiplying all numbers together, starting using one as the multiplicative identity.
  7.2461 + *
  7.2462 + * This runs on `O(n)`, linear time in respect to the array
  7.2463 + *
  7.2464 + * @param {Array<number>} x input
  7.2465 + * @return {number} product of all input numbers
  7.2466 + * @example
  7.2467 + * product([1, 2, 3, 4]); // => 24
  7.2468 + */
  7.2469 +function product(x/*: Array<number> */)/*: number */ {
  7.2470 +    var value = 1;
  7.2471 +    for (var i = 0; i < x.length; i++) {
  7.2472 +        value *= x[i];
  7.2473 +    }
  7.2474 +    return value;
  7.2475 +}
  7.2476 +
  7.2477 +module.exports = product;
  7.2478 +
  7.2479 +},{}],40:[function(require,module,exports){
  7.2480 +'use strict';
  7.2481 +/* @flow */
  7.2482 +
  7.2483 +var quantileSorted = require(41);
  7.2484 +var quickselect = require(42);
  7.2485 +
  7.2486 +/**
  7.2487 + * The [quantile](https://en.wikipedia.org/wiki/Quantile):
  7.2488 + * this is a population quantile, since we assume to know the entire
  7.2489 + * dataset in this library. This is an implementation of the
  7.2490 + * [Quantiles of a Population](http://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population)
  7.2491 + * algorithm from wikipedia.
  7.2492 + *
  7.2493 + * Sample is a one-dimensional array of numbers,
  7.2494 + * and p is either a decimal number from 0 to 1 or an array of decimal
  7.2495 + * numbers from 0 to 1.
  7.2496 + * In terms of a k/q quantile, p = k/q - it's just dealing with fractions or dealing
  7.2497 + * with decimal values.
  7.2498 + * When p is an array, the result of the function is also an array containing the appropriate
  7.2499 + * quantiles in input order
  7.2500 + *
  7.2501 + * @param {Array<number>} sample a sample from the population
  7.2502 + * @param {number} p the desired quantile, as a number between 0 and 1
  7.2503 + * @returns {number} quantile
  7.2504 + * @example
  7.2505 + * quantile([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 0.5); // => 9
  7.2506 + */
  7.2507 +function quantile(sample /*: Array<number> */, p /*: Array<number> | number */) {
  7.2508 +    var copy = sample.slice();
  7.2509 +
  7.2510 +    if (Array.isArray(p)) {
  7.2511 +        // rearrange elements so that each element corresponding to a requested
  7.2512 +        // quantile is on a place it would be if the array was fully sorted
  7.2513 +        multiQuantileSelect(copy, p);
  7.2514 +        // Initialize the result array
  7.2515 +        var results = [];
  7.2516 +        // For each requested quantile
  7.2517 +        for (var i = 0; i < p.length; i++) {
  7.2518 +            results[i] = quantileSorted(copy, p[i]);
  7.2519 +        }
  7.2520 +        return results;
  7.2521 +    } else {
  7.2522 +        var idx = quantileIndex(copy.length, p);
  7.2523 +        quantileSelect(copy, idx, 0, copy.length - 1);
  7.2524 +        return quantileSorted(copy, p);
  7.2525 +    }
  7.2526 +}
  7.2527 +
  7.2528 +function quantileSelect(arr, k, left, right) {
  7.2529 +    if (k % 1 === 0) {
  7.2530 +        quickselect(arr, k, left, right);
  7.2531 +    } else {
  7.2532 +        k = Math.floor(k);
  7.2533 +        quickselect(arr, k, left, right);
  7.2534 +        quickselect(arr, k + 1, k + 1, right);
  7.2535 +    }
  7.2536 +}
  7.2537 +
  7.2538 +function multiQuantileSelect(arr, p) {
  7.2539 +    var indices = [0];
  7.2540 +    for (var i = 0; i < p.length; i++) {
  7.2541 +        indices.push(quantileIndex(arr.length, p[i]));
  7.2542 +    }
  7.2543 +    indices.push(arr.length - 1);
  7.2544 +    indices.sort(compare);
  7.2545 +
  7.2546 +    var stack = [0, indices.length - 1];
  7.2547 +
  7.2548 +    while (stack.length) {
  7.2549 +        var r = Math.ceil(stack.pop());
  7.2550 +        var l = Math.floor(stack.pop());
  7.2551 +        if (r - l <= 1) continue;
  7.2552 +
  7.2553 +        var m = Math.floor((l + r) / 2);
  7.2554 +        quantileSelect(arr, indices[m], indices[l], indices[r]);
  7.2555 +
  7.2556 +        stack.push(l, m, m, r);
  7.2557 +    }
  7.2558 +}
  7.2559 +
  7.2560 +function compare(a, b) {
  7.2561 +    return a - b;
  7.2562 +}
  7.2563 +
  7.2564 +function quantileIndex(len /*: number */, p /*: number */)/*:number*/ {
  7.2565 +    var idx = len * p;
  7.2566 +    if (p === 1) {
  7.2567 +        // If p is 1, directly return the last index
  7.2568 +        return len - 1;
  7.2569 +    } else if (p === 0) {
  7.2570 +        // If p is 0, directly return the first index
  7.2571 +        return 0;
  7.2572 +    } else if (idx % 1 !== 0) {
  7.2573 +        // If index is not integer, return the next index in array
  7.2574 +        return Math.ceil(idx) - 1;
  7.2575 +    } else if (len % 2 === 0) {
  7.2576 +        // If the list has even-length, we'll return the middle of two indices
  7.2577 +        // around quantile to indicate that we need an average value of the two
  7.2578 +        return idx - 0.5;
  7.2579 +    } else {
  7.2580 +        // Finally, in the simple case of an integer index
  7.2581 +        // with an odd-length list, return the index
  7.2582 +        return idx;
  7.2583 +    }
  7.2584 +}
  7.2585 +
  7.2586 +module.exports = quantile;
  7.2587 +
  7.2588 +},{"41":41,"42":42}],41:[function(require,module,exports){
  7.2589 +'use strict';
  7.2590 +/* @flow */
  7.2591 +
  7.2592 +/**
  7.2593 + * This is the internal implementation of quantiles: when you know
  7.2594 + * that the order is sorted, you don't need to re-sort it, and the computations
  7.2595 + * are faster.
  7.2596 + *
  7.2597 + * @param {Array<number>} sample input data
  7.2598 + * @param {number} p desired quantile: a number between 0 to 1, inclusive
  7.2599 + * @returns {number} quantile value
  7.2600 + * @example
  7.2601 + * quantileSorted([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], 0.5); // => 9
  7.2602 + */
  7.2603 +function quantileSorted(sample /*: Array<number> */, p /*: number */)/*:number*/ {
  7.2604 +    var idx = sample.length * p;
  7.2605 +    if (p < 0 || p > 1) {
  7.2606 +        return NaN;
  7.2607 +    } else if (p === 1) {
  7.2608 +        // If p is 1, directly return the last element
  7.2609 +        return sample[sample.length - 1];
  7.2610 +    } else if (p === 0) {
  7.2611 +        // If p is 0, directly return the first element
  7.2612 +        return sample[0];
  7.2613 +    } else if (idx % 1 !== 0) {
  7.2614 +        // If p is not integer, return the next element in array
  7.2615 +        return sample[Math.ceil(idx) - 1];
  7.2616 +    } else if (sample.length % 2 === 0) {
  7.2617 +        // If the list has even-length, we'll take the average of this number
  7.2618 +        // and the next value, if there is one
  7.2619 +        return (sample[idx - 1] + sample[idx]) / 2;
  7.2620 +    } else {
  7.2621 +        // Finally, in the simple case of an integer value
  7.2622 +        // with an odd-length list, return the sample value at the index.
  7.2623 +        return sample[idx];
  7.2624 +    }
  7.2625 +}
  7.2626 +
  7.2627 +module.exports = quantileSorted;
  7.2628 +
  7.2629 +},{}],42:[function(require,module,exports){
  7.2630 +'use strict';
  7.2631 +/* @flow */
  7.2632 +
  7.2633 +module.exports = quickselect;
  7.2634 +
  7.2635 +/**
  7.2636 + * Rearrange items in `arr` so that all items in `[left, k]` range are the smallest.
  7.2637 + * The `k`-th element will have the `(k - left + 1)`-th smallest value in `[left, right]`.
  7.2638 + *
  7.2639 + * Implements Floyd-Rivest selection algorithm https://en.wikipedia.org/wiki/Floyd-Rivest_algorithm
  7.2640 + *
  7.2641 + * @private
  7.2642 + * @param {Array<number>} arr input array
  7.2643 + * @param {number} k pivot index
  7.2644 + * @param {number} left left index
  7.2645 + * @param {number} right right index
  7.2646 + * @returns {undefined}
  7.2647 + * @example
  7.2648 + * var arr = [65, 28, 59, 33, 21, 56, 22, 95, 50, 12, 90, 53, 28, 77, 39];
  7.2649 + * quickselect(arr, 8);
  7.2650 + * // = [39, 28, 28, 33, 21, 12, 22, 50, 53, 56, 59, 65, 90, 77, 95]
  7.2651 + */
  7.2652 +function quickselect(arr /*: Array<number> */, k /*: number */, left /*: number */, right /*: number */) {
  7.2653 +    left = left || 0;
  7.2654 +    right = right || (arr.length - 1);
  7.2655 +
  7.2656 +    while (right > left) {
  7.2657 +        // 600 and 0.5 are arbitrary constants chosen in the original paper to minimize execution time
  7.2658 +        if (right - left > 600) {
  7.2659 +            var n = right - left + 1;
  7.2660 +            var m = k - left + 1;
  7.2661 +            var z = Math.log(n);
  7.2662 +            var s = 0.5 * Math.exp(2 * z / 3);
  7.2663 +            var sd = 0.5 * Math.sqrt(z * s * (n - s) / n);
  7.2664 +            if (m - n / 2 < 0) sd *= -1;
  7.2665 +            var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
  7.2666 +            var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
  7.2667 +            quickselect(arr, k, newLeft, newRight);
  7.2668 +        }
  7.2669 +
  7.2670 +        var t = arr[k];
  7.2671 +        var i = left;
  7.2672 +        var j = right;
  7.2673 +
  7.2674 +        swap(arr, left, k);
  7.2675 +        if (arr[right] > t) swap(arr, left, right);
  7.2676 +
  7.2677 +        while (i < j) {
  7.2678 +            swap(arr, i, j);
  7.2679 +            i++;
  7.2680 +            j--;
  7.2681 +            while (arr[i] < t) i++;
  7.2682 +            while (arr[j] > t) j--;
  7.2683 +        }
  7.2684 +
  7.2685 +        if (arr[left] === t) swap(arr, left, j);
  7.2686 +        else {
  7.2687 +            j++;
  7.2688 +            swap(arr, j, right);
  7.2689 +        }
  7.2690 +
  7.2691 +        if (j <= k) left = j + 1;
  7.2692 +        if (k <= j) right = j - 1;
  7.2693 +    }
  7.2694 +}
  7.2695 +
  7.2696 +function swap(arr, i, j) {
  7.2697 +    var tmp = arr[i];
  7.2698 +    arr[i] = arr[j];
  7.2699 +    arr[j] = tmp;
  7.2700 +}
  7.2701 +
  7.2702 +},{}],43:[function(require,module,exports){
  7.2703 +'use strict';
  7.2704 +/* @flow */
  7.2705 +
  7.2706 +/**
  7.2707 + * The [R Squared](http://en.wikipedia.org/wiki/Coefficient_of_determination)
  7.2708 + * value of data compared with a function `f`
  7.2709 + * is the sum of the squared differences between the prediction
  7.2710 + * and the actual value.
  7.2711 + *
  7.2712 + * @param {Array<Array<number>>} data input data: this should be doubly-nested
  7.2713 + * @param {Function} func function called on `[i][0]` values within the dataset
  7.2714 + * @returns {number} r-squared value
  7.2715 + * @example
  7.2716 + * var samples = [[0, 0], [1, 1]];
  7.2717 + * var regressionLine = linearRegressionLine(linearRegression(samples));
  7.2718 + * rSquared(samples, regressionLine); // = 1 this line is a perfect fit
  7.2719 + */
  7.2720 +function rSquared(data /*: Array<Array<number>> */, func /*: Function */) /*: number */ {
  7.2721 +    if (data.length < 2) { return 1; }
  7.2722 +
  7.2723 +    // Compute the average y value for the actual
  7.2724 +    // data set in order to compute the
  7.2725 +    // _total sum of squares_
  7.2726 +    var sum = 0, average;
  7.2727 +    for (var i = 0; i < data.length; i++) {
  7.2728 +        sum += data[i][1];
  7.2729 +    }
  7.2730 +    average = sum / data.length;
  7.2731 +
  7.2732 +    // Compute the total sum of squares - the
  7.2733 +    // squared difference between each point
  7.2734 +    // and the average of all points.
  7.2735 +    var sumOfSquares = 0;
  7.2736 +    for (var j = 0; j < data.length; j++) {
  7.2737 +        sumOfSquares += Math.pow(average - data[j][1], 2);
  7.2738 +    }
  7.2739 +
  7.2740 +    // Finally estimate the error: the squared
  7.2741 +    // difference between the estimate and the actual data
  7.2742 +    // value at each point.
  7.2743 +    var err = 0;
  7.2744 +    for (var k = 0; k < data.length; k++) {
  7.2745 +        err += Math.pow(data[k][1] - func(data[k][0]), 2);
  7.2746 +    }
  7.2747 +
  7.2748 +    // As the error grows larger, its ratio to the
  7.2749 +    // sum of squares increases and the r squared
  7.2750 +    // value grows lower.
  7.2751 +    return 1 - err / sumOfSquares;
  7.2752 +}
  7.2753 +
  7.2754 +module.exports = rSquared;
  7.2755 +
  7.2756 +},{}],44:[function(require,module,exports){
  7.2757 +'use strict';
  7.2758 +/* @flow */
  7.2759 +
  7.2760 +/**
  7.2761 + * The Root Mean Square (RMS) is
  7.2762 + * a mean function used as a measure of the magnitude of a set
  7.2763 + * of numbers, regardless of their sign.
  7.2764 + * This is the square root of the mean of the squares of the
  7.2765 + * input numbers.
  7.2766 + * This runs on `O(n)`, linear time in respect to the array
  7.2767 + *
  7.2768 + * @param {Array<number>} x input
  7.2769 + * @returns {number} root mean square
  7.2770 + * @example
  7.2771 + * rootMeanSquare([-1, 1, -1, 1]); // => 1
  7.2772 + */
  7.2773 +function rootMeanSquare(x /*: Array<number> */)/*:number*/ {
  7.2774 +    if (x.length === 0) { return NaN; }
  7.2775 +
  7.2776 +    var sumOfSquares = 0;
  7.2777 +    for (var i = 0; i < x.length; i++) {
  7.2778 +        sumOfSquares += Math.pow(x[i], 2);
  7.2779 +    }
  7.2780 +
  7.2781 +    return Math.sqrt(sumOfSquares / x.length);
  7.2782 +}
  7.2783 +
  7.2784 +module.exports = rootMeanSquare;
  7.2785 +
  7.2786 +},{}],45:[function(require,module,exports){
  7.2787 +'use strict';
  7.2788 +/* @flow */
  7.2789 +
  7.2790 +var shuffle = require(51);
  7.2791 +
  7.2792 +/**
  7.2793 + * Create a [simple random sample](http://en.wikipedia.org/wiki/Simple_random_sample)
  7.2794 + * from a given array of `n` elements.
  7.2795 + *
  7.2796 + * The sampled values will be in any order, not necessarily the order
  7.2797 + * they appear in the input.
  7.2798 + *
  7.2799 + * @param {Array} array input array. can contain any type
  7.2800 + * @param {number} n count of how many elements to take
  7.2801 + * @param {Function} [randomSource=Math.random] an optional source of entropy
  7.2802 + * instead of Math.random
  7.2803 + * @return {Array} subset of n elements in original array
  7.2804 + * @example
  7.2805 + * var values = [1, 2, 4, 5, 6, 7, 8, 9];
  7.2806 + * sample(values, 3); // returns 3 random values, like [2, 5, 8];
  7.2807 + */
  7.2808 +function sample/*:: <T> */(
  7.2809 +    array /*: Array<T> */,
  7.2810 +    n /*: number */,
  7.2811 +    randomSource /*: Function */) /*: Array<T> */ {
  7.2812 +    // shuffle the original array using a fisher-yates shuffle
  7.2813 +    var shuffled = shuffle(array, randomSource);
  7.2814 +
  7.2815 +    // and then return a subset of it - the first `n` elements.
  7.2816 +    return shuffled.slice(0, n);
  7.2817 +}
  7.2818 +
  7.2819 +module.exports = sample;
  7.2820 +
  7.2821 +},{"51":51}],46:[function(require,module,exports){
  7.2822 +'use strict';
  7.2823 +/* @flow */
  7.2824 +
  7.2825 +var sampleCovariance = require(47);
  7.2826 +var sampleStandardDeviation = require(49);
  7.2827 +
  7.2828 +/**
  7.2829 + * The [correlation](http://en.wikipedia.org/wiki/Correlation_and_dependence) is
  7.2830 + * a measure of how correlated two datasets are, between -1 and 1
  7.2831 + *
  7.2832 + * @param {Array<number>} x first input
  7.2833 + * @param {Array<number>} y second input
  7.2834 + * @returns {number} sample correlation
  7.2835 + * @example
  7.2836 + * sampleCorrelation([1, 2, 3, 4, 5, 6], [2, 2, 3, 4, 5, 60]).toFixed(2);
  7.2837 + * // => '0.69'
  7.2838 + */
  7.2839 +function sampleCorrelation(x/*: Array<number> */, y/*: Array<number> */)/*:number*/ {
  7.2840 +    var cov = sampleCovariance(x, y),
  7.2841 +        xstd = sampleStandardDeviation(x),
  7.2842 +        ystd = sampleStandardDeviation(y);
  7.2843 +
  7.2844 +    return cov / xstd / ystd;
  7.2845 +}
  7.2846 +
  7.2847 +module.exports = sampleCorrelation;
  7.2848 +
  7.2849 +},{"47":47,"49":49}],47:[function(require,module,exports){
  7.2850 +'use strict';
  7.2851 +/* @flow */
  7.2852 +
  7.2853 +var mean = require(25);
  7.2854 +
  7.2855 +/**
  7.2856 + * [Sample covariance](https://en.wikipedia.org/wiki/Sample_mean_and_sampleCovariance) of two datasets:
  7.2857 + * how much do the two datasets move together?
  7.2858 + * x and y are two datasets, represented as arrays of numbers.
  7.2859 + *
  7.2860 + * @param {Array<number>} x first input
  7.2861 + * @param {Array<number>} y second input
  7.2862 + * @returns {number} sample covariance
  7.2863 + * @example
  7.2864 + * sampleCovariance([1, 2, 3, 4, 5, 6], [6, 5, 4, 3, 2, 1]); // => -3.5
  7.2865 + */
  7.2866 +function sampleCovariance(x /*:Array<number>*/, y /*:Array<number>*/)/*:number*/ {
  7.2867 +
  7.2868 +    // The two datasets must have the same length which must be more than 1
  7.2869 +    if (x.length <= 1 || x.length !== y.length) {
  7.2870 +        return NaN;
  7.2871 +    }
  7.2872 +
  7.2873 +    // determine the mean of each dataset so that we can judge each
  7.2874 +    // value of the dataset fairly as the difference from the mean. this
  7.2875 +    // way, if one dataset is [1, 2, 3] and [2, 3, 4], their covariance
  7.2876 +    // does not suffer because of the difference in absolute values
  7.2877 +    var xmean = mean(x),
  7.2878 +        ymean = mean(y),
  7.2879 +        sum = 0;
  7.2880 +
  7.2881 +    // for each pair of values, the covariance increases when their
  7.2882 +    // difference from the mean is associated - if both are well above
  7.2883 +    // or if both are well below
  7.2884 +    // the mean, the covariance increases significantly.
  7.2885 +    for (var i = 0; i < x.length; i++) {
  7.2886 +        sum += (x[i] - xmean) * (y[i] - ymean);
  7.2887 +    }
  7.2888 +
  7.2889 +    // this is Bessels' Correction: an adjustment made to sample statistics
  7.2890 +    // that allows for the reduced degree of freedom entailed in calculating
  7.2891 +    // values from samples rather than complete populations.
  7.2892 +    var besselsCorrection = x.length - 1;
  7.2893 +
  7.2894 +    // the covariance is weighted by the length of the datasets.
  7.2895 +    return sum / besselsCorrection;
  7.2896 +}
  7.2897 +
  7.2898 +module.exports = sampleCovariance;
  7.2899 +
  7.2900 +},{"25":25}],48:[function(require,module,exports){
  7.2901 +'use strict';
  7.2902 +/* @flow */
  7.2903 +
  7.2904 +var sumNthPowerDeviations = require(57);
  7.2905 +var sampleStandardDeviation = require(49);
  7.2906 +
  7.2907 +/**
  7.2908 + * [Skewness](http://en.wikipedia.org/wiki/Skewness) is
  7.2909 + * a measure of the extent to which a probability distribution of a
  7.2910 + * real-valued random variable "leans" to one side of the mean.
  7.2911 + * The skewness value can be positive or negative, or even undefined.
  7.2912 + *
  7.2913 + * Implementation is based on the adjusted Fisher-Pearson standardized
  7.2914 + * moment coefficient, which is the version found in Excel and several
  7.2915 + * statistical packages including Minitab, SAS and SPSS.
  7.2916 + *
  7.2917 + * @param {Array<number>} x input
  7.2918 + * @returns {number} sample skewness
  7.2919 + * @example
  7.2920 + * sampleSkewness([2, 4, 6, 3, 1]); // => 0.590128656384365
  7.2921 + */
  7.2922 +function sampleSkewness(x /*: Array<number> */)/*:number*/ {
  7.2923 +    // The skewness of less than three arguments is null
  7.2924 +    var theSampleStandardDeviation = sampleStandardDeviation(x);
  7.2925 +
  7.2926 +    if (isNaN(theSampleStandardDeviation) || x.length < 3) {
  7.2927 +        return NaN;
  7.2928 +    }
  7.2929 +
  7.2930 +    var n = x.length,
  7.2931 +        cubedS = Math.pow(theSampleStandardDeviation, 3),
  7.2932 +        sumCubedDeviations = sumNthPowerDeviations(x, 3);
  7.2933 +
  7.2934 +    return n * sumCubedDeviations / ((n - 1) * (n - 2) * cubedS);
  7.2935 +}
  7.2936 +
  7.2937 +module.exports = sampleSkewness;
  7.2938 +
  7.2939 +},{"49":49,"57":57}],49:[function(require,module,exports){
  7.2940 +'use strict';
  7.2941 +/* @flow */
  7.2942 +
  7.2943 +var sampleVariance = require(50);
  7.2944 +
  7.2945 +/**
  7.2946 + * The [standard deviation](http://en.wikipedia.org/wiki/Standard_deviation)
  7.2947 + * is the square root of the variance.
  7.2948 + *
  7.2949 + * @param {Array<number>} x input array
  7.2950 + * @returns {number} sample standard deviation
  7.2951 + * @example
  7.2952 + * sampleStandardDeviation([2, 4, 4, 4, 5, 5, 7, 9]).toFixed(2);
  7.2953 + * // => '2.14'
  7.2954 + */
  7.2955 +function sampleStandardDeviation(x/*:Array<number>*/)/*:number*/ {
  7.2956 +    // The standard deviation of no numbers is null
  7.2957 +    var sampleVarianceX = sampleVariance(x);
  7.2958 +    if (isNaN(sampleVarianceX)) { return NaN; }
  7.2959 +    return Math.sqrt(sampleVarianceX);
  7.2960 +}
  7.2961 +
  7.2962 +module.exports = sampleStandardDeviation;
  7.2963 +
  7.2964 +},{"50":50}],50:[function(require,module,exports){
  7.2965 +'use strict';
  7.2966 +/* @flow */
  7.2967 +
  7.2968 +var sumNthPowerDeviations = require(57);
  7.2969 +
  7.2970 +/*
  7.2971 + * The [sample variance](https://en.wikipedia.org/wiki/Variance#Sample_variance)
  7.2972 + * is the sum of squared deviations from the mean. The sample variance
  7.2973 + * is distinguished from the variance by the usage of [Bessel's Correction](https://en.wikipedia.org/wiki/Bessel's_correction):
  7.2974 + * instead of dividing the sum of squared deviations by the length of the input,
  7.2975 + * it is divided by the length minus one. This corrects the bias in estimating
  7.2976 + * a value from a set that you don't know if full.
  7.2977 + *
  7.2978 + * References:
  7.2979 + * * [Wolfram MathWorld on Sample Variance](http://mathworld.wolfram.com/SampleVariance.html)
  7.2980 + *
  7.2981 + * @param {Array<number>} x input array
  7.2982 + * @return {number} sample variance
  7.2983 + * @example
  7.2984 + * sampleVariance([1, 2, 3, 4, 5]); // => 2.5
  7.2985 + */
  7.2986 +function sampleVariance(x /*: Array<number> */)/*:number*/ {
  7.2987 +    // The variance of no numbers is null
  7.2988 +    if (x.length <= 1) { return NaN; }
  7.2989 +
  7.2990 +    var sumSquaredDeviationsValue = sumNthPowerDeviations(x, 2);
  7.2991 +
  7.2992 +    // this is Bessels' Correction: an adjustment made to sample statistics
  7.2993 +    // that allows for the reduced degree of freedom entailed in calculating
  7.2994 +    // values from samples rather than complete populations.
  7.2995 +    var besselsCorrection = x.length - 1;
  7.2996 +
  7.2997 +    // Find the mean value of that list
  7.2998 +    return sumSquaredDeviationsValue / besselsCorrection;
  7.2999 +}
  7.3000 +
  7.3001 +module.exports = sampleVariance;
  7.3002 +
  7.3003 +},{"57":57}],51:[function(require,module,exports){
  7.3004 +'use strict';
  7.3005 +/* @flow */
  7.3006 +
  7.3007 +var shuffleInPlace = require(52);
  7.3008 +
  7.3009 +/*
  7.3010 + * A [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)
  7.3011 + * is a fast way to create a random permutation of a finite set. This is
  7.3012 + * a function around `shuffle_in_place` that adds the guarantee that
  7.3013 + * it will not modify its input.
  7.3014 + *
  7.3015 + * @param {Array} sample an array of any kind of element
  7.3016 + * @param {Function} [randomSource=Math.random] an optional entropy source
  7.3017 + * @return {Array} shuffled version of input
  7.3018 + * @example
  7.3019 + * var shuffled = shuffle([1, 2, 3, 4]);
  7.3020 + * shuffled; // = [2, 3, 1, 4] or any other random permutation
  7.3021 + */
  7.3022 +function shuffle/*::<T>*/(sample/*:Array<T>*/, randomSource/*:Function*/) {
  7.3023 +    // slice the original array so that it is not modified
  7.3024 +    sample = sample.slice();
  7.3025 +
  7.3026 +    // and then shuffle that shallow-copied array, in place
  7.3027 +    return shuffleInPlace(sample.slice(), randomSource);
  7.3028 +}
  7.3029 +
  7.3030 +module.exports = shuffle;
  7.3031 +
  7.3032 +},{"52":52}],52:[function(require,module,exports){
  7.3033 +'use strict';
  7.3034 +/* @flow */
  7.3035 +
  7.3036 +/*
  7.3037 + * A [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)
  7.3038 + * in-place - which means that it **will change the order of the original
  7.3039 + * array by reference**.
  7.3040 + *
  7.3041 + * This is an algorithm that generates a random [permutation](https://en.wikipedia.org/wiki/Permutation)
  7.3042 + * of a set.
  7.3043 + *
  7.3044 + * @param {Array} sample input array
  7.3045 + * @param {Function} [randomSource=Math.random] an optional source of entropy
  7.3046 + * @returns {Array} sample
  7.3047 + * @example
  7.3048 + * var sample = [1, 2, 3, 4];
  7.3049 + * shuffleInPlace(sample);
  7.3050 + * // sample is shuffled to a value like [2, 1, 4, 3]
  7.3051 + */
  7.3052 +function shuffleInPlace(sample/*:Array<any>*/, randomSource/*:Function*/)/*:Array<any>*/ {
  7.3053 +
  7.3054 +
  7.3055 +    // a custom random number source can be provided if you want to use
  7.3056 +    // a fixed seed or another random number generator, like
  7.3057 +    // [random-js](https://www.npmjs.org/package/random-js)
  7.3058 +    randomSource = randomSource || Math.random;
  7.3059 +
  7.3060 +    // store the current length of the sample to determine
  7.3061 +    // when no elements remain to shuffle.
  7.3062 +    var length = sample.length;
  7.3063 +
  7.3064 +    // temporary is used to hold an item when it is being
  7.3065 +    // swapped between indices.
  7.3066 +    var temporary;
  7.3067 +
  7.3068 +    // The index to swap at each stage.
  7.3069 +    var index;
  7.3070 +
  7.3071 +    // While there are still items to shuffle
  7.3072 +    while (length > 0) {
  7.3073 +        // chose a random index within the subset of the array
  7.3074 +        // that is not yet shuffled
  7.3075 +        index = Math.floor(randomSource() * length--);
  7.3076 +
  7.3077 +        // store the value that we'll move temporarily
  7.3078 +        temporary = sample[length];
  7.3079 +
  7.3080 +        // swap the value at `sample[length]` with `sample[index]`
  7.3081 +        sample[length] = sample[index];
  7.3082 +        sample[index] = temporary;
  7.3083 +    }
  7.3084 +
  7.3085 +    return sample;
  7.3086 +}
  7.3087 +
  7.3088 +module.exports = shuffleInPlace;
  7.3089 +
  7.3090 +},{}],53:[function(require,module,exports){
  7.3091 +'use strict';
  7.3092 +/* @flow */
  7.3093 +
  7.3094 +/**
  7.3095 + * [Sign](https://en.wikipedia.org/wiki/Sign_function) is a function 
  7.3096 + * that extracts the sign of a real number
  7.3097 + * 
  7.3098 + * @param {Number} x input value
  7.3099 + * @returns {Number} sign value either 1, 0 or -1
  7.3100 + * @throws {TypeError} if the input argument x is not a number
  7.3101 + * @private
  7.3102 + * 
  7.3103 + * @example
  7.3104 + * sign(2); // => 1
  7.3105 + */
  7.3106 +function sign(x/*: number */)/*: number */ {
  7.3107 +    if (typeof x === 'number') {
  7.3108 +        if (x < 0) {
  7.3109 +            return -1;
  7.3110 +        } else if (x === 0) {
  7.3111 +            return 0
  7.3112 +        } else {
  7.3113 +            return 1;
  7.3114 +        }
  7.3115 +    } else {
  7.3116 +        throw new TypeError('not a number');
  7.3117 +    }
  7.3118 +}
  7.3119 +
  7.3120 +module.exports = sign;
  7.3121 +
  7.3122 +},{}],54:[function(require,module,exports){
  7.3123 +'use strict';
  7.3124 +/* @flow */
  7.3125 +
  7.3126 +var variance = require(62);
  7.3127 +
  7.3128 +/**
  7.3129 + * The [standard deviation](http://en.wikipedia.org/wiki/Standard_deviation)
  7.3130 + * is the square root of the variance. It's useful for measuring the amount
  7.3131 + * of variation or dispersion in a set of values.
  7.3132 + *
  7.3133 + * Standard deviation is only appropriate for full-population knowledge: for
  7.3134 + * samples of a population, {@link sampleStandardDeviation} is
  7.3135 + * more appropriate.
  7.3136 + *
  7.3137 + * @param {Array<number>} x input
  7.3138 + * @returns {number} standard deviation
  7.3139 + * @example
  7.3140 + * variance([2, 4, 4, 4, 5, 5, 7, 9]); // => 4
  7.3141 + * standardDeviation([2, 4, 4, 4, 5, 5, 7, 9]); // => 2
  7.3142 + */
  7.3143 +function standardDeviation(x /*: Array<number> */)/*:number*/ {
  7.3144 +    // The standard deviation of no numbers is null
  7.3145 +    var v = variance(x);
  7.3146 +    if (isNaN(v)) { return 0; }
  7.3147 +    return Math.sqrt(v);
  7.3148 +}
  7.3149 +
  7.3150 +module.exports = standardDeviation;
  7.3151 +
  7.3152 +},{"62":62}],55:[function(require,module,exports){
  7.3153 +'use strict';
  7.3154 +/* @flow */
  7.3155 +
  7.3156 +var SQRT_2PI = Math.sqrt(2 * Math.PI);
  7.3157 +
  7.3158 +function cumulativeDistribution(z) {
  7.3159 +    var sum = z,
  7.3160 +        tmp = z;
  7.3161 +
  7.3162 +    // 15 iterations are enough for 4-digit precision
  7.3163 +    for (var i = 1; i < 15; i++) {
  7.3164 +        tmp *= z * z / (2 * i + 1);
  7.3165 +        sum += tmp;
  7.3166 +    }
  7.3167 +    return Math.round((0.5 + (sum / SQRT_2PI) * Math.exp(-z * z / 2)) * 1e4) / 1e4;
  7.3168 +}
  7.3169 +
  7.3170 +/**
  7.3171 + * A standard normal table, also called the unit normal table or Z table,
  7.3172 + * is a mathematical table for the values of Φ (phi), which are the values of
  7.3173 + * the cumulative distribution function of the normal distribution.
  7.3174 + * It is used to find the probability that a statistic is observed below,
  7.3175 + * above, or between values on the standard normal distribution, and by
  7.3176 + * extension, any normal distribution.
  7.3177 + *
  7.3178 + * The probabilities are calculated using the
  7.3179 + * [Cumulative distribution function](https://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function).
  7.3180 + * The table used is the cumulative, and not cumulative from 0 to mean
  7.3181 + * (even though the latter has 5 digits precision, instead of 4).
  7.3182 + */
  7.3183 +var standardNormalTable/*: Array<number> */ = [];
  7.3184 +
  7.3185 +for (var z = 0; z <= 3.09; z += 0.01) {
  7.3186 +    standardNormalTable.push(cumulativeDistribution(z));
  7.3187 +}
  7.3188 +
  7.3189 +module.exports = standardNormalTable;
  7.3190 +
  7.3191 +},{}],56:[function(require,module,exports){
  7.3192 +'use strict';
  7.3193 +/* @flow */
  7.3194 +
  7.3195 +/**
  7.3196 + * Our default sum is the [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm) is
  7.3197 + * a method for computing the sum of a list of numbers while correcting
  7.3198 + * for floating-point errors. Traditionally, sums are calculated as many
  7.3199 + * successive additions, each one with its own floating-point roundoff. These
  7.3200 + * losses in precision add up as the number of numbers increases. This alternative
  7.3201 + * algorithm is more accurate than the simple way of calculating sums by simple
  7.3202 + * addition.
  7.3203 + *
  7.3204 + * This runs on `O(n)`, linear time in respect to the array
  7.3205 + *
  7.3206 + * @param {Array<number>} x input
  7.3207 + * @return {number} sum of all input numbers
  7.3208 + * @example
  7.3209 + * sum([1, 2, 3]); // => 6
  7.3210 + */
  7.3211 +function sum(x/*: Array<number> */)/*: number */ {
  7.3212 +
  7.3213 +    // like the traditional sum algorithm, we keep a running
  7.3214 +    // count of the current sum.
  7.3215 +    var sum = 0;
  7.3216 +
  7.3217 +    // but we also keep three extra variables as bookkeeping:
  7.3218 +    // most importantly, an error correction value. This will be a very
  7.3219 +    // small number that is the opposite of the floating point precision loss.
  7.3220 +    var errorCompensation = 0;
  7.3221 +
  7.3222 +    // this will be each number in the list corrected with the compensation value.
  7.3223 +    var correctedCurrentValue;
  7.3224 +
  7.3225 +    // and this will be the next sum
  7.3226 +    var nextSum;
  7.3227 +
  7.3228 +    for (var i = 0; i < x.length; i++) {
  7.3229 +        // first correct the value that we're going to add to the sum
  7.3230 +        correctedCurrentValue = x[i] - errorCompensation;
  7.3231 +
  7.3232 +        // compute the next sum. sum is likely a much larger number
  7.3233 +        // than correctedCurrentValue, so we'll lose precision here,
  7.3234 +        // and measure how much precision is lost in the next step
  7.3235 +        nextSum = sum + correctedCurrentValue;
  7.3236 +
  7.3237 +        // we intentionally didn't assign sum immediately, but stored
  7.3238 +        // it for now so we can figure out this: is (sum + nextValue) - nextValue
  7.3239 +        // not equal to 0? ideally it would be, but in practice it won't:
  7.3240 +        // it will be some very small number. that's what we record
  7.3241 +        // as errorCompensation.
  7.3242 +        errorCompensation = nextSum - sum - correctedCurrentValue;
  7.3243 +
  7.3244 +        // now that we've computed how much we'll correct for in the next
  7.3245 +        // loop, start treating the nextSum as the current sum.
  7.3246 +        sum = nextSum;
  7.3247 +    }
  7.3248 +
  7.3249 +    return sum;
  7.3250 +}
  7.3251 +
  7.3252 +module.exports = sum;
  7.3253 +
  7.3254 +},{}],57:[function(require,module,exports){
  7.3255 +'use strict';
  7.3256 +/* @flow */
  7.3257 +
  7.3258 +var mean = require(25);
  7.3259 +
  7.3260 +/**
  7.3261 + * The sum of deviations to the Nth power.
  7.3262 + * When n=2 it's the sum of squared deviations.
  7.3263 + * When n=3 it's the sum of cubed deviations.
  7.3264 + *
  7.3265 + * @param {Array<number>} x
  7.3266 + * @param {number} n power
  7.3267 + * @returns {number} sum of nth power deviations
  7.3268 + * @example
  7.3269 + * var input = [1, 2, 3];
  7.3270 + * // since the variance of a set is the mean squared
  7.3271 + * // deviations, we can calculate that with sumNthPowerDeviations:
  7.3272 + * var variance = sumNthPowerDeviations(input) / input.length;
  7.3273 + */
  7.3274 +function sumNthPowerDeviations(x/*: Array<number> */, n/*: number */)/*:number*/ {
  7.3275 +    var meanValue = mean(x),
  7.3276 +        sum = 0;
  7.3277 +
  7.3278 +    for (var i = 0; i < x.length; i++) {
  7.3279 +        sum += Math.pow(x[i] - meanValue, n);
  7.3280 +    }
  7.3281 +
  7.3282 +    return sum;
  7.3283 +}
  7.3284 +
  7.3285 +module.exports = sumNthPowerDeviations;
  7.3286 +
  7.3287 +},{"25":25}],58:[function(require,module,exports){
  7.3288 +'use strict';
  7.3289 +/* @flow */
  7.3290 +
  7.3291 +/**
  7.3292 + * The simple [sum](https://en.wikipedia.org/wiki/Summation) of an array
  7.3293 + * is the result of adding all numbers together, starting from zero.
  7.3294 + *
  7.3295 + * This runs on `O(n)`, linear time in respect to the array
  7.3296 + *
  7.3297 + * @param {Array<number>} x input
  7.3298 + * @return {number} sum of all input numbers
  7.3299 + * @example
  7.3300 + * sumSimple([1, 2, 3]); // => 6
  7.3301 + */
  7.3302 +function sumSimple(x/*: Array<number> */)/*: number */ {
  7.3303 +    var value = 0;
  7.3304 +    for (var i = 0; i < x.length; i++) {
  7.3305 +        value += x[i];
  7.3306 +    }
  7.3307 +    return value;
  7.3308 +}
  7.3309 +
  7.3310 +module.exports = sumSimple;
  7.3311 +
  7.3312 +},{}],59:[function(require,module,exports){
  7.3313 +'use strict';
  7.3314 +/* @flow */
  7.3315 +
  7.3316 +var standardDeviation = require(54);
  7.3317 +var mean = require(25);
  7.3318 +
  7.3319 +/**
  7.3320 + * This is to compute [a one-sample t-test](https://en.wikipedia.org/wiki/Student%27s_t-test#One-sample_t-test), comparing the mean
  7.3321 + * of a sample to a known value, x.
  7.3322 + *
  7.3323 + * in this case, we're trying to determine whether the
  7.3324 + * population mean is equal to the value that we know, which is `x`
  7.3325 + * here. usually the results here are used to look up a
  7.3326 + * [p-value](http://en.wikipedia.org/wiki/P-value), which, for
  7.3327 + * a certain level of significance, will let you determine that the
  7.3328 + * null hypothesis can or cannot be rejected.
  7.3329 + *
  7.3330 + * @param {Array<number>} sample an array of numbers as input
  7.3331 + * @param {number} x expected value of the population mean
  7.3332 + * @returns {number} value
  7.3333 + * @example
  7.3334 + * tTest([1, 2, 3, 4, 5, 6], 3.385).toFixed(2); // => '0.16'
  7.3335 + */
  7.3336 +function tTest(sample/*: Array<number> */, x/*: number */)/*:number*/ {
  7.3337 +    // The mean of the sample
  7.3338 +    var sampleMean = mean(sample);
  7.3339 +
  7.3340 +    // The standard deviation of the sample
  7.3341 +    var sd = standardDeviation(sample);
  7.3342 +
  7.3343 +    // Square root the length of the sample
  7.3344 +    var rootN = Math.sqrt(sample.length);
  7.3345 +
  7.3346 +    // returning the t value
  7.3347 +    return (sampleMean - x) / (sd / rootN);
  7.3348 +}
  7.3349 +
  7.3350 +module.exports = tTest;
  7.3351 +
  7.3352 +},{"25":25,"54":54}],60:[function(require,module,exports){
  7.3353 +'use strict';
  7.3354 +/* @flow */
  7.3355 +
  7.3356 +var mean = require(25);
  7.3357 +var sampleVariance = require(50);
  7.3358 +
  7.3359 +/**
  7.3360 + * This is to compute [two sample t-test](http://en.wikipedia.org/wiki/Student's_t-test).
  7.3361 + * Tests whether "mean(X)-mean(Y) = difference", (
  7.3362 + * in the most common case, we often have `difference == 0` to test if two samples
  7.3363 + * are likely to be taken from populations with the same mean value) with
  7.3364 + * no prior knowledge on standard deviations of both samples
  7.3365 + * other than the fact that they have the same standard deviation.
  7.3366 + *
  7.3367 + * Usually the results here are used to look up a
  7.3368 + * [p-value](http://en.wikipedia.org/wiki/P-value), which, for
  7.3369 + * a certain level of significance, will let you determine that the
  7.3370 + * null hypothesis can or cannot be rejected.
  7.3371 + *
  7.3372 + * `diff` can be omitted if it equals 0.
  7.3373 + *
  7.3374 + * [This is used to confirm or deny](http://www.monarchlab.org/Lab/Research/Stats/2SampleT.aspx)
  7.3375 + * a null hypothesis that the two populations that have been sampled into
  7.3376 + * `sampleX` and `sampleY` are equal to each other.
  7.3377 + *
  7.3378 + * @param {Array<number>} sampleX a sample as an array of numbers
  7.3379 + * @param {Array<number>} sampleY a sample as an array of numbers
  7.3380 + * @param {number} [difference=0]
  7.3381 + * @returns {number} test result
  7.3382 + * @example
  7.3383 + * ss.tTestTwoSample([1, 2, 3, 4], [3, 4, 5, 6], 0); //= -2.1908902300206643
  7.3384 + */
  7.3385 +function tTestTwoSample(
  7.3386 +    sampleX/*: Array<number> */,
  7.3387 +    sampleY/*: Array<number> */,
  7.3388 +    difference/*: number */) {
  7.3389 +    var n = sampleX.length,
  7.3390 +        m = sampleY.length;
  7.3391 +
  7.3392 +    // If either sample doesn't actually have any values, we can't
  7.3393 +    // compute this at all, so we return `null`.
  7.3394 +    if (!n || !m) { return null; }
  7.3395 +
  7.3396 +    // default difference (mu) is zero
  7.3397 +    if (!difference) {
  7.3398 +        difference = 0;
  7.3399 +    }
  7.3400 +
  7.3401 +    var meanX = mean(sampleX),
  7.3402 +        meanY = mean(sampleY),
  7.3403 +        sampleVarianceX = sampleVariance(sampleX),
  7.3404 +        sampleVarianceY = sampleVariance(sampleY);
  7.3405 +
  7.3406 +    if (typeof meanX === 'number' &&
  7.3407 +        typeof meanY === 'number' &&
  7.3408 +        typeof sampleVarianceX === 'number' &&
  7.3409 +        typeof sampleVarianceY === 'number') {
  7.3410 +        var weightedVariance = ((n - 1) * sampleVarianceX +
  7.3411 +            (m - 1) * sampleVarianceY) / (n + m - 2);
  7.3412 +
  7.3413 +        return (meanX - meanY - difference) /
  7.3414 +            Math.sqrt(weightedVariance * (1 / n + 1 / m));
  7.3415 +    }
  7.3416 +}
  7.3417 +
  7.3418 +module.exports = tTestTwoSample;
  7.3419 +
  7.3420 +},{"25":25,"50":50}],61:[function(require,module,exports){
  7.3421 +'use strict';
  7.3422 +/* @flow */
  7.3423 +
  7.3424 +/**
  7.3425 + * For a sorted input, counting the number of unique values
  7.3426 + * is possible in constant time and constant memory. This is
  7.3427 + * a simple implementation of the algorithm.
  7.3428 + *
  7.3429 + * Values are compared with `===`, so objects and non-primitive objects
  7.3430 + * are not handled in any special way.
  7.3431 + *
  7.3432 + * @param {Array} input an array of primitive values.
  7.3433 + * @returns {number} count of unique values
  7.3434 + * @example
  7.3435 + * uniqueCountSorted([1, 2, 3]); // => 3
  7.3436 + * uniqueCountSorted([1, 1, 1]); // => 1
  7.3437 + */
  7.3438 +function uniqueCountSorted(input/*: Array<any>*/)/*: number */ {
  7.3439 +    var uniqueValueCount = 0,
  7.3440 +        lastSeenValue;
  7.3441 +    for (var i = 0; i < input.length; i++) {
  7.3442 +        if (i === 0 || input[i] !== lastSeenValue) {
  7.3443 +            lastSeenValue = input[i];
  7.3444 +            uniqueValueCount++;
  7.3445 +        }
  7.3446 +    }
  7.3447 +    return uniqueValueCount;
  7.3448 +}
  7.3449 +
  7.3450 +module.exports = uniqueCountSorted;
  7.3451 +
  7.3452 +},{}],62:[function(require,module,exports){
  7.3453 +'use strict';
  7.3454 +/* @flow */
  7.3455 +
  7.3456 +var sumNthPowerDeviations = require(57);
  7.3457 +
  7.3458 +/**
  7.3459 + * The [variance](http://en.wikipedia.org/wiki/Variance)
  7.3460 + * is the sum of squared deviations from the mean.
  7.3461 + *
  7.3462 + * This is an implementation of variance, not sample variance:
  7.3463 + * see the `sampleVariance` method if you want a sample measure.
  7.3464 + *
  7.3465 + * @param {Array<number>} x a population
  7.3466 + * @returns {number} variance: a value greater than or equal to zero.
  7.3467 + * zero indicates that all values are identical.
  7.3468 + * @example
  7.3469 + * variance([1, 2, 3, 4, 5, 6]); // => 2.9166666666666665
  7.3470 + */
  7.3471 +function variance(x/*: Array<number> */)/*:number*/ {
  7.3472 +    // The variance of no numbers is null
  7.3473 +    if (x.length === 0) { return NaN; }
  7.3474 +
  7.3475 +    // Find the mean of squared deviations between the
  7.3476 +    // mean value and each value.
  7.3477 +    return sumNthPowerDeviations(x, 2) / x.length;
  7.3478 +}
  7.3479 +
  7.3480 +module.exports = variance;
  7.3481 +
  7.3482 +},{"57":57}],63:[function(require,module,exports){
  7.3483 +'use strict';
  7.3484 +/* @flow */
  7.3485 +
  7.3486 +/**
  7.3487 + * The [Z-Score, or Standard Score](http://en.wikipedia.org/wiki/Standard_score).
  7.3488 + *
  7.3489 + * The standard score is the number of standard deviations an observation
  7.3490 + * or datum is above or below the mean. Thus, a positive standard score
  7.3491 + * represents a datum above the mean, while a negative standard score
  7.3492 + * represents a datum below the mean. It is a dimensionless quantity
  7.3493 + * obtained by subtracting the population mean from an individual raw
  7.3494 + * score and then dividing the difference by the population standard
  7.3495 + * deviation.
  7.3496 + *
  7.3497 + * The z-score is only defined if one knows the population parameters;
  7.3498 + * if one only has a sample set, then the analogous computation with
  7.3499 + * sample mean and sample standard deviation yields the
  7.3500 + * Student's t-statistic.
  7.3501 + *
  7.3502 + * @param {number} x
  7.3503 + * @param {number} mean
  7.3504 + * @param {number} standardDeviation
  7.3505 + * @return {number} z score
  7.3506 + * @example
  7.3507 + * zScore(78, 80, 5); // => -0.4
  7.3508 + */
  7.3509 +function zScore(x/*:number*/, mean/*:number*/, standardDeviation/*:number*/)/*:number*/ {
  7.3510 +    return (x - mean) / standardDeviation;
  7.3511 +}
  7.3512 +
  7.3513 +module.exports = zScore;
  7.3514 +
  7.3515 +},{}]},{},[1])(1)
  7.3516 +});
  7.3517 +//# sourceMappingURL=simple-statistics.js.map