Feature #162: Added Rickshaw graphs to most panes of statistics. Needs a little tidying for clarity.
Feature #162: Added Rickshaw graphs to most panes of statistics. Needs a little tidying for clarity.

import re import re
import csv import csv
import sys import sys
  import json
import logging import logging
import operator import operator
import collections import collections
from ckan.lib.base import (BaseController, c, g, render, request, response, abort) from ckan.lib.base import (BaseController, c, g, render, request, response, abort)
   
import sqlalchemy import sqlalchemy
from sqlalchemy import func, cast, Integer from sqlalchemy import func, cast, Integer
import ckan.model as model import ckan.model as model
from ga_model import GA_Url, GA_Stat, GA_ReferralStat, GA_Publisher from ga_model import GA_Url, GA_Stat, GA_ReferralStat, GA_Publisher
   
log = logging.getLogger('ckanext.ga-report') log = logging.getLogger('ckanext.ga-report')
   
DOWNLOADS_AVAILABLE_FROM = '2012-12' DOWNLOADS_AVAILABLE_FROM = '2012-12'
   
def _get_month_name(strdate): def _get_month_name(strdate):
import calendar import calendar
from time import strptime from time import strptime
d = strptime(strdate, '%Y-%m') d = strptime(strdate, '%Y-%m')
return '%s %s' % (calendar.month_name[d.tm_mon], d.tm_year) return '%s %s' % (calendar.month_name[d.tm_mon], d.tm_year)
   
  def _get_unix_epoch(strdate):
  from time import strptime,mktime
  d = strptime(strdate, '%Y-%m')
  return int(mktime(d))
   
def _month_details(cls, stat_key=None): def _month_details(cls, stat_key=None):
''' '''
Returns a list of all the periods for which we have data, unfortunately Returns a list of all the periods for which we have data, unfortunately
knows too much about the type of the cls being passed as GA_Url has a knows too much about the type of the cls being passed as GA_Url has a
more complex query more complex query
   
This may need extending if we add a period_name to the stats This may need extending if we add a period_name to the stats
''' '''
months = [] months = []
day = None day = None
   
q = model.Session.query(cls.period_name,cls.period_complete_day)\ q = model.Session.query(cls.period_name,cls.period_complete_day)\
.filter(cls.period_name!='All').distinct(cls.period_name) .filter(cls.period_name!='All').distinct(cls.period_name)
if stat_key: if stat_key:
q= q.filter(cls.stat_name==stat_key) q= q.filter(cls.stat_name==stat_key)
   
vals = q.order_by("period_name desc").all() vals = q.order_by("period_name desc").all()
   
if vals and vals[0][1]: if vals and vals[0][1]:
day = int(vals[0][1]) day = int(vals[0][1])
ordinal = 'th' if 11 <= day <= 13 \ ordinal = 'th' if 11 <= day <= 13 \
else {1:'st',2:'nd',3:'rd'}.get(day % 10, 'th') else {1:'st',2:'nd',3:'rd'}.get(day % 10, 'th')
day = "{day}{ordinal}".format(day=day, ordinal=ordinal) day = "{day}{ordinal}".format(day=day, ordinal=ordinal)
   
for m in vals: for m in vals:
months.append( (m[0], _get_month_name(m[0]))) months.append( (m[0], _get_month_name(m[0])))
   
return months, day return months, day
   
   
class GaReport(BaseController): class GaReport(BaseController):
   
def csv(self, month): def csv(self, month):
import csv import csv
   
q = model.Session.query(GA_Stat).filter(GA_Stat.stat_name!='Downloads') q = model.Session.query(GA_Stat).filter(GA_Stat.stat_name!='Downloads')
if month != 'all': if month != 'all':
q = q.filter(GA_Stat.period_name==month) q = q.filter(GA_Stat.period_name==month)
entries = q.order_by('GA_Stat.period_name, GA_Stat.stat_name, GA_Stat.key').all() entries = q.order_by('GA_Stat.period_name, GA_Stat.stat_name, GA_Stat.key').all()
   
response.headers['Content-Type'] = "text/csv; charset=utf-8" response.headers['Content-Type'] = "text/csv; charset=utf-8"
response.headers['Content-Disposition'] = str('attachment; filename=stats_%s.csv' % (month,)) response.headers['Content-Disposition'] = str('attachment; filename=stats_%s.csv' % (month,))
   
writer = csv.writer(response) writer = csv.writer(response)
writer.writerow(["Period", "Statistic", "Key", "Value"]) writer.writerow(["Period", "Statistic", "Key", "Value"])
   
for entry in entries: for entry in entries:
writer.writerow([entry.period_name.encode('utf-8'), writer.writerow([entry.period_name.encode('utf-8'),
entry.stat_name.encode('utf-8'), entry.stat_name.encode('utf-8'),
entry.key.encode('utf-8'), entry.key.encode('utf-8'),
entry.value.encode('utf-8')]) entry.value.encode('utf-8')])
   
   
def index(self): def index(self):
   
# Get the month details by fetching distinct values and determining the # Get the month details by fetching distinct values and determining the
# month names from the values. # month names from the values.
c.months, c.day = _month_details(GA_Stat) c.months, c.day = _month_details(GA_Stat)
   
# Work out which month to show, based on query params of the first item # Work out which month to show, based on query params of the first item
c.month_desc = 'all months' c.month_desc = 'all months'
c.month = request.params.get('month', '') c.month = request.params.get('month', '')
if c.month: if c.month:
c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month]) c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month])
   
q = model.Session.query(GA_Stat).\ q = model.Session.query(GA_Stat).\
filter(GA_Stat.stat_name=='Totals') filter(GA_Stat.stat_name=='Totals')
if c.month: if c.month:
q = q.filter(GA_Stat.period_name==c.month) q = q.filter(GA_Stat.period_name==c.month)
entries = q.order_by('ga_stat.key').all() entries = q.order_by('ga_stat.key').all()
   
def clean_key(key, val): def clean_key(key, val):
if key in ['Average time on site', 'Pages per visit', 'New visits', 'Bounce rate (home page)']: if key in ['Average time on site', 'Pages per visit', 'New visits', 'Bounce rate (home page)']:
val = "%.2f" % round(float(val), 2) val = "%.2f" % round(float(val), 2)
if key == 'Average time on site': if key == 'Average time on site':
mins, secs = divmod(float(val), 60) mins, secs = divmod(float(val), 60)
hours, mins = divmod(mins, 60) hours, mins = divmod(mins, 60)
val = '%02d:%02d:%02d (%s seconds) ' % (hours, mins, secs, val) val = '%02d:%02d:%02d (%s seconds) ' % (hours, mins, secs, val)
if key in ['New visits','Bounce rate (home page)']: if key in ['New visits','Bounce rate (home page)']:
val = "%s%%" % val val = "%s%%" % val
if key in ['Total page views', 'Total visits']: if key in ['Total page views', 'Total visits']:
val = int(val) val = int(val)
   
return key, val return key, val
   
# Query historic values for sparkline rendering # Query historic values for sparkline rendering
graph_query = model.Session.query(GA_Stat)\ graph_query = model.Session.query(GA_Stat)\
.filter(GA_Stat.stat_name=='Totals')\ .filter(GA_Stat.stat_name=='Totals')\
.order_by(GA_Stat.period_name) .order_by(GA_Stat.period_name)
graph_data = {} graph_data = {}
for x in graph_query: for x in graph_query:
graph_data[x.key] = graph_data.get(x.key,[]) graph_data[x.key] = graph_data.get(x.key,[])
key, val = clean_key(x.key,float(x.value)) key, val = clean_key(x.key,float(x.value))
tooltip = '%s: %s' % (_get_month_name(x.period_name), val) tooltip = '%s: %s' % (_get_month_name(x.period_name), val)
graph_data[x.key].append( (tooltip,x.value) ) graph_data[x.key].append( (tooltip,x.value) )
# Trim the latest month, as it looks like a huge dropoff # Trim the latest month, as it looks like a huge dropoff
for key in graph_data: for key in graph_data:
graph_data[key] = graph_data[key][:-1] graph_data[key] = graph_data[key][:-1]
   
c.global_totals = [] c.global_totals = []
if c.month: if c.month:
for e in entries: for e in entries:
key, val = clean_key(e.key, e.value) key, val = clean_key(e.key, e.value)
sparkline = graph_data[e.key] sparkline = graph_data[e.key]
c.global_totals.append((key, val, sparkline)) c.global_totals.append((key, val, sparkline))
else: else:
d = collections.defaultdict(list) d = collections.defaultdict(list)
for e in entries: for e in entries:
d[e.key].append(float(e.value)) d[e.key].append(float(e.value))
for k, v in d.iteritems(): for k, v in d.iteritems():
if k in ['Total page views', 'Total visits']: if k in ['Total page views', 'Total visits']:
v = sum(v) v = sum(v)
else: else:
v = float(sum(v))/float(len(v)) v = float(sum(v))/float(len(v))
sparkline = graph_data[k] sparkline = graph_data[k]
key, val = clean_key(k,v) key, val = clean_key(k,v)
   
c.global_totals.append((key, val, sparkline)) c.global_totals.append((key, val, sparkline))
c.global_totals = sorted(c.global_totals, key=operator.itemgetter(0)) c.global_totals = sorted(c.global_totals, key=operator.itemgetter(0))
   
keys = { keys = {
'Browser versions': 'browser_versions', 'Browser versions': 'browser_versions',
'Browsers': 'browsers', 'Browsers': 'browsers',
'Operating Systems versions': 'os_versions', 'Operating Systems versions': 'os_versions',
'Operating Systems': 'os', 'Operating Systems': 'os',
'Social sources': 'social_networks', 'Social sources': 'social_networks',
'Languages': 'languages', 'Languages': 'languages',
'Country': 'country' 'Country': 'country'
} }
   
def shorten_name(name, length=60): def shorten_name(name, length=60):
return (name[:length] + '..') if len(name) > 60 else name return (name[:length] + '..') if len(name) > 60 else name
   
def fill_out_url(url): def fill_out_url(url):
import urlparse import urlparse
return urlparse.urljoin(g.site_url, url) return urlparse.urljoin(g.site_url, url)
   
c.social_referrer_totals, c.social_referrers = [], [] c.social_referrer_totals, c.social_referrers = [], []
q = model.Session.query(GA_ReferralStat) q = model.Session.query(GA_ReferralStat)
q = q.filter(GA_ReferralStat.period_name==c.month) if c.month else q q = q.filter(GA_ReferralStat.period_name==c.month) if c.month else q
q = q.order_by('ga_referrer.count::int desc') q = q.order_by('ga_referrer.count::int desc')
for entry in q.all(): for entry in q.all():
c.social_referrers.append((shorten_name(entry.url), fill_out_url(entry.url), c.social_referrers.append((shorten_name(entry.url), fill_out_url(entry.url),
entry.source,entry.count)) entry.source,entry.count))
   
q = model.Session.query(GA_ReferralStat.url, q = model.Session.query(GA_ReferralStat.url,
func.sum(GA_ReferralStat.count).label('count')) func.sum(GA_ReferralStat.count).label('count'))
q = q.filter(GA_ReferralStat.period_name==c.month) if c.month else q q = q.filter(GA_ReferralStat.period_name==c.month) if c.month else q
q = q.order_by('count desc').group_by(GA_ReferralStat.url) q = q.order_by('count desc').group_by(GA_ReferralStat.url)
for entry in q.all(): for entry in q.all():
c.social_referrer_totals.append((shorten_name(entry[0]), fill_out_url(entry[0]),'', c.social_referrer_totals.append((shorten_name(entry[0]), fill_out_url(entry[0]),'',
entry[1])) entry[1]))
   
for k, v in keys.iteritems(): for k, v in keys.iteritems():
q = model.Session.query(GA_Stat).\ q = model.Session.query(GA_Stat).\
filter(GA_Stat.stat_name==k) filter(GA_Stat.stat_name==k).\
  order_by(GA_Stat.period_name)
  # Run the query on all months to gather graph data
  series = {}
  x_axis = set()
  for stat in q:
  x_val = _get_unix_epoch(stat.period_name)
  series[ stat.key ] = series.get(stat.key,{})
  series[ stat.key ][x_val] = float(stat.value)
  x_axis.add(x_val)
  # Common x-axis for all series. Exclude this month (incomplete data)
  x_axis = sorted(list(x_axis))[:-1]
  # Buffer a rickshaw dataset from the series
  def create_graph(series_name, series_data):
  return {
  'name':series_name,
  'data':[ {'x':x,'y':series_data.get(x,0)} for x in x_axis ]
  }
  rickshaw = [ create_graph(name,data) for name, data in series.items() ]
  rickshaw = sorted(rickshaw,key=lambda x:x['data'][-1]['y'])
  setattr(c, v+'_graph', json.dumps(rickshaw))
   
  # Buffer the tabular data
if c.month: if c.month:
entries = [] entries = []
q = q.filter(GA_Stat.period_name==c.month).\ q = q.filter(GA_Stat.period_name==c.month).\
order_by('ga_stat.value::int desc') order_by('ga_stat.value::int desc')
   
d = collections.defaultdict(int) d = collections.defaultdict(int)
for e in q.all(): for e in q.all():
d[e.key] += int(e.value) d[e.key] += int(e.value)
entries = [] entries = []
for key, val in d.iteritems(): for key, val in d.iteritems():
entries.append((key,val,)) entries.append((key,val,))
entries = sorted(entries, key=operator.itemgetter(1), reverse=True) entries = sorted(entries, key=operator.itemgetter(1), reverse=True)
   
# Get the total for each set of values and then set the value as # Get the total for each set of values and then set the value as
# a percentage of the total # a percentage of the total
if k == 'Social sources': if k == 'Social sources':
total = sum([x for n,x,graph in c.global_totals if n == 'Total visits']) total = sum([x for n,x,graph in c.global_totals if n == 'Total visits'])
else: else:
total = sum([num for _,num in entries]) total = sum([num for _,num in entries])
setattr(c, v, [(k,_percent(v,total)) for k,v in entries ]) setattr(c, v, [(k,_percent(v,total)) for k,v in entries ])
   
return render('ga_report/site/index.html') return render('ga_report/site/index.html')
   
   
class GaDatasetReport(BaseController): class GaDatasetReport(BaseController):
""" """
Displays the pageview and visit count for datasets Displays the pageview and visit count for datasets
with options to filter by publisher and time period. with options to filter by publisher and time period.
""" """
def publisher_csv(self, month): def publisher_csv(self, month):
''' '''
Returns a CSV of each publisher with the total number of dataset Returns a CSV of each publisher with the total number of dataset
views & visits. views & visits.
''' '''
c.month = month if not month == 'all' else '' c.month = month if not month == 'all' else ''
response.headers['Content-Type'] = "text/csv; charset=utf-8" response.headers['Content-Type'] = "text/csv; charset=utf-8"
response.headers['Content-Disposition'] = str('attachment; filename=publishers_%s.csv' % (month,)) response.headers['Content-Disposition'] = str('attachment; filename=publishers_%s.csv' % (month,))
   
writer = csv.writer(response) writer = csv.writer(response)
writer.writerow(["Publisher Title", "Publisher Name", "Views", "Visits", "Period Name"]) writer.writerow(["Publisher Title", "Publisher Name", "Views", "Visits", "Period Name"])
   
for publisher,view,visit in _get_top_publishers(None): for publisher,view,visit in _get_top_publishers(None):
writer.writerow([publisher.title.encode('utf-8'), writer.writerow([publisher.title.encode('utf-8'),
publisher.name.encode('utf-8'), publisher.name.encode('utf-8'),
view, view,
visit, visit,
month]) month])
   
def dataset_csv(self, id='all', month='all'): def dataset_csv(self, id='all', month='all'):
''' '''
Returns a CSV with the number of views & visits for each dataset. Returns a CSV with the number of views & visits for each dataset.
   
:param id: A Publisher ID or None if you want for all :param id: A Publisher ID or None if you want for all
:param month: The time period, or 'all' :param month: The time period, or 'all'
''' '''
c.month = month if not month == 'all' else '' c.month = month if not month == 'all' else ''
if id != 'all': if id != 'all':
c.publisher = model.Group.get(id) c.publisher = model.Group.get(id)
if not c.publisher: if not c.publisher:
abort(404, 'A publisher with that name could not be found') abort(404, 'A publisher with that name could not be found')
   
packages = self._get_packages(c.publisher) packages = self._get_packages(c.publisher)
response.headers['Content-Type'] = "text/csv; charset=utf-8" response.headers['Content-Type'] = "text/csv; charset=utf-8"
response.headers['Content-Disposition'] = \ response.headers['Content-Disposition'] = \
str('attachment; filename=datasets_%s_%s.csv' % (c.publisher_name, month,)) str('attachment; filename=datasets_%s_%s.csv' % (c.publisher_name, month,))
   
writer = csv.writer(response) writer = csv.writer(response)
writer.writerow(["Dataset Title", "Dataset Name", "Views", "Visits", "Resource downloads", "Period Name"]) writer.writerow(["Dataset Title", "Dataset Name", "Views", "Visits", "Resource downloads", "Period Name"])
   
for package,view,visit,downloads in packages: for package,view,visit,downloads in packages:
writer.writerow([package.title.encode('utf-8'), writer.writerow([package.title.encode('utf-8'),
package.name.encode('utf-8'), package.name.encode('utf-8'),
view, view,
visit, visit,
downloads, downloads,
month]) month])
   
def publishers(self): def publishers(self):
'''A list of publishers and the number of views/visits for each''' '''A list of publishers and the number of views/visits for each'''
   
# Get the month details by fetching distinct values and determining the # Get the month details by fetching distinct values and determining the
# month names from the values. # month names from the values.
c.months, c.day = _month_details(GA_Url) c.months, c.day = _month_details(GA_Url)
   
# Work out which month to show, based on query params of the first item # Work out which month to show, based on query params of the first item
c.month = request.params.get('month', '') c.month = request.params.get('month', '')
c.month_desc = 'all months' c.month_desc = 'all months'
if c.month: if c.month:
c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month]) c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month])
   
c.top_publishers = _get_top_publishers() c.top_publishers = _get_top_publishers()
return render('ga_report/publisher/index.html') return render('ga_report/publisher/index.html')
   
def _get_packages(self, publisher=None, count=-1): def _get_packages(self, publisher=None, count=-1):
'''Returns the datasets in order of views''' '''Returns the datasets in order of views'''
have_download_data = True have_download_data = True
month = c.month or 'All' month = c.month or 'All'
if month != 'All': if month != 'All':
have_download_data = month >= DOWNLOADS_AVAILABLE_FROM have_download_data = month >= DOWNLOADS_AVAILABLE_FROM
   
q = model.Session.query(GA_Url,model.Package)\ q = model.Session.query(GA_Url,model.Package)\
.filter(model.Package.name==GA_Url.package_id)\ .filter(model.Package.name==GA_Url.package_id)\
.filter(GA_Url.url.like('/dataset/%')) .filter(GA_Url.url.like('/dataset/%'))
if publisher: if publisher:
q = q.filter(GA_Url.department_id==publisher.name) q = q.filter(GA_Url.department_id==publisher.name)
q = q.filter(GA_Url.period_name==month) q = q.filter(GA_Url.period_name==month)
q = q.order_by('ga_url.pageviews::int desc') q = q.order_by('ga_url.pageviews::int desc')
top_packages = [] top_packages = []
if count == -1: if count == -1:
entries = q.all() entries = q.all()
else: else:
entries = q.limit(count) entries = q.limit(count)
   
for entry,package in entries: for entry,package in entries:
if package: if package:
# Downloads .... # Downloads ....
if have_download_data: if have_download_data:
dls = model.Session.query(GA_Stat).\ dls = model.Session.query(GA_Stat).\
filter(GA_Stat.stat_name=='Downloads').\ filter(GA_Stat.stat_name=='Downloads').\
filter(GA_Stat.key==package.name) filter(GA_Stat.key==package.name)
if month != 'All': # Fetch everything unless the month is specific if month != 'All': # Fetch everything unless the month is specific
dls = dls.filter(GA_Stat.period_name==month) dls = dls.filter(GA_Stat.period_name==month)
   
downloads = sum(int(d.value) for d in dls.all()) downloads = sum(int(d.value) for d in dls.all())
else: else:
downloads = 'No data' downloads = 'No data'
top_packages.append((package, entry.pageviews, entry.visits, downloads)) top_packages.append((package, entry.pageviews, entry.visits, downloads))
else: else:
log.warning('Could not find package associated package') log.warning('Could not find package associated package')
   
return top_packages return top_packages
   
def read(self): def read(self):
''' '''
Lists the most popular datasets across all publishers Lists the most popular datasets across all publishers
''' '''
return self.read_publisher(None) return self.read_publisher(None)
   
def read_publisher(self, id): def read_publisher(self, id):
''' '''
Lists the most popular datasets for a publisher (or across all publishers) Lists the most popular datasets for a publisher (or across all publishers)
''' '''
count = 20 count = 20
   
c.publishers = _get_publishers() c.publishers = _get_publishers()
   
id = request.params.get('publisher', id) id = request.params.get('publisher', id)
if id and id != 'all': if id and id != 'all':
c.publisher = model.Group.get(id) c.publisher = model.Group.get(id)
if not c.publisher: if not c.publisher:
abort(404, 'A publisher with that name could not be found') abort(404, 'A publisher with that name could not be found')
c.publisher_name = c.publisher.name c.publisher_name = c.publisher.name
c.top_packages = [] # package, dataset_views in c.top_packages c.top_packages = [] # package, dataset_views in c.top_packages
   
# Get the month details by fetching distinct values and determining the # Get the month details by fetching distinct values and determining the
# month names from the values. # month names from the values.
c.months, c.day = _month_details(GA_Url) c.months, c.day = _month_details(GA_Url)
   
# Work out which month to show, based on query params of the first item # Work out which month to show, based on query params of the first item
c.month = request.params.get('month', '') c.month = request.params.get('month', '')
if not c.month: if not c.month:
c.month_desc = 'all months' c.month_desc = 'all months'
else: else:
c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month]) c.month_desc = ''.join([m[1] for m in c.months if m[0]==c.month])
   
month = c.month or 'All' month = c.month or 'All'
c.publisher_page_views = 0 c.publisher_page_views = 0
q = model.Session.query(GA_Url).\ q = model.Session.query(GA_Url).\
filter(GA_Url.url=='/publisher/%s' % c.publisher_name) filter(GA_Url.url=='/publisher/%s' % c.publisher_name)
entry = q.filter(GA_Url.period_name==c.month).first() entry = q.filter(GA_Url.period_name==c.month).first()
c.publisher_page_views = entry.pageviews if entry else 0 c.publisher_page_views = entry.pageviews if entry else 0
   
c.top_packages = self._get_packages(c.publisher, 20) c.top_packages = self._get_packages(c.publisher, 20)
   
return render('ga_report/publisher/read.html') return render('ga_report/publisher/read.html')
   
def _get_top_publishers(limit=20): def _get_top_publishers(limit=20):
''' '''
Returns a list of the top 20 publishers by dataset visits. Returns a list of the top 20 publishers by dataset visits.
(The number to show can be varied with 'limit') (The number to show can be varied with 'limit')
''' '''
month = c.month or 'All' month = c.month or 'All'
connection = model.Session.connection() connection = model.Session.connection()
q = """ q = """
select department_id, sum(pageviews::int) views, sum(visits::int) visits select department_id, sum(pageviews::int) views, sum(visits::int) visits
from ga_url from ga_url
where department_id <> '' where department_id <> ''
and package_id <> '' and package_id <> ''
and url like '/dataset/%%' and url like '/dataset/%%'
and period_name=%s and period_name=%s
group by department_id order by views desc group by department_id order by views desc
""" """
if limit: if limit:
q = q + " limit %s;" % (limit) q = q + " limit %s;" % (limit)
   
top_publishers = [] top_publishers = []
res = connection.execute(q, month) res = connection.execute(q, month)
for row in res: for row in res:
g = model.Group.get(row[0]) g = model.Group.get(row[0])
if g: if g:
top_publishers.append((g, row[1], row[2])) top_publishers.append((g, row[1], row[2]))
return top_publishers return top_publishers
   
   
def _get_publishers(): def _get_publishers():
''' '''
Returns a list of all publishers. Each item is a tuple: Returns a list of all publishers. Each item is a tuple:
(name, title) (name, title)
''' '''
publishers = [] publishers = []
for pub in model.Session.query(model.Group).\ for pub in model.Session.query(model.Group).\
filter(model.Group.type=='publisher').\ filter(model.Group.type=='publisher').\
filter(model.Group.state=='active').\ filter(model.Group.state=='active').\
order_by(model.Group.name): order_by(model.Group.name):
publishers.append((pub.name, pub.title)) publishers.append((pub.name, pub.title))
return publishers return publishers
   
def _percent(num, total): def _percent(num, total):
p = 100 * float(num)/float(total) p = 100 * float(num)/float(total)
return "%.2f%%" % round(p, 2) return "%.2f%%" % round(p, 2)
   
  (function(){function a(a){var b=a.source,d=a.target,e=c(b,d),f=[b];while(b!==e)b=b.parent,f.push(b);var g=f.length;while(d!==e)f.splice(g,0,d),d=d.parent;return f}function b(a){var b=[],c=a.parent;while(c!=null)b.push(a),a=c,c=c.parent;return b.push(a),b}function c(a,c){if(a===c)return a;var d=b(a),e=b(c),f=d.pop(),g=e.pop(),h=null;while(f===g)h=f,f=d.pop(),g=e.pop();return h}function g(a){a.fixed|=2}function h(a){a!==f&&(a.fixed&=1)}function i(){j(),f.fixed&=1,e=f=null}function j(){f.px+=d3.event.dx,f.py+=d3.event.dy,e.resume()}function k(a,b,c){var d=0,e=0;a.charge=0;if(!a.leaf){var f=a.nodes,g=f.length,h=-1,i;while(++h<g){i=f[h];if(i==null)continue;k(i,b,c),a.charge+=i.charge,d+=i.charge*i.cx,e+=i.charge*i.cy}}if(a.point){a.leaf||(a.point.x+=Math.random()-.5,a.point.y+=Math.random()-.5);var j=b*c[a.point.index];a.charge+=a.pointCharge=j,d+=j*a.point.x,e+=j*a.point.y}a.cx=d/a.charge,a.cy=e/a.charge}function l(a){return 20}function m(a){return 1}function o(a){return a.x}function p(a){return a.y}function q(a,b,c){a.y0=b,a.y=c}function t(a){var b=1,c=0,d=a[0][1],e,f=a.length;for(;b<f;++b)(e=a[b][1])>d&&(c=b,d=e);return c}function u(a){return a.reduce(v,0)}function v(a,b){return a+b[1]}function w(a,b){return x(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function x(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function y(a){return[d3.min(a),d3.max(a)]}function z(a,b){return a.sort=d3.rebind(a,b.sort),a.children=d3.rebind(a,b.children),a.links=D,a.value=d3.rebind(a,b.value),a.nodes=function(b){return E=!0,(a.nodes=a)(b)},a}function A(a){return a.children}function B(a){return a.value}function C(a,b){return b.value-a.value}function D(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function F(a,b){return a.value-b.value}function G(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function H(a,b){a._pack_next=b,b._pack_prev=a}function I(a,b){var c=b.x-a.x,d=b.y-a.y,e=a.r+b.r;return e*e-c*c-d*d>.001}function J(a){function l(a){b=Math.min(a.x-a.r,b),c=Math.max(a.x+a.r,c),d=Math.min(a.y-a.r,d),e=Math.max(a.y+a.r,e)}var b=Infinity,c=-Infinity,d=Infinity,e=-Infinity,f=a.length,g,h,i,j,k;a.forEach(K),g=a[0],g.x=-g.r,g.y=0,l(g);if(f>1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],O(g,h,i),l(i),G(g,i),g._pack_prev=i,G(i,h),h=g._pack_next;for(var m=3;m<f;m++){O(g,h,i=a[m]);var n=0,o=1,p=1;for(j=h._pack_next;j!==h;j=j._pack_next,o++)if(I(j,i)){n=1;break}if(n==1)for(k=g._pack_prev;k!==j._pack_prev;k=k._pack_prev,p++)if(I(k,i)){p<o&&(n=-1,j=k);break}n==0?(G(g,i),h=i,l(i)):n>0?(H(g,j),h=j,m--):(H(j,h),g=j,m--)}}}var q=(b+c)/2,r=(d+e)/2,s=0;for(var m=0;m<f;m++){var t=a[m];t.x-=q,t.y-=r,s=Math.max(s,t.r+Math.sqrt(t.x*t.x+t.y*t.y))}return a.forEach(L),s}function K(a){a._pack_next=a._pack_prev=a}function L(a){delete a._pack_next,delete a._pack_prev}function M(a){var b=a.children;b&&b.length?(b.forEach(M),a.r=J(b)):a.r=Math.sqrt(a.value)}function N(a,b,c,d){var e=a.children;a.x=b+=d*a.x,a.y=c+=d*a.y,a.r*=d;if(e){var f=-1,g=e.length;while(++f<g)N(e[f],b,c,d)}}function O(a,b,c){var d=a.r+c.r,e=b.x-a.x,f=b.y-a.y;if(d&&(e||f)){var g=b.r+c.r,h=Math.sqrt(e*e+f*f),i=Math.max(-1,Math.min(1,(d*d+h*h-g*g)/(2*d*h))),j=Math.acos(i),k=i*(d/=h),l=Math.sin(j)*d;c.x=a.x+k*e+l*f,c.y=a.y+k*f-l*e}else c.x=a.x+d,c.y=a.y}function P(a){return 1+d3.max(a,function(a){return a.y})}function Q(a){return a.reduce(function(a,b){return a+b.x},0)/a.length}function R(a){var b=a.children;return b&&b.length?R(b[0]):a}function S(a){var b=a.children,c;return b&&(c=b.length)?S(b[c-1]):a}function T(a,b){return a.parent==b.parent?1:2}function U(a){var b=a.children;return b&&b.length?b[0]:a._tree.thread}function V(a){var b=a.children,c;return b&&(c=b.length)?b[c-1]:a._tree.thread}function W(a,b){var c=a.children;if(c&&(e=c.length)){var d,e,f=-1;while(++f<e)b(d=W(c[f],b),a)>0&&(a=d)}return a}function X(a,b){return a.x-b.x}function Y(a,b){return b.x-a.x}function Z(a,b){return a.depth-b.depth}function $(a,b){function c(a,d){var e=a.children;if(e&&(i=e.length)){var f,g=null,h=-1,i;while(++h<i)f=e[h],c(f,g),g=f}b(a,d)}c(a,null)}function _(a){var b=0,c=0,d=a.children,e=d.length,f;while(--e>=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function ba(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function bb(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function bc(a){return{x:a.x,y:a.y,dx:a.dx,dy:a.dy}}function bd(a,b){var c=a.x+b[3],d=a.y+b[0],e=a.dx-b[1]-b[3],f=a.dy-b[0]-b[2];return e<0&&(c+=e/2,e=0),f<0&&(d+=f/2,f=0),{x:c,y:d,dx:e,dy:f}}d3.layout={},d3.layout.bundle=function(){return function(b){var c=[],d=-1,e=b.length;while(++d<e)c.push(a(b[d]));return c}},d3.layout.chord=function(){function j(){var a={},j=[],l=d3.range(e),m=[],n,o,p,q,r;b=[],c=[],n=0,q=-1;while(++q<e){o=0,r=-1;while(++r<e)o+=d[q][r];j.push(o),m.push(d3.range(e)),n+=o}g&&l.sort(function(a,b){return g(j[a],j[b])}),h&&m.forEach(function(a,b){a.sort(function(a,c){return h(d[b][a],d[b][c])})}),n=(2*Math.PI-f*e)/n,o=0,q=-1;while(++q<e){p=o,r=-1;while(++r<e){var s=l[q],t=m[s][r],u=d[s][t],v=o,w=o+=u*n;a[s+"-"+t]={index:s,subindex:t,startAngle:v,endAngle:w,value:u}}c.push({index:s,startAngle:p,endAngle:o,value:(o-p)/n}),o+=f}q=-1;while(++q<e){r=q-1;while(++r<e){var x=a[q+"-"+r],y=a[r+"-"+q];(x.value||y.value)&&b.push(x.value<y.value?{source:y,target:x}:{source:x,target:y})}}i&&k()}function k(){b.sort(function(a,b){return i((a.source.value+a.target.value)/2,(b.source.value+b.target.value)/2)})}var a={},b,c,d,e,f=0,g,h,i;return a.matrix=function(f){return arguments.length?(e=(d=f)&&d.length,b=c=null,a):d},a.padding=function(d){return arguments.length?(f=d,b=c=null,a):f},a.sortGroups=function(d){return arguments.length?(g=d,b=c=null,a):g},a.sortSubgroups=function(c){return arguments.length?(h=c,b=null,a):h},a.sortChords=function(c){return arguments.length?(i=c,b&&k(),a):i},a.chords=function(){return b||j(),b},a.groups=function(){return c||j(),c},a},d3.layout.force=function(){function A(a){return function(b,c,d,e,f){if(b.point!==a){var g=b.cx-a.x,h=b.cy-a.y,i=1/Math.sqrt(g*g+h*h);if((e-c)*i<t){var j=b.charge*i*i;return a.px-=g*j,a.py-=h*j,!0}if(b.point&&isFinite(i)){var j=b.pointCharge*i*i;a.px-=g*j,a.py-=h*j}}return!b.charge}}function B(){var a=v.length,d=w.length,e,f,g,h,i,j,l,m,p;for(f=0;f<d;++f){g=w[f],h=g.source,i=g.target,m=i.x-h.x,p=i.y-h.y;if(j=m*m+p*p)j=n*y[f]*((j=Math.sqrt(j))-x[f])/j,m*=j,p*=j,i.x-=m*(l=h.weight/(i.weight+h.weight)),i.y-=p*l,h.x+=m*(l=1-l),h.y+=p*l}if(l=n*s){m=c[0]/2,p=c[1]/2,f=-1;if(l)while(++f<a)g=v[f],g.x+=(m-g.x)*l,g.y+=(p-g.y)*l}if(r){k(e=d3.geom.quadtree(v),n,z),f=-1;while(++f<a)(g=v[f]).fixed||e.visit(A(g))}f=-1;while(++f<a)g=v[f],g.fixed?(g.x=g.px,g.y=g.py):(g.x-=(g.px-(g.px=g.x))*o,g.y-=(g.py-(g.py=g.y))*o);return b.tick({type:"tick",alpha:n}),(n*=.99)<.005}function C(b){g(f=b),e=a}var a={},b=d3.dispatch("tick"),c=[1,1],d,n,o=.9,p=l,q=m,r=-30,s=.1,t=.8,u,v=[],w=[],x,y,z;return a.on=function(c,d){return b.on(c,d),a},a.nodes=function(b){return arguments.length?(v=b,a):v},a.links=function(b){return arguments.length?(w=b,a):w},a.size=function(b){return arguments.length?(c=b,a):c},a.linkDistance=function(b){return arguments.length?(p=d3.functor(b),a):p},a.distance=a.linkDistance,a.linkStrength=function(b){return arguments.length?(q=d3.functor(b),a):q},a.friction=function(b){return arguments.length?(o=b,a):o},a.charge=function(b){return arguments.length?(r=typeof b=="function"?b:+b,a):r},a.gravity=function(b){return arguments.length?(s=b,a):s},a.theta=function(b){return arguments.length?(t=b,a):t},a.start=function(){function k(a,c){var d=l(b),e=-1,f=d.length,g;while(++e<f)if(!isNaN(g=d[e][a]))return g;return Math.random()*c}function l(){if(!i){i=[];for(d=0;d<e;++d)i[d]=[];for(d=0;d<f;++d){var a=w[d];i[a.source.index].push(a.target),i[a.target.index].push(a.source)}}return i[b]}var b,d,e=v.length,f=w.length,g=c[0],h=c[1],i,j;for(b=0;b<e;++b)(j=v[b]).index=b,j.weight=0;x=[],y=[];for(b=0;b<f;++b)j=w[b],typeof j.source=="number"&&(j.source=v[j.source]),typeof j.target=="number"&&(j.target=v[j.target]),x[b]=p.call(this,j,b),y[b]=q.call(this,j,b),++j.source.weight,++j.target.weight;for(b=0;b<e;++b)j=v[b],isNaN(j.x)&&(j.x=k("x",g)),isNaN(j.y)&&(j.y=k("y",h)),isNaN(j.px)&&(j.px=j.x),isNaN(j.py)&&(j.py=j.y);z=[];if(typeof r=="function")for(b=0;b<e;++b)z[b]=+r.call(this,v[b],b);else for(b=0;b<e;++b)z[b]=r;return a.resume()},a.resume=function(){return n=.1,d3.timer(B),a},a.stop=function(){return n=0,a},a.drag=function(){d||(d=d3.behavior.drag().on("dragstart",C).on("drag",j).on("dragend",i)),this.on("mouseover.force",g).on("mouseout.force",h).call(d)},a};var e,f;d3.layout.partition=function(){function c(a,b,d,e){var f=a.children;a.x=b,a.y=a.depth*e,a.dx=d,a.dy=e;if(f&&(h=f.length)){var g=-1,h,i,j;d=a.value?d/a.value:0;while(++g<h)c(i=f[g],b,j=i.value*d,e),b+=j}}function d(a){var b=a.children,c=0;if(b&&(f=b.length)){var e=-1,f;while(++e<f)c=Math.max(c,d(b[e]))}return 1+c}function e(e,f){var g=a.call(this,e,f);return c(g[0],0,b[0],b[1]/d(g[0])),g}var a=d3.layout.hierarchy(),b=[1,1];return e.size=function(a){return arguments.length?(b=a,e):b},z(e,a)},d3.layout.pie=function(){function f(g,h){var i=g.map(function(b,c){return+a.call(f,b,c)}),j=+(typeof c=="function"?c.apply(this,arguments):c),k=((typeof e=="function"?e.apply(this,arguments):e)-c)/d3.sum(i),l=d3.range(g.length);b!=null&&l.sort(b===n?function(a,b){return i[b]-i[a]}:function(a,c){return b(g[a],g[c])});var m=l.map(function(a){return{data:g[a],value:d=i[a],startAngle:j,endAngle:j+=d*k}});return g.map(function(a,b){return m[l[b]]})}var a=Number,b=n,c=0,e=2*Math.PI;return f.value=function(b){return arguments.length?(a=b,f):a},f.sort=function(a){return arguments.length?(b=a,f):b},f.startAngle=function(a){return arguments.length?(c=a,f):c},f.endAngle=function(a){return arguments.length?(e=a,f):e},f};var n={};d3.layout.stack=function(){function g(h,i){var j=h.map(function(b,c){return a.call(g,b,c)}),k=j.map(function(a,b){return a.map(function(a,b){return[e.call(g,a,b),f.call(g,a,b)]})}),l=b.call(g,k,i);j=d3.permute(j,l),k=d3.permute(k,l);var m=c.call(g,k,i),n=j.length,o=j[0].length,p,q,r;for(q=0;q<o;++q){d.call(g,j[0][q],r=m[q],k[0][q][1]);for(p=1;p<n;++p)d.call(g,j[p][q],r+=k[p-1][q][1],k[p][q][1])}return h}var a=Object,b=r["default"],c=s.zero,d=q,e=o,f=p;return g.values=function(b){return arguments.length?(a=b,g):a},g.order=function(a){return arguments.length?(b=typeof a=="function"?a:r[a],g):b},g.offset=function(a){return arguments.length?(c=typeof a=="function"?a:s[a],g):c},g.x=function(a){return arguments.length?(e=a,g):e},g.y=function(a){return arguments.length?(f=a,g):f},g.out=function(a){return arguments.length?(d=a,g):d},g};var r={"inside-out":function(a){var b=a.length,c,d,e=a.map(t),f=a.map(u),g=d3.range(b).sort(function(a,b){return e[a]-e[b]}),h=0,i=0,j=[],k=[];for(c=0;c<b;++c)d=g[c],h<i?(h+=f[d],j.push(d)):(i+=f[d],k.push(d));return k.reverse().concat(j)},reverse:function(a){return d3.range(a.length).reverse()},"default":function(a){return d3.range(a.length)}},s={silhouette:function(a){var b=a.length,c=a[0].length,d=[],e=0,f,g,h,i=[];for(g=0;g<c;++g){for(f=0,h=0;f<b;f++)h+=a[f][g][1];h>e&&(e=h),d.push(h)}for(g=0;g<c;++g)i[g]=(e-d[g])/2;return i},wiggle:function(a){var b=a.length,c=a[0],d=c.length,e=0,f,g,h,i,j,k,l,m,n,o=[];o[0]=m=n=0;for(g=1;g<d;++g){for(f=0,i=0;f<b;++f)i+=a[f][g][1];for(f=0,j=0,l=c[g][0]-c[g-1][0];f<b;++f){for(h=0,k=(a[f][g][1]-a[f][g-1][1])/(2*l);h<f;++h)k+=(a[h][g][1]-a[h][g-1][1])/l;j+=k*a[f][g][1]}o[g]=m-=i?j/i*l:0,m<n&&(n=m)}for(g=0;g<d;++g)o[g]-=n;return o},expand:function(a){var b=a.length,c=a[0].length,d=1/b,e,f,g,h=[];for(f=0;f<c;++f){for(e=0,g=0;e<b;e++)g+=a[e][f][1];if(g)for(e=0;e<b;e++)a[e][f][1]/=g;else for(e=0;e<b;e++)a[e][f][1]=d}for(f=0;f<c;++f)h[f]=0;return h},zero:function(a){var b=-1,c=a[0].length,d=[];while(++b<c)d[b]=0;return d}};d3.layout.histogram=function(){function e(e,f){var g=[],h=e.map(b,this),i=c.call(this,h,f),j=d.call(this,i,h,f),k,f=-1,l=h.length,m=j.length-1,n=a?1:1/l,o;while(++f<m)k=g[f]=[],k.dx=j[f+1]-(k.x=j[f]),k.y=0;f=-1;while(++f<l)o=h[f],o>=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]));return g}var a=!0,b=Number,c=y,d=w;return e.value=function(a){return arguments.length?(b=a,e):b},e.range=function(a){return arguments.length?(c=d3.functor(a),e):c},e.bins=function(a){return arguments.length?(d=typeof a=="number"?function(b){return x(b,a)}:d3.functor(a),e):d},e.frequency=function(b){return arguments.length?(a=!!b,e):a},e},d3.layout.hierarchy=function(){function e(f,h,i){var j=b.call(g,f,h),k=E?f:{data:f};k.depth=h,i.push(k);if(j&&(m=j.length)){var l=-1,m,n=k.children=[],o=0,p=h+1;while(++l<m)d=e(j[l],p,i),d.parent=k,n.push(d),o+=d.value;a&&n.sort(a),c&&(k.value=o)}else c&&(k.value=+c.call(g,f,h)||0);return k}function f(a,b){var d=a.children,e=0;if(d&&(i=d.length)){var h=-1,i,j=b+1;while(++h<i)e+=f(d[h],j)}else c&&(e=+c.call(g,E?a:a.data,b)||0);return c&&(a.value=e),e}function g(a){var b=[];return e(a,0,b),b}var a=C,b=A,c=B;return g.sort=function(b){return arguments.length?(a=b,g):a},g.children=function(a){return arguments.length?(b=a,g):b},g.value=function(a){return arguments.length?(c=a,g):c},g.revalue=function(a){return f(a,0),a},g};var E=!1;d3.layout.pack=function(){function c(c,d){var e=a.call(this,c,d),f=e[0];f.x=0,f.y=0,M(f);var g=b[0],h=b[1],i=1/Math.max(2*f.r/g,2*f.r/h);return N(f,g/2,h/2,i),e}var a=d3.layout.hierarchy().sort(F),b=[1,1];return c.size=function(a){return arguments.length?(b=a,c):b},z(c,a)},d3.layout.cluster=function(){function d(d,e){var f=a.call(this,d,e),g=f[0],h,i=0,j,k;$(g,function(a){var c=a.children;c&&c.length?(a.x=Q(c),a.y=P(c)):(a.x=h?i+=b(a,h):0,a.y=0,h=a)});var l=R(g),m=S(g),n=l.x-b(l,m)/2,o=m.x+b(m,l)/2;return $(g,function(a){a.x=(a.x-n)/(o-n)*c[0],a.y=(1-a.y/g.y)*c[1]}),f}var a=d3.layout.hierarchy().sort(null).value(null),b=T,c=[1,1];return d.separation=function(a){return arguments.length?(b=a,d):b},d.size=function(a){return arguments.length?(c=a,d):c},z(d,a)},d3.layout.tree=function(){function d(d,e){function h(a,c){var d=a.children,e=a._tree;if(d&&(f=d.length)){var f,g=d[0],i,k=g,l,m=-1;while(++m<f)l=d[m],h(l,i),k=j(l,i,k),i=l;_(a);var n=.5*(g._tree.prelim+l._tree.prelim);c?(e.prelim=c._tree.prelim+b(a,c),e.mod=e.prelim-n):e.prelim=n}else c&&(e.prelim=c._tree.prelim+b(a,c))}function i(a,b){a.x=a._tree.prelim+b;var c=a.children;if(c&&(e=c.length)){var d=-1,e;b+=a._tree.mod;while(++d<e)i(c[d],b)}}function j(a,c,d){if(c){var e=a,f=a,g=c,h=a.parent.children[0],i=e._tree.mod,j=f._tree.mod,k=g._tree.mod,l=h._tree.mod,m;while(g=V(g),e=U(e),g&&e)h=U(h),f=V(f),f._tree.ancestor=a,m=g._tree.prelim+k-e._tree.prelim-i+b(g,e),m>0&&(ba(bb(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!V(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!U(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}var f=a.call(this,d,e),g=f[0];$(g,function(a,b){a._tree={ancestor:a,prelim:0,mod:0,change:0,shift:0,number:b?b._tree.number+1:0}}),h(g),i(g,-g._tree.prelim);var k=W(g,Y),l=W(g,X),m=W(g,Z),n=k.x-b(k,l)/2,o=l.x+b(l,k)/2,p=m.depth||1;return $(g,function(a){a.x=(a.x-n)/(o-n)*c[0],a.y=a.depth/p*c[1],delete a._tree}),f}var a=d3.layout.hierarchy().sort(null).value(null),b=T,c=[1,1];return d.separation=function(a){return arguments.length?(b=a,d):b},d.size=function(a){return arguments.length?(c=a,d):c},z(d,a)},d3.layout.treemap=function(){function i(a,b){var c=-1,d=a.length,e,f;while(++c<d)f=(e=a[c]).value*(b<0?0:b),e.area=isNaN(f)||f<=0?0:f}function j(a){var b=a.children;if(b&&b.length){var c=e(a),d=[],f=b.slice(),g,h=Infinity,k,n=Math.min(c.dx,c.dy),o;i(f,c.dx*c.dy/a.value),d.area=0;while((o=f.length)>0)d.push(g=f[o-1]),d.area+=g.area,(k=l(d,n))<=h?(f.pop(),h=k):(d.area-=d.pop().area,m(d,n,c,!1),n=Math.min(c.dx,c.dy),d.length=d.area=0,h=Infinity);d.length&&(m(d,n,c,!0),d.length=d.area=0),b.forEach(j)}}function k(a){var b=a.children;if(b&&b.length){var c=e(a),d=b.slice(),f,g=[];i(d,c.dx*c.dy/a.value),g.area=0;while(f=d.pop())g.push(f),g.area+=f.area,f.z!=null&&(m(g,f.z?c.dx:c.dy,c,!d.length),g.length=g.area=0);b.forEach(k)}}function l(a,b){var c=a.area,d,e=0,f=Infinity,g=-1,i=a.length;while(++g<i){if(!(d=a[g].area))continue;d<f&&(f=d),d>e&&(e=d)}return c*=c,b*=b,c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function m(a,c,d,e){var f=-1,g=a.length,h=d.x,i=d.y,j=c?b(a.area/c):0,k;if(c==d.dx){if(e||j>d.dy)j=j?d.dy:0;while(++f<g)k=a[f],k.x=h,k.y=i,k.dy=j,h+=k.dx=j?b(k.area/j):0;k.z=!0,k.dx+=d.x+d.dx-h,d.y+=j,d.dy-=j}else{if(e||j>d.dx)j=j?d.dx:0;while(++f<g)k=a[f],k.x=h,k.y=i,k.dx=j,i+=k.dy=j?b(k.area/j):0;k.z=!1,k.dy+=d.y+d.dy-i,d.x+=j,d.dx-=j}}function n(b){var d=g||a(b),e=d[0];return e.x=0,e.y=0,e.dx=c[0],e.dy=c[1],g&&a.revalue(e),i([e],e.dx*e.dy/e.value),(g?k:j)(e),f&&(g=d),d}var a=d3.layout.hierarchy(),b=Math.round,c=[1,1],d=null,e=bc,f=!1,g,h=.5*(1+Math.sqrt(5));return n.size=function(a){return arguments.length?(c=a,n):c},n.padding=function(a){function b(b){var c=a.call(n,b,b.depth);return c==null?bc(b):bd(b,typeof c=="number"?[c,c,c,c]:c)}function c(b){return bd(b,a)}if(!arguments.length)return d;var f;return e=(d=a)==null?bc:(f=typeof a)==="function"?b:f==="number"?(a=[a,a,a,a],c):c,n},n.round=function(a){return arguments.length?(b=a?Math.round:Number,n):b!=Number},n.sticky=function(a){return arguments.length?(f=a,g=null,n):f},n.ratio=function(a){return arguments.length?(h=a,n):h},z(n,a)}})();
  (function() {
  function d3_class(ctor, properties) {
  try {
  for (var key in properties) {
  Object.defineProperty(ctor.prototype, key, {
  value: properties[key],
  enumerable: false
  });
  }
  } catch (e) {
  ctor.prototype = properties;
  }
  }
  function d3_arrayCopy(pseudoarray) {
  var i = -1, n = pseudoarray.length, array = [];
  while (++i < n) array.push(pseudoarray[i]);
  return array;
  }
  function d3_arraySlice(pseudoarray) {
  return Array.prototype.slice.call(pseudoarray);
  }
  function d3_Map() {}
  function d3_identity(d) {
  return d;
  }
  function d3_this() {
  return this;
  }
  function d3_true() {
  return true;
  }
  function d3_functor(v) {
  return typeof v === "function" ? v : function() {
  return v;
  };
  }
  function d3_rebind(target, source, method) {
  return function() {
  var value = method.apply(source, arguments);
  return arguments.length ? target : value;
  };
  }
  function d3_number(x) {
  return x != null && !isNaN(x);
  }
  function d3_zipLength(d) {
  return d.length;
  }
  function d3_splitter(d) {
  return d == null;
  }
  function d3_collapse(s) {
  return s.trim().replace(/\s+/g, " ");
  }
  function d3_range_integerScale(x) {
  var k = 1;
  while (x * k % 1) k *= 10;
  return k;
  }
  function d3_dispatch() {}
  function d3_dispatch_event(dispatch) {
  function event() {
  var z = listeners, i = -1, n = z.length, l;
  while (++i < n) if (l = z[i].on) l.apply(this, arguments);
  return dispatch;
  }
  var listeners = [], listenerByName = new d3_Map;
  event.on = function(name, listener) {
  var l = listenerByName.get(name), i;
  if (arguments.length < 2) return l && l.on;
  if (l) {
  l.on = null;
  listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
  listenerByName.remove(name);
  }
  if (listener) listeners.push(listenerByName.set(name, {
  on: listener
  }));
  return dispatch;
  };
  return event;
  }
  function d3_format_precision(x, p) {
  return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1);
  }
  function d3_format_typeDefault(x) {
  return x + "";
  }
  function d3_format_group(value) {
  var i = value.lastIndexOf("."), f = i >= 0 ? value.substring(i) : (i = value.length, ""), t = [];
  while (i > 0) t.push(value.substring(i -= 3, i + 3));
  return t.reverse().join(",") + f;
  }
  function d3_formatPrefix(d, i) {
  var k = Math.pow(10, Math.abs(8 - i) * 3);
  return {
  scale: i > 8 ? function(d) {
  return d / k;
  } : function(d) {
  return d * k;
  },
  symbol: d
  };
  }
  function d3_ease_clamp(f) {
  return function(t) {
  return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
  };
  }
  function d3_ease_reverse(f) {
  return function(t) {
  return 1 - f(1 - t);
  };
  }
  function d3_ease_reflect(f) {
  return function(t) {
  return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
  };
  }
  function d3_ease_identity(t) {
  return t;
  }
  function d3_ease_poly(e) {
  return function(t) {
  return Math.pow(t, e);
  };
  }
  function d3_ease_sin(t) {
  return 1 - Math.cos(t * Math.PI / 2);
  }
  function d3_ease_exp(t) {
  return Math.pow(2, 10 * (t - 1));
  }
  function d3_ease_circle(t) {
  return 1 - Math.sqrt(1 - t * t);
  }
  function d3_ease_elastic(a, p) {
  var s;
  if (arguments.length < 2) p = .45;
  if (arguments.length < 1) {
  a = 1;
  s = p / 4;
  } else s = p / (2 * Math.PI) * Math.asin(1 / a);
  return function(t) {
  return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p);
  };
  }
  function d3_ease_back(s) {
  if (!s) s = 1.70158;
  return function(t) {
  return t * t * ((s + 1) * t - s);
  };
  }
  function d3_ease_bounce(t) {
  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;
  }
  function d3_eventCancel() {
  d3.event.stopPropagation();
  d3.event.preventDefault();
  }
  function d3_eventSource() {
  var e = d3.event, s;
  while (s = e.sourceEvent) e = s;
  return e;
  }
  function d3_eventDispatch(target) {
  var dispatch = new d3_dispatch, i = 0, n = arguments.length;
  while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
  dispatch.of = function(thiz, argumentz) {
  return function(e1) {
  try {
  var e0 = e1.sourceEvent = d3.event;
  e1.target = target;
  d3.event = e1;
  dispatch[e1.type].apply(thiz, argumentz);
  } finally {
  d3.event = e0;
  }
  };
  };
  return dispatch;
  }
  function d3_transform(m) {
  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;
  if (r0[0] * r1[1] < r1[0] * r0[1]) {
  r0[0] *= -1;
  r0[1] *= -1;
  kx *= -1;
  kz *= -1;
  }
  this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_transformDegrees;
  this.translate = [ m.e, m.f ];
  this.scale = [ kx, ky ];
  this.skew = ky ? Math.atan2(kz, ky) * d3_transformDegrees : 0;
  }
  function d3_transformDot(a, b) {
  return a[0] * b[0] + a[1] * b[1];
  }
  function d3_transformNormalize(a) {
  var k = Math.sqrt(d3_transformDot(a, a));
  if (k) {
  a[0] /= k;
  a[1] /= k;
  }
  return k;
  }
  function d3_transformCombine(a, b, k) {
  a[0] += k * b[0];
  a[1] += k * b[1];
  return a;
  }
  function d3_interpolateByName(name) {
  return name == "transform" ? d3.interpolateTransform : d3.interpolate;
  }
  function d3_uninterpolateNumber(a, b) {
  b = b - (a = +a) ? 1 / (b - a) : 0;
  return function(x) {
  return (x - a) * b;
  };
  }
  function d3_uninterpolateClamp(a, b) {
  b = b - (a = +a) ? 1 / (b - a) : 0;
  return function(x) {
  return Math.max(0, Math.min(1, (x - a) * b));
  };
  }
  function d3_Color() {}
  function d3_rgb(r, g, b) {
  return new d3_Rgb(r, g, b);
  }
  function d3_Rgb(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
  }
  function d3_rgb_hex(v) {
  return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
  }
  function d3_rgb_parse(format, rgb, hsl) {
  var r = 0, g = 0, b = 0, m1, m2, name;
  m1 = /([a-z]+)\((.*)\)/i.exec(format);
  if (m1) {
  m2 = m1[2].split(",");
  switch (m1[1]) {
  case "hsl":
  {
  return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
  }
  case "rgb":
  {
  return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
  }
  }
  }
  if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
  if (format != null && format.charAt(0) === "#") {
  if (format.length === 4) {
  r = format.charAt(1);
  r += r;
  g = format.charAt(2);
  g += g;
  b = format.charAt(3);
  b += b;
  } else if (format.length === 7) {
  r = format.substring(1, 3);
  g = format.substring(3, 5);
  b = format.substring(5, 7);
  }
  r = parseInt(r, 16);
  g = parseInt(g, 16);
  b = parseInt(b, 16);
  }
  return rgb(r, g, b);
  }
  function d3_rgb_hsl(r, g, b) {
  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;
  if (d) {
  s = l < .5 ? d / (max + min) : d / (2 - max - min);
  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;
  h *= 60;
  } else {
  s = h = 0;
  }
  return d3_hsl(h, s, l);
  }
  function d3_rgb_lab(r, g, b) {
  r = d3_rgb_xyz(r);
  g = d3_rgb_xyz(g);
  b = d3_rgb_xyz(b);
  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);
  return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
  }
  function d3_rgb_xyz(r) {
  return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
  }
  function d3_rgb_parseNumber(c) {
  var f = parseFloat(c);
  return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
  }
  function d3_hsl(h, s, l) {
  return new d3_Hsl(h, s, l);
  }
  function d3_Hsl(h, s, l) {
  this.h = h;
  this.s = s;
  this.l = l;
  }
  function d3_hsl_rgb(h, s, l) {
  function v(h) {
  if (h > 360) h -= 360; else if (h < 0) h += 360;
  if (h < 60) return m1 + (m2 - m1) * h / 60;
  if (h < 180) return m2;
  if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
  return m1;
  }
  function vv(h) {
  return Math.round(v(h) * 255);
  }
  var m1, m2;
  h = h % 360;
  if (h < 0) h += 360;
  s = s < 0 ? 0 : s > 1 ? 1 : s;
  l = l < 0 ? 0 : l > 1 ? 1 : l;
  m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
  m1 = 2 * l - m2;
  return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
  }
  function d3_hcl(h, c, l) {
  return new d3_Hcl(h, c, l);
  }
  function d3_Hcl(h, c, l) {
  this.h = h;
  this.c = c;
  this.l = l;
  }
  function d3_hcl_lab(h, c, l) {
  return d3_lab(l, Math.cos(h *= Math.PI / 180) * c, Math.sin(h) * c);
  }
  function d3_lab(l, a, b) {
  return new d3_Lab(l, a, b);
  }
  function d3_Lab(l, a, b) {
  this.l = l;
  this.a = a;
  this.b = b;
  }
  function d3_lab_rgb(l, a, b) {
  var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
  x = d3_lab_xyz(x) * d3_lab_X;
  y = d3_lab_xyz(y) * d3_lab_Y;
  z = d3_lab_xyz(z) * d3_lab_Z;
  return 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));
  }
  function d3_lab_hcl(l, a, b) {
  return d3_hcl(Math.atan2(b, a) / Math.PI * 180, Math.sqrt(a * a + b * b), l);
  }
  function d3_lab_xyz(x) {
  return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
  }
  function d3_xyz_lab(x) {
  return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
  }
  function d3_xyz_rgb(r) {
  return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
  }
  function d3_selection(groups) {
  d3_arraySubclass(groups, d3_selectionPrototype);
  return groups;
  }
  function d3_selection_selector(selector) {
  return function() {
  return d3_select(selector, this);
  };
  }
  function d3_selection_selectorAll(selector) {
  return function() {
  return d3_selectAll(selector, this);
  };
  }
  function d3_selection_attr(name, value) {
  function attrNull() {
  this.removeAttribute(name);
  }
  function attrNullNS() {
  this.removeAttributeNS(name.space, name.local);
  }
  function attrConstant() {
  this.setAttribute(name, value);
  }
  function attrConstantNS() {
  this.setAttributeNS(name.space, name.local, value);
  }
  function attrFunction() {
  var x = value.apply(this, arguments);
  if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
  }
  function attrFunctionNS() {
  var x = value.apply(this, arguments);
  if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
  }
  name = d3.ns.qualify(name);
  return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
  }
  function d3_selection_classedRe(name) {
  return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
  }
  function d3_selection_classed(name, value) {
  function classedConstant() {
  var i = -1;
  while (++i < n) name[i](this, value);
  }
  function classedFunction() {
  var i = -1, x = value.apply(this, arguments);
  while (++i < n) name[i](this, x);
  }
  name = name.trim().split(/\s+/).map(d3_selection_classedName);
  var n = name.length;
  return typeof value === "function" ? classedFunction : classedConstant;
  }
  function d3_selection_classedName(name) {
  var re = d3_selection_classedRe(name);
  return function(node, value) {
  if (c = node.classList) return value ? c.add(name) : c.remove(name);
  var c = node.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
  if (value) {
  re.lastIndex = 0;
  if (!re.test(cv)) {
  cv = d3_collapse(cv + " " + name);
  if (cb) c.baseVal = cv; else node.className = cv;
  }
  } else if (cv) {
  cv = d3_collapse(cv.replace(re, " "));
  if (cb) c.baseVal = cv; else node.className = cv;
  }
  };
  }
  function d3_selection_style(name, value, priority) {
  function styleNull() {
  this.style.removeProperty(name);
  }
  function styleConstant() {
  this.style.setProperty(name, value, priority);
  }
  function styleFunction() {
  var x = value.apply(this, arguments);
  if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
  }
  return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
  }
  function d3_selection_property(name, value) {
  function propertyNull() {
  delete this[name];
  }
  function propertyConstant() {
  this[name] = value;
  }
  function propertyFunction() {
  var x = value.apply(this, arguments);
  if (x == null) delete this[name]; else this[name] = x;
  }
  return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
  }
  function d3_selection_dataNode(data) {
  return {
  __data__: data
  };
  }
  function d3_selection_filter(selector) {
  return function() {
  return d3_selectMatches(this, selector);
  };
  }
  function d3_selection_sortComparator(comparator) {
  if (!arguments.length) comparator = d3.ascending;
  return function(a, b) {
  return comparator(a && a.__data__, b && b.__data__);
  };
  }
  function d3_selection_on(type, listener, capture) {
  function onRemove() {
  var wrapper = this[name];
  if (wrapper) {
  this.removeEventListener(type, wrapper, wrapper.$);
  delete this[name];
  }
  }
  function onAdd() {
  function wrapper(e) {
  var o = d3.event;
  d3.event = e;
  args[0] = node.__data__;
  try {
  listener.apply(node, args);
  } finally {
  d3.event = o;
  }
  }
  var node = this, args = arguments;
  onRemove.call(this);
  this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);
  wrapper._ = listener;
  }
  var name = "__on" + type, i = type.indexOf(".");
  if (i > 0) type = type.substring(0, i);
  return listener ? onAdd : onRemove;
  }
  function d3_selection_each(groups, callback) {
  for (var j = 0, m = groups.length; j < m; j++) {
  for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
  if (node = group[i]) callback(node, i, j);
  }
  }
  return groups;
  }
  function d3_selection_enter(selection) {
  d3_arraySubclass(selection, d3_selection_enterPrototype);
  return selection;
  }
  function d3_transition(groups, id, time) {
  d3_arraySubclass(groups, d3_transitionPrototype);
  var tweens = new d3_Map, event = d3.dispatch("start", "end"), ease = d3_transitionEase;
  groups.id = id;
  groups.time = time;
  groups.tween = function(name, tween) {
  if (arguments.length < 2) return tweens.get(name);
  if (tween == null) tweens.remove(name); else tweens.set(name, tween);
  return groups;
  };
  groups.ease = function(value) {
  if (!arguments.length) return ease;
  ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments);
  return groups;
  };
  groups.each = function(type, listener) {
  if (arguments.length < 2) return d3_transition_each.call(groups, type);
  event.on(type, listener);
  return groups;
  };
  d3.timer(function(elapsed) {
  return d3_selection_each(groups, function(node, i, j) {
  function start(elapsed) {
  if (lock.active > id) return stop();
  lock.active = id;
  tweens.forEach(function(key, value) {
  if (value = value.call(node, d, i)) {
  tweened.push(value);
  }
  });
  event.start.call(node, d, i);
  if (!tick(elapsed)) d3.timer(tick, 0, time);
  return 1;
  }
  function tick(elapsed) {
  if (lock.active !== id) return stop();
  var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;
  while (n > 0) {
  tweened[--n].call(node, e);
  }
  if (t >= 1) {
  stop();
  d3_transitionId = id;
  event.end.call(node, d, i);
  d3_transitionId = 0;
  return 1;
  }
  }
  function stop() {
  if (!--lock.count) delete node.__transition__;
  return 1;
  }
  var tweened = [], delay = node.delay, duration = node.duration, lock = (node = node.node).__transition__ || (node.__transition__ = {
  active: 0,
  count: 0
  }), d = node.__data__;
  ++lock.count;
  delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time);
  });
  }, 0, time);
  return groups;
  }
  function d3_transition_each(callback) {
  var id = d3_transitionId, ease = d3_transitionEase, delay = d3_transitionDelay, duration = d3_transitionDuration;
  d3_transitionId = this.id;
  d3_transitionEase = this.ease();
  d3_selection_each(this, function(node, i, j) {
  d3_transitionDelay = node.delay;
  d3_transitionDuration = node.duration;
  callback.call(node = node.node, node.__data__, i, j);
  });
  d3_transitionId = id;
  d3_transitionEase = ease;
  d3_transitionDelay = delay;
  d3_transitionDuration = duration;
  return this;
  }
  function d3_tweenNull(d, i, a) {
  return a != "" && d3_tweenRemove;
  }
  function d3_tweenByName(b, name) {
  return d3.tween(b, d3_interpolateByName(name));
  }
  function d3_timer_step() {
  var elapsed, now = Date.now(), t1 = d3_timer_queue;
  while (t1) {
  elapsed = now - t1.then;
  if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
  t1 = t1.next;
  }
  var delay = d3_timer_flush() - now;
  if (delay > 24) {
  if (isFinite(delay)) {
  clearTimeout(d3_timer_timeout);
  d3_timer_timeout = setTimeout(d3_timer_step, delay);
  }
  d3_timer_interval = 0;
  } else {
  d3_timer_interval = 1;
  d3_timer_frame(d3_timer_step);
  }
  }
  function d3_timer_flush() {
  var t0 = null, t1 = d3_timer_queue, then = Infinity;
  while (t1) {
  if (t1.flush) {
  delete d3_timer_byId[t1.callback.id];
  t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
  } else {
  then = Math.min(then, t1.then + t1.delay);
  t1 = (t0 = t1).next;
  }
  }
  return then;
  }
  function d3_mousePoint(container, e) {
  var svg = container.ownerSVGElement || container;
  if (svg.createSVGPoint) {
  var point = svg.createSVGPoint();
  if (d3_mouse_bug44083 < 0 && (window.scrollX || window.scrollY)) {
  svg = d3.select(document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0);
  var ctm = svg[0][0].getScreenCTM();
  d3_mouse_bug44083 = !(ctm.f || ctm.e);
  svg.remove();
  }
  if (d3_mouse_bug44083) {
  point.x = e.pageX;
  point.y = e.pageY;
  } else {
  point.x = e.clientX;
  point.y = e.clientY;
  }
  point = point.matrixTransform(container.getScreenCTM().inverse());
  return [ point.x, point.y ];
  }
  var rect = container.getBoundingClientRect();
  return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
  }
  function d3_noop() {}
  function d3_scaleExtent(domain) {
  var start = domain[0], stop = domain[domain.length - 1];
  return start < stop ? [ start, stop ] : [ stop, start ];
  }
  function d3_scaleRange(scale) {
  return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
  }
  function d3_scale_nice(domain, nice) {
  var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
  if (x1 < x0) {
  dx = i0, i0 = i1, i1 = dx;
  dx = x0, x0 = x1, x1 = dx;
  }
  if (nice = nice(x1 - x0)) {
  domain[i0] = nice.floor(x0);
  domain[i1] = nice.ceil(x1);
  }
  return domain;
  }
  function d3_scale_niceDefault() {
  return Math;
  }
  function d3_scale_linear(domain, range, interpolate, clamp) {
  function rescale() {
  var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
  output = linear(domain, range, uninterpolate, interpolate);
  input = linear(range, domain, uninterpolate, d3.interpolate);
  return scale;
  }
  function scale(x) {
  return output(x);
  }
  var output, input;
  scale.invert = function(y) {
  return input(y);
  };
  scale.domain = function(x) {
  if (!arguments.length) return domain;
  domain = x.map(Number);
  return rescale();
  };
  scale.range = function(x) {
  if (!arguments.length) return range;
  range = x;
  return rescale();
  };
  scale.rangeRound = function(x) {
  return scale.range(x).interpolate(d3.interpolateRound);
  };
  scale.clamp = function(x) {
  if (!arguments.length) return clamp;
  clamp = x;
  return rescale();
  };
  scale.interpolate = function(x) {
  if (!arguments.length) return interpolate;
  interpolate = x;
  return rescale();
  };
  scale.ticks = function(m) {
  return d3_scale_linearTicks(domain, m);
  };
  scale.tickFormat = function(m) {
  return d3_scale_linearTickFormat(domain, m);
  };
  scale.nice = function() {
  d3_scale_nice(domain, d3_scale_linearNice);
  return rescale();
  };
  scale.copy = function() {
  return d3_scale_linear(domain, range, interpolate, clamp);
  };
  return rescale();
  }
  function d3_scale_linearRebind(scale, linear) {
  return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
  }
  function d3_scale_linearNice(dx) {
  dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
  return dx && {
  floor: function(x) {
  return Math.floor(x / dx) * dx;
  },
  ceil: function(x) {
  return Math.ceil(x / dx) * dx;
  }
  };
  }
  function d3_scale_linearTickRange(domain, m) {
  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;
  if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
  extent[0] = Math.ceil(extent[0] / step) * step;
  extent[1] = Math.floor(extent[1] / step) * step + step * .5;
  extent[2] = step;
  return extent;
  }
  function d3_scale_linearTicks(domain, m) {
  return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
  }
  function d3_scale_linearTickFormat(domain, m) {
  return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f");
  }
  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
  var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
  return function(x) {
  return i(u(x));
  };
  }
  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
  var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
  if (domain[k] < domain[0]) {
  domain = domain.slice().reverse();
  range = range.slice().reverse();
  }
  while (++j <= k) {
  u.push(uninterpolate(domain[j - 1], domain[j]));
  i.push(interpolate(range[j - 1], range[j]));
  }
  return function(x) {
  var j = d3.bisect(domain, x, 1, k) - 1;
  return i[j](u[j](x));
  };
  }
  function d3_scale_log(linear, log) {
  function scale(x) {
  return linear(log(x));
  }
  var pow = log.pow;
  scale.invert = function(x) {
  return pow(linear.invert(x));
  };
  scale.domain = function(x) {
  if (!arguments.length) return linear.domain().map(pow);
  log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;
  pow = log.pow;
  linear.domain(x.map(log));
  return scale;
  };
  scale.nice = function() {
  linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
  return scale;
  };
  scale.ticks = function() {
  var extent = d3_scaleExtent(linear.domain()), ticks = [];
  if (extent.every(isFinite)) {
  var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]);
  if (log === d3_scale_logn) {
  ticks.push(pow(i));
  for (; i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
  } else {
  for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);
  ticks.push(pow(i));
  }
  for (i = 0; ticks[i] < u; i++) {}
  for (j = ticks.length; ticks[j - 1] > v; j--) {}
  ticks = ticks.slice(i, j);
  }
  return ticks;
  };
  scale.tickFormat = function(n, format) {
  if (arguments.length < 2) format = d3_scale_logFormat;
  if (arguments.length < 1) return format;
  var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12, Math.floor) : (e = 1e-12, Math.ceil), e;
  return function(d) {
  return d / pow(f(log(d) + e)) <= k ? format(d) : "";
  };
  };
  scale.copy = function() {
  return d3_scale_log(linear.copy(), log);
  };
  return d3_scale_linearRebind(scale, linear);
  }
  function d3_scale_logp(x) {
  return Math.log(x < 0 ? 0 : x) / Math.LN10;
  }
  function d3_scale_logn(x) {
  return -Math.log(x > 0 ? 0 : -x) / Math.LN10;
  }
  function d3_scale_pow(linear, exponent) {
  function scale(x) {
  return linear(powp(x));
  }
  var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
  scale.invert = function(x) {
  return powb(linear.invert(x));
  };
  scale.domain = function(x) {
  if (!arguments.length) return linear.domain().map(powb);
  linear.domain(x.map(powp));
  return scale;
  };
  scale.ticks = function(m) {
  return d3_scale_linearTicks(scale.domain(), m);
  };
  scale.tickFormat = function(m) {
  return d3_scale_linearTickFormat(scale.domain(), m);
  };
  scale.nice = function() {
  return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
  };
  scale.exponent = function(x) {
  if (!arguments.length) return exponent;
  var domain = scale.domain();
  powp = d3_scale_powPow(exponent = x);
  powb = d3_scale_powPow(1 / exponent);
  return scale.domain(domain);
  };
  scale.copy = function() {
  return d3_scale_pow(linear.copy(), exponent);
  };
  return d3_scale_linearRebind(scale, linear);
  }
  function d3_scale_powPow(e) {
  return function(x) {
  return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
  };
  }
  function d3_scale_ordinal(domain, ranger) {
  function scale(x) {
  return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];
  }
  function steps(start, step) {
  return d3.range(domain.length).map(function(i) {
  return start + step * i;
  });
  }
  var index, range, rangeBand;
  scale.domain = function(x) {
  if (!arguments.length) return domain;
  domain = [];
  index = new d3_Map;
  var i = -1, n = x.length, xi;
  while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
  return scale[ranger.t].apply(scale, ranger.a);
  };
  scale.range = function(x) {
  if (!arguments.length) return range;
  range = x;
  rangeBand = 0;
  ranger = {
  t: "range",
  a: arguments
  };
  return scale;
  };
  scale.rangePoints = function(x, padding) {
  if (arguments.length < 2) padding = 0;
  var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
  range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
  rangeBand = 0;
  ranger = {
  t: "rangePoints",
  a: arguments
  };
  return scale;
  };
  scale.rangeBands = function(x, padding, outerPadding) {
  if (arguments.length < 2) padding = 0;
  if (arguments.length < 3) outerPadding = padding;
  var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
  range = steps(start + step * outerPadding, step);
  if (reverse) range.reverse();
  rangeBand = step * (1 - padding);
  ranger = {
  t: "rangeBands",
  a: arguments
  };
  return scale;
  };
  scale.rangeRoundBands = function(x, padding, outerPadding) {
  if (arguments.length < 2) padding = 0;
  if (arguments.length < 3) outerPadding = padding;
  var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
  range = steps(start + Math.round(error / 2), step);
  if (reverse) range.reverse();
  rangeBand = Math.round(step * (1 - padding));
  ranger = {
  t: "rangeRoundBands",
  a: arguments
  };
  return scale;
  };
  scale.rangeBand = function() {
  return rangeBand;
  };
  scale.rangeExtent = function() {
  return d3_scaleExtent(ranger.a[0]);
  };
  scale.copy = function() {
  return d3_scale_ordinal(domain, ranger);
  };
  return scale.domain(domain);
  }
  function d3_scale_quantile(domain, range) {
  function rescale() {
  var k = 0, n = domain.length, q = range.length;
  thresholds = [];
  while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
  return scale;
  }
  function scale(x) {
  if (isNaN(x = +x)) return NaN;
  return range[d3.bisect(thresholds, x)];
  }
  var thresholds;
  scale.domain = function(x) {
  if (!arguments.length) return domain;
  domain = x.filter(function(d) {
  return !isNaN(d);
  }).sort(d3.ascending);
  return rescale();
  };
  scale.range = function(x) {
  if (!arguments.length) return range;
  range = x;
  return rescale();
  };
  scale.quantiles = function() {
  return thresholds;
  };
  scale.copy = function() {
  return d3_scale_quantile(domain, range);
  };
  return rescale();
  }
  function d3_scale_quantize(x0, x1, range) {
  function scale(x) {
  return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
  }
  function rescale() {
  kx = range.length / (x1 - x0);
  i = range.length - 1;
  return scale;
  }
  var kx, i;
  scale.domain = function(x) {
  if (!arguments.length) return [ x0, x1 ];
  x0 = +x[0];
  x1 = +x[x.length - 1];
  return rescale();
  };
  scale.range = function(x) {
  if (!arguments.length) return range;
  range = x;
  return rescale();
  };
  scale.copy = function() {
  return d3_scale_quantize(x0, x1, range);
  };
  return rescale();
  }
  function d3_scale_threshold(domain, range) {
  function scale(x) {
  return range[d3.bisect(domain, x)];
  }
  scale.domain = function(_) {
  if (!arguments.length) return domain;
  domain = _;
  return scale;
  };
  scale.range = function(_) {
  if (!arguments.length) return range;
  range = _;
  return scale;
  };
  scale.copy = function() {
  return d3_scale_threshold(domain, range);
  };
  return scale;
  }
  function d3_scale_identity(domain) {
  function identity(x) {
  return +x;
  }
  identity.invert = identity;
  identity.domain = identity.range = function(x) {
  if (!arguments.length) return domain;
  domain = x.map(identity);
  return identity;
  };
  identity.ticks = function(m) {
  return d3_scale_linearTicks(domain, m);
  };
  identity.tickFormat = function(m) {
  return d3_scale_linearTickFormat(domain, m);
  };
  identity.copy = function() {
  return d3_scale_identity(domain);
  };
  return identity;
  }
  function d3_svg_arcInnerRadius(d) {
  return d.innerRadius;
  }
  function d3_svg_arcOuterRadius(d) {
  return d.outerRadius;
  }
  function d3_svg_arcStartAngle(d) {
  return d.startAngle;
  }
  function d3_svg_arcEndAngle(d) {
  return d.endAngle;
  }
  function d3_svg_line(projection) {
  function line(data) {
  function segment() {
  segments.push("M", interpolate(projection(points), tension));
  }
  var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
  while (++i < n) {
  if (defined.call(this, d = data[i], i)) {
  points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
  } else if (points.length) {
  segment();
  points = [];
  }
  }
  if (points.length) segment();
  return segments.length ? segments.join("") : null;
  }
  var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
  line.x = function(_) {
  if (!arguments.length) return x;
  x = _;
  return line;
  };
  line.y = function(_) {
  if (!arguments.length) return y;
  y = _;
  return line;
  };
  line.defined = function(_) {
  if (!arguments.length) return defined;
  defined = _;
  return line;
  };
  line.interpolate = function(_) {
  if (!arguments.length) return interpolateKey;
  if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
  return line;
  };
  line.tension = function(_) {
  if (!arguments.length) return tension;
  tension = _;
  return line;
  };
  return line;
  }
  function d3_svg_lineX(d) {
  return d[0];
  }
  function d3_svg_lineY(d) {
  return d[1];
  }
  function d3_svg_lineLinear(points) {
  return points.join("L");
  }
  function d3_svg_lineLinearClosed(points) {
  return d3_svg_lineLinear(points) + "Z";
  }
  function d3_svg_lineStepBefore(points) {
  var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
  while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
  return path.join("");
  }
  function d3_svg_lineStepAfter(points) {
  var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
  while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
  return path.join("");
  }
  function d3_svg_lineCardinalOpen(points, tension) {
  return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
  }
  function d3_svg_lineCardinalClosed(points, tension) {
  return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
  }
  function d3_svg_lineCardinal(points, tension, closed) {
  return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
  }
  function d3_svg_lineHermite(points, tangents) {
  if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
  return d3_svg_lineLinear(points);
  }
  var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
  if (quad) {
  path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
  p0 = points[1];
  pi = 2;
  }
  if (tangents.length > 1) {
  t = tangents[1];
  p = points[pi];
  pi++;
  path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
  for (var i = 2; i < tangents.length; i++, pi++) {
  p = points[pi];
  t = tangents[i];
  path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
  }
  }
  if (quad) {
  var lp = points[pi];
  path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
  }
  return path;
  }
  function d3_svg_lineCardinalTangents(points, tension) {
  var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
  while (++i < n) {
  p0 = p1;
  p1 = p2;
  p2 = points[i];
  tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
  }
  return tangents;
  }
  function d3_svg_lineBasis(points) {
  if (points.length < 3) return d3_svg_lineLinear(points);
  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 ];
  d3_svg_lineBasisBezier(path, px, py);
  while (++i < n) {
  pi = points[i];
  px.shift();
  px.push(pi[0]);
  py.shift();
  py.push(pi[1]);
  d3_svg_lineBasisBezier(path, px, py);
  }
  i = -1;
  while (++i < 2) {
  px.shift();
  px.push(pi[0]);
  py.shift();
  py.push(pi[1]);
  d3_svg_lineBasisBezier(path, px, py);
  }
  return path.join("");
  }
  function d3_svg_lineBasisOpen(points) {
  if (points.length < 4) return d3_svg_lineLinear(points);
  var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
  while (++i < 3) {
  pi = points[i];
  px.push(pi[0]);
  py.push(pi[1]);
  }
  path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
  --i;
  while (++i < n) {
  pi = points[i];
  px.shift();
  px.push(pi[0]);
  py.shift();
  py.push(pi[1]);
  d3_svg_lineBasisBezier(path, px, py);
  }
  return path.join("");
  }
  function d3_svg_lineBasisClosed(points) {
  var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
  while (++i < 4) {
  pi = points[i % n];
  px.push(pi[0]);
  py.push(pi[1]);
  }
  path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
  --i;
  while (++i < m) {
  pi = points[i % n];
  px.shift();
  px.push(pi[0]);
  py.shift();
  py.push(pi[1]);
  d3_svg_lineBasisBezier(path, px, py);
  }
  return path.join("");
  }
  function d3_svg_lineBundle(points, tension) {
  var n = points.length - 1;
  if (n) {
  var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
  while (++i <= n) {
  p = points[i];
  t = i / n;
  p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
  p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
  }
  }
  return d3_svg_lineBasis(points);
  }
  function d3_svg_lineDot4(a, b) {
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  }
  function d3_svg_lineBasisBezier(path, x, y) {
  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));
  }
  function d3_svg_lineSlope(p0, p1) {
  return (p1[1] - p0[1]) / (p1[0] - p0[0]);
  }
  function d3_svg_lineFiniteDifferences(points) {
  var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
  while (++i < j) {
  m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
  }
  m[i] = d;
  return m;
  }
  function d3_svg_lineMonotoneTangents(points) {
  var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
  while (++i < j) {
  d = d3_svg_lineSlope(points[i], points[i + 1]);
  if (Math.abs(d) < 1e-6) {
  m[i] = m[i + 1] = 0;
  } else {
  a = m[i] / d;
  b = m[i + 1] / d;
  s = a * a + b * b;
  if (s > 9) {
  s = d * 3 / Math.sqrt(s);
  m[i] = s * a;
  m[i + 1] = s * b;
  }
  }
  }
  i = -1;
  while (++i <= j) {
  s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
  tangents.push([ s || 0, m[i] * s || 0 ]);
  }
  return tangents;
  }
  function d3_svg_lineMonotone(points) {
  return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
  }
  function d3_svg_lineRadial(points) {
  var point, i = -1, n = points.length, r, a;
  while (++i < n) {
  point = points[i];
  r = point[0];
  a = point[1] + d3_svg_arcOffset;
  point[0] = r * Math.cos(a);
  point[1] = r * Math.sin(a);
  }
  return points;
  }
  function d3_svg_area(projection) {
  function area(data) {
  function segment() {
  segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
  }
  var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
  return x;
  } : d3_functor(x1), fy1 = y0 === y1 ? function() {
  return y;
  } : d3_functor(y1), x, y;
  while (++i < n) {
  if (defined.call(this, d = data[i], i)) {
  points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
  points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
  } else if (points0.length) {
  segment();
  points0 = [];
  points1 = [];
  }
  }
  if (points0.length) segment();
  return segments.length ? segments.join("") : null;
  }
  var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
  area.x = function(_) {
  if (!arguments.length) return x1;
  x0 = x1 = _;
  return area;
  };
  area.x0 = function(_) {
  if (!arguments.length) return x0;
  x0 = _;
  return area;
  };
  area.x1 = function(_) {
  if (!arguments.length) return x1;
  x1 = _;
  return area;
  };
  area.y = function(_) {
  if (!arguments.length) return y1;
  y0 = y1 = _;
  return area;
  };
  area.y0 = function(_) {
  if (!arguments.length) return y0;
  y0 = _;
  return area;
  };
  area.y1 = function(_) {
  if (!arguments.length) return y1;
  y1 = _;
  return area;
  };
  area.defined = function(_) {
  if (!arguments.length) return defined;
  defined = _;
  return area;
  };
  area.interpolate = function(_) {
  if (!arguments.length) return interpolateKey;
  if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
  interpolateReverse = interpolate.reverse || interpolate;
  L = interpolate.closed ? "M" : "L";
  return area;
  };
  area.tension = function(_) {
  if (!arguments.length) return tension;
  tension = _;
  return area;
  };
  return area;
  }
  function d3_svg_chordSource(d) {
  return d.source;
  }
  function d3_svg_chordTarget(d) {
  return d.target;
  }
  function d3_svg_chordRadius(d) {
  return d.radius;
  }
  function d3_svg_chordStartAngle(d) {
  return d.startAngle;
  }
  function d3_svg_chordEndAngle(d) {
  return d.endAngle;
  }
  function d3_svg_diagonalProjection(d) {
  return [ d.x, d.y ];
  }
  function d3_svg_diagonalRadialProjection(projection) {
  return function() {
  var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
  return [ r * Math.cos(a), r * Math.sin(a) ];
  };
  }
  function d3_svg_symbolSize() {
  return 64;
  }
  function d3_svg_symbolType() {
  return "circle";
  }
  function d3_svg_symbolCircle(size) {
  var r = Math.sqrt(size / Math.PI);
  return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
  }
  function d3_svg_axisX(selection, x) {
  selection.attr("transform", function(d) {
  return "translate(" + x(d) + ",0)";
  });
  }
  function d3_svg_axisY(selection, y) {
  selection.attr("transform", function(d) {
  return "translate(0," + y(d) + ")";
  });
  }
  function d3_svg_axisSubdivide(scale, ticks, m) {
  subticks = [];
  if (m && ticks.length > 1) {
  var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;
  while (++i < n) {
  for (j = m; --j > 0; ) {
  if ((v = +ticks[i] - j * d) >= extent[0]) {
  subticks.push(v);
  }
  }
  }
  for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {
  subticks.push(v);
  }
  }
  return subticks;
  }
  function d3_behavior_zoomDelta() {
  if (!d3_behavior_zoomDiv) {
  d3_behavior_zoomDiv = d3.select("body").append("div").style("visibility", "hidden").style("top", 0).style("height", 0).style("width", 0).style("overflow-y", "scroll").append("div").style("height", "2000px").node().parentNode;
  }
  var e = d3.event, delta;
  try {
  d3_behavior_zoomDiv.scrollTop = 1e3;
  d3_behavior_zoomDiv.dispatchEvent(e);
  delta = 1e3 - d3_behavior_zoomDiv.scrollTop;
  } catch (error) {
  delta = e.wheelDelta || -e.detail * 5;
  }
  return delta;
  }
  function d3_layout_bundlePath(link) {
  var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
  while (start !== lca) {
  start = start.parent;
  points.push(start);
  }
  var k = points.length;
  while (end !== lca) {
  points.splice(k, 0, end);
  end = end.parent;
  }
  return points;
  }
  function d3_layout_bundleAncestors(node) {
  var ancestors = [], parent = node.parent;
  while (parent != null) {
  ancestors.push(node);
  node = parent;
  parent = parent.parent;
  }
  ancestors.push(node);
  return ancestors;
  }
  function d3_layout_bundleLeastCommonAncestor(a, b) {
  if (a === b) return a;
  var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
  while (aNode === bNode) {
  sharedNode = aNode;
  aNode = aNodes.pop();
  bNode = bNodes.pop();
  }
  return sharedNode;
  }
  function d3_layout_forceDragstart(d) {
  d.fixed |= 2;
  }
  function d3_layout_forceDragend(d) {
  d.fixed &= 1;
  }
  function d3_layout_forceMouseover(d) {
  d.fixed |= 4;
  }
  function d3_layout_forceMouseout(d) {
  d.fixed &= 3;
  }
  function d3_layout_forceAccumulate(quad, alpha, charges) {
  var cx = 0, cy = 0;
  quad.charge = 0;
  if (!quad.leaf) {
  var nodes = quad.nodes, n = nodes.length, i = -1, c;
  while (++i < n) {
  c = nodes[i];
  if (c == null) continue;
  d3_layout_forceAccumulate(c, alpha, charges);
  quad.charge += c.charge;
  cx += c.charge * c.cx;
  cy += c.charge * c.cy;
  }
  }
  if (quad.point) {
  if (!quad.leaf) {
  quad.point.x += Math.random() - .5;
  quad.point.y += Math.random() - .5;
  }
  var k = alpha * charges[quad.point.index];
  quad.charge += quad.pointCharge = k;
  cx += k * quad.point.x;
  cy += k * quad.point.y;
  }
  quad.cx = cx / quad.charge;
  quad.cy = cy / quad.charge;
  }
  function d3_layout_forceLinkDistance(link) {
  return 20;
  }
  function d3_layout_forceLinkStrength(link) {
  return 1;
  }
  function d3_layout_stackX(d) {
  return d.x;
  }
  function d3_layout_stackY(d) {
  return d.y;
  }
  function d3_layout_stackOut(d, y0, y) {
  d.y0 = y0;
  d.y = y;
  }
  function d3_layout_stackOrderDefault(data) {
  return d3.range(data.length);
  }
  function d3_layout_stackOffsetZero(data) {
  var j = -1, m = data[0].length, y0 = [];
  while (++j < m) y0[j] = 0;
  return y0;
  }
  function d3_layout_stackMaxIndex(array) {
  var i = 1, j = 0, v = array[0][1], k, n = array.length;
  for (; i < n; ++i) {
  if ((k = array[i][1]) > v) {
  j = i;
  v = k;
  }
  }
  return j;
  }
  function d3_layout_stackReduceSum(d) {
  return d.reduce(d3_layout_stackSum, 0);
  }
  function d3_layout_stackSum(p, d) {
  return p + d[1];
  }
  function d3_layout_histogramBinSturges(range, values) {
  return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
  }
  function d3_layout_histogramBinFixed(range, n) {
  var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
  while (++x <= n) f[x] = m * x + b;
  return f;
  }
  function d3_layout_histogramRange(values) {
  return [ d3.min(values), d3.max(values) ];
  }
  function d3_layout_hierarchyRebind(object, hierarchy) {
  d3.rebind(object, hierarchy, "sort", "children", "value");
  object.links = d3_layout_hierarchyLinks;
  object.nodes = function(d) {
  d3_layout_hierarchyInline = true;
  return (object.nodes = object)(d);
  };
  return object;
  }
  function d3_layout_hierarchyChildren(d) {
  return d.children;
  }
  function d3_layout_hierarchyValue(d) {
  return d.value;
  }
  function d3_layout_hierarchySort(a, b) {
  return b.value - a.value;
  }
  function d3_layout_hierarchyLinks(nodes) {
  return d3.merge(nodes.map(function(parent) {
  return (parent.children || []).map(function(child) {
  return {
  source: parent,
  target: child
  };
  });
  }));
  }
  function d3_layout_packSort(a, b) {
  return a.value - b.value;
  }
  function d3_layout_packInsert(a, b) {
  var c = a._pack_next;
  a._pack_next = b;
  b._pack_prev = a;
  b._pack_next = c;
  c._pack_prev = b;
  }
  function d3_layout_packSplice(a, b) {
  a._pack_next = b;
  b._pack_prev = a;
  }
  function d3_layout_packIntersects(a, b) {
  var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
  return dr * dr - dx * dx - dy * dy > .001;
  }
  function d3_layout_packSiblings(node) {
  function bound(node) {
  xMin = Math.min(node.x - node.r, xMin);
  xMax = Math.max(node.x + node.r, xMax);
  yMin = Math.min(node.y - node.r, yMin);
  yMax = Math.max(node.y + node.r, yMax);
  }
  if (!(nodes = node.children) || !(n = nodes.length)) return;
  var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
  nodes.forEach(d3_layout_packLink);
  a = nodes[0];
  a.x = -a.r;
  a.y = 0;
  bound(a);
  if (n > 1) {
  b = nodes[1];
  b.x = b.r;
  b.y = 0;
  bound(b);
  if (n > 2) {
  c = nodes[2];
  d3_layout_packPlace(a, b, c);
  bound(c);
  d3_layout_packInsert(a, c);
  a._pack_prev = c;
  d3_layout_packInsert(c, b);
  b = a._pack_next;
  for (i = 3; i < n; i++) {
  d3_layout_packPlace(a, b, c = nodes[i]);
  var isect = 0, s1 = 1, s2 = 1;
  for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
  if (d3_layout_packIntersects(j, c)) {
  isect = 1;
  break;
  }
  }
  if (isect == 1) {
  for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
  if (d3_layout_packIntersects(k, c)) {
  break;
  }
  }
  }
  if (isect) {
  if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
  i--;
  } else {
  d3_layout_packInsert(a, c);
  b = c;
  bound(c);
  }
  }
  }
  }
  var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
  for (i = 0; i < n; i++) {
  c = nodes[i];
  c.x -= cx;
  c.y -= cy;
  cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
  }
  node.r = cr;
  nodes.forEach(d3_layout_packUnlink);
  }
  function d3_layout_packLink(node) {
  node._pack_next = node._pack_prev = node;
  }
  function d3_layout_packUnlink(node) {
  delete node._pack_next;
  delete node._pack_prev;
  }
  function d3_layout_packTransform(node, x, y, k) {
  var children = node.children;
  node.x = x += k * node.x;
  node.y = y += k * node.y;
  node.r *= k;
  if (children) {
  var i = -1, n = children.length;
  while (++i < n) d3_layout_packTransform(children[i], x, y, k);
  }
  }
  function d3_layout_packPlace(a, b, c) {
  var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
  if (db && (dx || dy)) {
  var da = b.r + c.r, dc = dx * dx + dy * dy;
  da *= da;
  db *= db;
  var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
  c.x = a.x + x * dx + y * dy;
  c.y = a.y + x * dy - y * dx;
  } else {
  c.x = a.x + db;
  c.y = a.y;
  }
  }
  function d3_layout_clusterY(children) {
  return 1 + d3.max(children, function(child) {
  return child.y;
  });
  }
  function d3_layout_clusterX(children) {
  return children.reduce(function(x, child) {
  return x + child.x;
  }, 0) / children.length;
  }
  function d3_layout_clusterLeft(node) {
  var children = node.children;
  return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
  }
  function d3_layout_clusterRight(node) {
  var children = node.children, n;
  return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
  }
  function d3_layout_treeSeparation(a, b) {
  return a.parent == b.parent ? 1 : 2;
  }
  function d3_layout_treeLeft(node) {
  var children = node.children;
  return children && children.length ? children[0] : node._tree.thread;
  }
  function d3_layout_treeRight(node) {
  var children = node.children, n;
  return children && (n = children.length) ? children[n - 1] : node._tree.thread;
  }
  function d3_layout_treeSearch(node, compare) {
  var children = node.children;
  if (children && (n = children.length)) {
  var child, n, i = -1;
  while (++i < n) {
  if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
  node = child;
  }
  }
  }
  return node;
  }
  function d3_layout_treeRightmost(a, b) {
  return a.x - b.x;
  }
  function d3_layout_treeLeftmost(a, b) {
  return b.x - a.x;
  }
  function d3_layout_treeDeepest(a, b) {
  return a.depth - b.depth;
  }
  function d3_layout_treeVisitAfter(node, callback) {
  function visit(node, previousSibling) {
  var children = node.children;
  if (children && (n = children.length)) {
  var child, previousChild = null, i = -1, n;
  while (++i < n) {
  child = children[i];
  visit(child, previousChild);
  previousChild = child;
  }
  }
  callback(node, previousSibling);
  }
  visit(node, null);
  }
  function d3_layout_treeShift(node) {
  var shift = 0, change = 0, children = node.children, i = children.length, child;
  while (--i >= 0) {
  child = children[i]._tree;
  child.prelim += shift;
  child.mod += shift;
  shift += child.shift + (change += child.change);
  }
  }
  function d3_layout_treeMove(ancestor, node, shift) {
  ancestor = ancestor._tree;
  node = node._tree;
  var change = shift / (node.number - ancestor.number);
  ancestor.change += change;
  node.change -= change;
  node.shift += shift;
  node.prelim += shift;
  node.mod += shift;
  }
  function d3_layout_treeAncestor(vim, node, ancestor) {
  return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
  }
  function d3_layout_treemapPadNull(node) {
  return {
  x: node.x,
  y: node.y,
  dx: node.dx,
  dy: node.dy
  };
  }
  function d3_layout_treemapPad(node, padding) {
  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];
  if (dx < 0) {
  x += dx / 2;
  dx = 0;
  }
  if (dy < 0) {
  y += dy / 2;
  dy = 0;
  }
  return {
  x: x,
  y: y,
  dx: dx,
  dy: dy
  };
  }
  function d3_dsv(delimiter, mimeType) {
  function dsv(url, callback) {
  d3.text(url, mimeType, function(text) {
  callback(text && dsv.parse(text));
  });
  }
  function formatRow(row) {
  return row.map(formatValue).join(delimiter);
  }
  function formatValue(text) {
  return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
  }
  var reParse = new RegExp("\r\n|[" + delimiter + "\r\n]", "g"), reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
  dsv.parse = function(text) {
  var header;
  return dsv.parseRows(text, function(row, i) {
  if (i) {
  var o = {}, j = -1, m = header.length;
  while (++j < m) o[header[j]] = row[j];
  return o;
  } else {
  header = row;
  return null;
  }
  });
  };
  dsv.parseRows = function(text, f) {
  function token() {
  if (reParse.lastIndex >= text.length) return EOF;
  if (eol) {
  eol = false;
  return EOL;
  }
  var j = reParse.lastIndex;
  if (text.charCodeAt(j) === 34) {
  var i = j;
  while (i++ < text.length) {
  if (text.charCodeAt(i) === 34) {
  if (text.charCodeAt(i + 1) !== 34) break;
  i++;
  }
  }
  reParse.lastIndex = i + 2;
  var c = text.charCodeAt(i + 1);
  if (c === 13) {
  eol = true;
  if (text.charCodeAt(i + 2) === 10) reParse.lastIndex++;
  } else if (c === 10) {
  eol = true;
  }
  return text.substring(j + 1, i).replace(/""/g, '"');
  }
  var m = reParse.exec(text);
  if (m) {
  eol = m[0].charCodeAt(0) !== delimiterCode;
  return text.substring(j, m.index);
  }
  reParse.lastIndex = text.length;
  return text.substring(j);
  }
  var EOL = {}, EOF = {}, rows = [], n = 0, t, eol;
  reParse.lastIndex = 0;
  while ((t = token()) !== EOF) {
  var a = [];
  while (t !== EOL && t !== EOF) {
  a.push(t);
  t = token();
  }
  if (f && !(a = f(a, n++))) continue;
  rows.push(a);
  }
  return rows;
  };
  dsv.format = function(rows) {
  return rows.map(formatRow).join("\n");
  };
  return dsv;
  }
  function d3_geo_type(types, defaultValue) {
  return function(object) {
  return object && types.hasOwnProperty(object.type) ? types[object.type](object) : defaultValue;
  };
  }
  function d3_path_circle(radius) {
  return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + +2 * radius + "z";
  }
  function d3_geo_bounds(o, f) {
  if (d3_geo_boundsTypes.hasOwnProperty(o.type)) d3_geo_boundsTypes[o.type](o, f);
  }
  function d3_geo_boundsFeature(o, f) {
  d3_geo_bounds(o.geometry, f);
  }
  function d3_geo_boundsFeatureCollection(o, f) {
  for (var a = o.features, i = 0, n = a.length; i < n; i++) {
  d3_geo_bounds(a[i].geometry, f);
  }
  }
  function d3_geo_boundsGeometryCollection(o, f) {
  for (var a = o.geometries, i = 0, n = a.length; i < n; i++) {
  d3_geo_bounds(a[i], f);
  }
  }
  function d3_geo_boundsLineString(o, f) {
  for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
  f.apply(null, a[i]);
  }
  }
  function d3_geo_boundsMultiLineString(o, f) {
  for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
  for (var b = a[i], j = 0, m = b.length; j < m; j++) {
  f.apply(null, b[j]);
  }
  }
  }
  function d3_geo_boundsMultiPolygon(o, f) {
  for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
  for (var b = a[i][0], j = 0, m = b.length; j < m; j++) {
  f.apply(null, b[j]);
  }
  }
  }
  function d3_geo_boundsPoint(o, f) {
  f.apply(null, o.coordinates);
  }
  function d3_geo_boundsPolygon(o, f) {
  for (var a = o.coordinates[0], i = 0, n = a.length; i < n; i++) {
  f.apply(null, a[i]);
  }
  }
  function d3_geo_greatArcSource(d) {
  return d.source;
  }
  function d3_geo_greatArcTarget(d) {
  return d.target;
  }
  function d3_geo_greatArcInterpolator() {
  function interpolate(t) {
  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;
  return [ Math.atan2(y, x) / d3_geo_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_geo_radians ];
  }
  var x0, y0, cy0, sy0, kx0, ky0, x1, y1, cy1, sy1, kx1, ky1, d, k;
  interpolate.distance = function() {
  if (d == null) k = 1 / Math.sin(d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))));
  return d;
  };
  interpolate.source = function(_) {
  var cx0 = Math.cos(x0 = _[0] * d3_geo_radians), sx0 = Math.sin(x0);
  cy0 = Math.cos(y0 = _[1] * d3_geo_radians);
  sy0 = Math.sin(y0);
  kx0 = cy0 * cx0;
  ky0 = cy0 * sx0;
  d = null;
  return interpolate;
  };
  interpolate.target = function(_) {
  var cx1 = Math.cos(x1 = _[0] * d3_geo_radians), sx1 = Math.sin(x1);
  cy1 = Math.cos(y1 = _[1] * d3_geo_radians);
  sy1 = Math.sin(y1);
  kx1 = cy1 * cx1;
  ky1 = cy1 * sx1;
  d = null;
  return interpolate;
  };
  return interpolate;
  }
  function d3_geo_greatArcInterpolate(a, b) {
  var i = d3_geo_greatArcInterpolator().source(a).target(b);
  i.distance();
  return i;
  }
  function d3_geom_contourStart(grid) {
  var x = 0, y = 0;
  while (true) {
  if (grid(x, y)) {
  return [ x, y ];
  }
  if (x === 0) {
  x = y + 1;
  y = 0;
  } else {
  x = x - 1;
  y = y + 1;
  }
  }
  }
  function d3_geom_hullCCW(i1, i2, i3, v) {
  var t, a, b, c, d, e, f;
  t = v[i1];
  a = t[0];
  b = t[1];
  t = v[i2];
  c = t[0];
  d = t[1];
  t = v[i3];
  e = t[0];
  f = t[1];
  return (f - b) * (c - a) - (d - b) * (e - a) > 0;
  }
  function d3_geom_polygonInside(p, a, b) {
  return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
  }
  function d3_geom_polygonIntersect(c, d, a, b) {
  var x1 = c[0], x2 = d[0], x3 = a[0], x4 = b[0], y1 = c[1], y2 = d[1], y3 = a[1], y4 = b[1], x13 = x1 - x3, x21 = x2 - x1, x43 = x4 - x3, y13 = y1 - y3, y21 = y2 - y1, y43 = y4 - y3, ua = (x43 * y13 - y43 * x13) / (y43 * x21 - x43 * y21);
  return [ x1 + ua * x21, y1 + ua * y21 ];
  }
  function d3_voronoi_tessellate(vertices, callback) {
  var Sites = {
  list: vertices.map(function(v, i) {
  return {
  index: i,
  x: v[0],
  y: v[1]
  };
  }).sort(function(a, b) {
  return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;
  }),
  bottomSite: null
  };
  var EdgeList = {
  list: [],
  leftEnd: null,
  rightEnd: null,
  init: function() {
  EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l");
  EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l");
  EdgeList.leftEnd.r = EdgeList.rightEnd;
  EdgeList.rightEnd.l = EdgeList.leftEnd;
  EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);
  },
  createHalfEdge: function(edge, side) {
  return {
  edge: edge,
  side: side,
  vertex: null,
  l: null,
  r: null
  };
  },
  insert: function(lb, he) {
  he.l = lb;
  he.r = lb.r;
  lb.r.l = he;
  lb.r = he;
  },
  leftBound: function(p) {
  var he = EdgeList.leftEnd;
  do {
  he = he.r;
  } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));
  he = he.l;
  return he;
  },
  del: function(he) {
  he.l.r = he.r;
  he.r.l = he.l;
  he.edge = null;
  },
  right: function(he) {
  return he.r;
  },
  left: function(he) {
  return he.l;
  },
  leftRegion: function(he) {
  return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];
  },
  rightRegion: function(he) {
  return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]];
  }
  };
  var Geom = {
  bisect: function(s1, s2) {
  var newEdge = {
  region: {
  l: s1,
  r: s2
  },
  ep: {
  l: null,
  r: null
  }
  };
  var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;
  newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;
  if (adx > ady) {
  newEdge.a = 1;
  newEdge.b = dy / dx;
  newEdge.c /= dx;
  } else {
  newEdge.b = 1;
  newEdge.a = dx / dy;
  newEdge.c /= dy;
  }
  return newEdge;
  },
  intersect: function(el1, el2) {
  var e1 = el1.edge, e2 = el2.edge;
  if (!e1 || !e2 || e1.region.r == e2.region.r) {
  return null;
  }
  var d = e1.a * e2.b - e1.b * e2.a;
  if (Math.abs(d) < 1e-10) {
  return null;
  }
  var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;
  if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {
  el = el1;
  e = e1;
  } else {
  el = el2;
  e = e2;
  }
  var rightOfSite = xint >= e.region.r.x;
  if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") {
  return null;
  }
  return {
  x: xint,
  y: yint
  };
  },
  rightOf: function(he, p) {
  var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;
  if (rightOfSite && he.side === "l") {
  return 1;
  }
  if (!rightOfSite && he.side === "r") {
  return 0;
  }
  if (e.a === 1) {
  var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;
  if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {
  above = fast = dyp >= e.b * dxp;
  } else {
  above = p.x + p.y * e.b > e.c;
  if (e.b < 0) {
  above = !above;
  }
  if (!above) {
  fast = 1;
  }
  }
  if (!fast) {
  var dxs = topsite.x - e.region.l.x;
  above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);
  if (e.b < 0) {
  above = !above;
  }
  }
  } else {
  var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;
  above = t1 * t1 > t2 * t2 + t3 * t3;
  }
  return he.side === "l" ? above : !above;
  },
  endPoint: function(edge, side, site) {
  edge.ep[side] = site;
  if (!edge.ep[d3_voronoi_opposite[side]]) return;
  callback(edge);
  },
  distance: function(s, t) {
  var dx = s.x - t.x, dy = s.y - t.y;
  return Math.sqrt(dx * dx + dy * dy);
  }
  };
  var EventQueue = {
  list: [],
  insert: function(he, site, offset) {
  he.vertex = site;
  he.ystar = site.y + offset;
  for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {
  var next = list[i];
  if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {
  continue;
  } else {
  break;
  }
  }
  list.splice(i, 0, he);
  },
  del: function(he) {
  for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}
  ls.splice(i, 1);
  },
  empty: function() {
  return EventQueue.list.length === 0;
  },
  nextEvent: function(he) {
  for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {
  if (ls[i] == he) return ls[i + 1];
  }
  return null;
  },
  min: function() {
  var elem = EventQueue.list[0];
  return {
  x: elem.vertex.x,
  y: elem.ystar
  };
  },
  extractMin: function() {
  return EventQueue.list.shift();
  }
  };
  EdgeList.init();
  Sites.bottomSite = Sites.list.shift();
  var newSite = Sites.list.shift(), newIntStar;
  var lbnd, rbnd, llbnd, rrbnd, bisector;
  var bot, top, temp, p, v;
  var e, pm;
  while (true) {
  if (!EventQueue.empty()) {
  newIntStar = EventQueue.min();
  }
  if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {
  lbnd = EdgeList.leftBound(newSite);
  rbnd = EdgeList.right(lbnd);
  bot = EdgeList.rightRegion(lbnd);
  e = Geom.bisect(bot, newSite);
  bisector = EdgeList.createHalfEdge(e, "l");
  EdgeList.insert(lbnd, bisector);
  p = Geom.intersect(lbnd, bisector);
  if (p) {
  EventQueue.del(lbnd);
  EventQueue.insert(lbnd, p, Geom.distance(p, newSite));
  }
  lbnd = bisector;
  bisector = EdgeList.createHalfEdge(e, "r");
  EdgeList.insert(lbnd, bisector);
  p = Geom.intersect(bisector, rbnd);
  if (p) {
  EventQueue.insert(bisector, p, Geom.distance(p, newSite));
  }
  newSite = Sites.list.shift();
  } else if (!EventQueue.empty()) {
  lbnd = EventQueue.extractMin();
  llbnd = EdgeList.left(lbnd);
  rbnd = EdgeList.right(lbnd);
  rrbnd = EdgeList.right(rbnd);
  bot = EdgeList.leftRegion(lbnd);
  top = EdgeList.rightRegion(rbnd);
  v = lbnd.vertex;
  Geom.endPoint(lbnd.edge, lbnd.side, v);
  Geom.endPoint(rbnd.edge, rbnd.side, v);
  EdgeList.del(lbnd);
  EventQueue.del(rbnd);
  EdgeList.del(rbnd);
  pm = "l";
  if (bot.y > top.y) {
  temp = bot;
  bot = top;
  top = temp;
  pm = "r";
  }
  e = Geom.bisect(bot, top);
  bisector = EdgeList.createHalfEdge(e, pm);
  EdgeList.insert(llbnd, bisector);
  Geom.endPoint(e, d3_voronoi_opposite[pm], v);
  p = Geom.intersect(llbnd, bisector);
  if (p) {
  EventQueue.del(llbnd);
  EventQueue.insert(llbnd, p, Geom.distance(p, bot));
  }
  p = Geom.intersect(bisector, rrbnd);
  if (p) {
  EventQueue.insert(bisector, p, Geom.distance(p, bot));
  }
  } else {
  break;
  }
  }
  for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {
  callback(lbnd.edge);
  }
  }
  function d3_geom_quadtreeNode() {
  return {
  leaf: true,
  nodes: [],
  point: null
  };
  }
  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
  if (!f(node, x1, y1, x2, y2)) {
  var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
  if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
  if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
  if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
  if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
  }
  }
  function d3_geom_quadtreePoint(p) {
  return {
  x: p[0],
  y: p[1]
  };
  }
  function d3_time_utc() {
  this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
  }
  function d3_time_formatAbbreviate(name) {
  return name.substring(0, 3);
  }
  function d3_time_parse(date, template, string, j) {
  var c, p, i = 0, n = template.length, m = string.length;
  while (i < n) {
  if (j >= m) return -1;
  c = template.charCodeAt(i++);
  if (c == 37) {
  p = d3_time_parsers[template.charAt(i++)];
  if (!p || (j = p(date, string, j)) < 0) return -1;
  } else if (c != string.charCodeAt(j++)) {
  return -1;
  }
  }
  return j;
  }
  function d3_time_formatRe(names) {
  return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
  }
  function d3_time_formatLookup(names) {
  var map = new d3_Map, i = -1, n = names.length;
  while (++i < n) map.set(names[i].toLowerCase(), i);
  return map;
  }
  function d3_time_parseWeekdayAbbrev(date, string, i) {
  d3_time_dayAbbrevRe.lastIndex = 0;
  var n = d3_time_dayAbbrevRe.exec(string.substring(i));
  return n ? i += n[0].length : -1;
  }
  function d3_time_parseWeekday(date, string, i) {
  d3_time_dayRe.lastIndex = 0;
  var n = d3_time_dayRe.exec(string.substring(i));
  return n ? i += n[0].length : -1;
  }
  function d3_time_parseMonthAbbrev(date, string, i) {
  d3_time_monthAbbrevRe.lastIndex = 0;
  var n = d3_time_monthAbbrevRe.exec(string.substring(i));
  return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;
  }
  function d3_time_parseMonth(date, string, i) {
  d3_time_monthRe.lastIndex = 0;
  var n = d3_time_monthRe.exec(string.substring(i));
  return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i += n[0].length) : -1;
  }
  function d3_time_parseLocaleFull(date, string, i) {
  return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
  }
  function d3_time_parseLocaleDate(date, string, i) {
  return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
  }
  function d3_time_parseLocaleTime(date, string, i) {
  return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
  }
  function d3_time_parseFullYear(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 4));
  return n ? (date.y = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseYear(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.y = d3_time_expandYear(+n[0]), i += n[0].length) : -1;
  }
  function d3_time_expandYear(d) {
  return d + (d > 68 ? 1900 : 2e3);
  }
  function d3_time_parseMonthNumber(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.m = n[0] - 1, i += n[0].length) : -1;
  }
  function d3_time_parseDay(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.d = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseHour24(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.H = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseMinutes(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.M = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseSeconds(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 2));
  return n ? (date.S = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseMilliseconds(date, string, i) {
  d3_time_numberRe.lastIndex = 0;
  var n = d3_time_numberRe.exec(string.substring(i, i + 3));
  return n ? (date.L = +n[0], i += n[0].length) : -1;
  }
  function d3_time_parseAmPm(date, string, i) {
  var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase());
  return n == null ? -1 : (date.p = n, i);
  }
  function d3_time_zone(d) {
  var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(Math.abs(z) / 60), zm = Math.abs(z) % 60;
  return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm);
  }
  function d3_time_formatIsoNative(date) {
  return date.toISOString();
  }
  function d3_time_interval(local, step, number) {
  function round(date) {
  var d0 = local(date), d1 = offset(d0, 1);
  return date - d0 < d1 - date ? d0 : d1;
  }
  function ceil(date) {
  step(date = local(new d3_time(date - 1)), 1);
  return date;
  }
  function offset(date, k) {
  step(date = new d3_time(+date), k);
  return date;
  }
  function range(t0, t1, dt) {
  var time = ceil(t0), times = [];
  if (dt > 1) {
  while (time < t1) {
  if (!(number(time) % dt)) times.push(new Date(+time));
  step(time, 1);
  }
  } else {
  while (time < t1) times.push(new Date(+time)), step(time, 1);
  }
  return times;
  }
  function range_utc(t0, t1, dt) {
  try {
  d3_time = d3_time_utc;
  var utc = new d3_time_utc;
  utc._ = t0;
  return range(utc, t1, dt);
  } finally {
  d3_time = Date;
  }
  }
  local.floor = local;
  local.round = round;
  local.ceil = ceil;
  local.offset = offset;
  local.range = range;
  var utc = local.utc = d3_time_interval_utc(local);
  utc.floor = utc;
  utc.round = d3_time_interval_utc(round);
  utc.ceil = d3_time_interval_utc(ceil);
  utc.offset = d3_time_interval_utc(offset);
  utc.range = range_utc;
  return local;
  }
  function d3_time_interval_utc(method) {
  return function(date, k) {
  try {
  d3_time = d3_time_utc;
  var utc = new d3_time_utc;
  utc._ = date;
  return method(utc, k)._;
  } finally {
  d3_time = Date;
  }
  };
  }
  function d3_time_scale(linear, methods, format) {
  function scale(x) {
  return linear(x);
  }
  scale.invert = function(x) {
  return d3_time_scaleDate(linear.invert(x));
  };
  scale.domain = function(x) {
  if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
  linear.domain(x);
  return scale;
  };
  scale.nice = function(m) {
  return scale.domain(d3_scale_nice(scale.domain(), function() {
  return m;
  }));
  };
  scale.ticks = function(m, k) {
  var extent = d3_time_scaleExtent(scale.domain());
  if (typeof m !== "function") {
  var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target);
  if (i == d3_time_scaleSteps.length) return methods.year(extent, m);
  if (!i) return linear.ticks(m).map(d3_time_scaleDate);
  if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i;
  m = methods[i];
  k = m[1];
  m = m[0].range;
  }
  return m(extent[0], new Date(+extent[1] + 1), k);
  };
  scale.tickFormat = function() {
  return format;
  };
  scale.copy = function() {
  return d3_time_scale(linear.copy(), methods, format);
  };
  return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
  }
  function d3_time_scaleExtent(domain) {
  var start = domain[0], stop = domain[domain.length - 1];
  return start < stop ? [ start, stop ] : [ stop, start ];
  }
  function d3_time_scaleDate(t) {
  return new Date(t);
  }
  function d3_time_scaleFormat(formats) {
  return function(date) {
  var i = formats.length - 1, f = formats[i];
  while (!f[1](date)) f = formats[--i];
  return f[0](date);
  };
  }
  function d3_time_scaleSetYear(y) {
  var d = new Date(y, 0, 1);
  d.setFullYear(y);
  return d;
  }
  function d3_time_scaleGetYear(d) {
  var y = d.getFullYear(), d0 = d3_time_scaleSetYear(y), d1 = d3_time_scaleSetYear(y + 1);
  return y + (d - d0) / (d1 - d0);
  }
  function d3_time_scaleUTCSetYear(y) {
  var d = new Date(Date.UTC(y, 0, 1));
  d.setUTCFullYear(y);
  return d;
  }
  function d3_time_scaleUTCGetYear(d) {
  var y = d.getUTCFullYear(), d0 = d3_time_scaleUTCSetYear(y), d1 = d3_time_scaleUTCSetYear(y + 1);
  return y + (d - d0) / (d1 - d0);
  }
  if (!Date.now) Date.now = function() {
  return +(new Date);
  };
  try {
  document.createElement("div").style.setProperty("opacity", 0, "");
  } catch (error) {
  var d3_style_prototype = CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
  d3_style_prototype.setProperty = function(name, value, priority) {
  d3_style_setProperty.call(this, name, value + "", priority);
  };
  }
  d3 = {
  version: "2.10.3"
  };
  var d3_array = d3_arraySlice;
  try {
  d3_array(document.documentElement.childNodes)[0].nodeType;
  } catch (e) {
  d3_array = d3_arrayCopy;
  }
  var d3_arraySubclass = [].__proto__ ? function(array, prototype) {
  array.__proto__ = prototype;
  } : function(array, prototype) {
  for (var property in prototype) array[property] = prototype[property];
  };
  d3.map = function(object) {
  var map = new d3_Map;
  for (var key in object) map.set(key, object[key]);
  return map;
  };
  d3_class(d3_Map, {
  has: function(key) {
  return d3_map_prefix + key in this;
  },
  get: function(key) {
  return this[d3_map_prefix + key];
  },
  set: function(key, value) {
  return this[d3_map_prefix + key] = value;
  },
  remove: function(key) {
  key = d3_map_prefix + key;
  return key in this && delete this[key];
  },
  keys: function() {
  var keys = [];
  this.forEach(function(key) {
  keys.push(key);
  });
  return keys;
  },
  values: function() {
  var values = [];
  this.forEach(function(key, value) {
  values.push(value);
  });
  return values;
  },
  entries: function() {
  var entries = [];
  this.forEach(function(key, value) {
  entries.push({
  key: key,
  value: value
  });
  });
  return entries;
  },
  forEach: function(f) {
  for (var key in this) {
  if (key.charCodeAt(0) === d3_map_prefixCode) {
  f.call(this, key.substring(1), this[key]);
  }
  }
  }
  });
  var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
  d3.functor = d3_functor;
  d3.rebind = function(target, source) {
  var i = 1, n = arguments.length, method;
  while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
  return target;
  };
  d3.ascending = function(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  };
  d3.descending = function(a, b) {
  return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
  };
  d3.mean = function(array, f) {
  var n = array.length, a, m = 0, i = -1, j = 0;
  if (arguments.length === 1) {
  while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
  } else {
  while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
  }
  return j ? m : undefined;
  };
  d3.median = function(array, f) {
  if (arguments.length > 1) array = array.map(f);
  array = array.filter(d3_number);
  return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
  };
  d3.min = function(array, f) {
  var i = -1, n = array.length, a, b;
  if (arguments.length === 1) {
  while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
  while (++i < n) if ((b = array[i]) != null && a > b) a = b;
  } else {
  while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
  while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
  }
  return a;
  };
  d3.max = function(array, f) {
  var i = -1, n = array.length, a, b;
  if (arguments.length === 1) {
  while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
  while (++i < n) if ((b = array[i]) != null && b > a) a = b;
  } else {
  while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
  while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
  }
  return a;
  };
  d3.extent = function(array, f) {
  var i = -1, n = array.length, a, b, c;
  if (arguments.length === 1) {
  while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined;
  while (++i < n) if ((b = array[i]) != null) {
  if (a > b) a = b;
  if (c < b) c = b;
  }
  } else {
  while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined;
  while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
  if (a > b) a = b;
  if (c < b) c = b;
  }
  }
  return [ a, c ];
  };
  d3.random = {
  normal: function(µ, σ) {
  var n = arguments.length;
  if (n < 2) σ = 1;
  if (n < 1) µ = 0;
  return function() {
  var x, y, r;
  do {
  x = Math.random() * 2 - 1;
  y = Math.random() * 2 - 1;
  r = x * x + y * y;
  } while (!r || r > 1);
  return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
  };
  },
  logNormal: function(µ, σ) {
  var n = arguments.length;
  if (n < 2) σ = 1;
  if (n < 1) µ = 0;
  var random = d3.random.normal();
  return function() {
  return Math.exp(µ + σ * random());
  };
  },
  irwinHall: function(m) {
  return function() {
  for (var s = 0, j = 0; j < m; j++) s += Math.random();
  return s / m;
  };
  }
  };
  d3.sum = function(array, f) {
  var s = 0, n = array.length, a, i = -1;
  if (arguments.length === 1) {
  while (++i < n) if (!isNaN(a = +array[i])) s += a;
  } else {
  while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
  }
  return s;
  };
  d3.quantile = function(values, p) {
  var H = (values.length - 1) * p + 1, h = Math.floor(H), v = values[h - 1], e = H - h;
  return e ? v + e * (values[h] - v) : v;
  };
  d3.transpose = function(matrix) {
  return d3.zip.apply(d3, matrix);
  };
  d3.zip = function() {
  if (!(n = arguments.length)) return [];
  for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
  for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
  zip[j] = arguments[j][i];
  }
  }
  return zips;
  };
  d3.bisector = function(f) {
  return {
  left: function(a, x, lo, hi) {
  if (arguments.length < 3) lo = 0;
  if (arguments.length < 4) hi = a.length;
  while (lo < hi) {
  var mid = lo + hi >>> 1;
  if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid;
  }
  return lo;
  },
  right: function(a, x, lo, hi) {
  if (arguments.length < 3) lo = 0;
  if (arguments.length < 4) hi = a.length;
  while (lo < hi) {
  var mid = lo + hi >>> 1;
  if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1;
  }
  return lo;
  }
  };
  };
  var d3_bisector = d3.bisector(function(d) {
  return d;
  });
  d3.bisectLeft = d3_bisector.left;
  d3.bisect = d3.bisectRight = d3_bisector.right;
  d3.first = function(array, f) {
  var i = 0, n = array.length, a = array[0], b;
  if (arguments.length === 1) f = d3.ascending;
  while (++i < n) {
  if (f.call(array, a, b = array[i]) > 0) {
  a = b;
  }
  }
  return a;
  };
  d3.last = function(array, f) {
  var i = 0, n = array.length, a = array[0], b;
  if (arguments.length === 1) f = d3.ascending;
  while (++i < n) {
  if (f.call(array, a, b = array[i]) <= 0) {
  a = b;
  }
  }
  return a;
  };
  d3.nest = function() {
  function map(array, depth) {
  if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
  var i = -1, n = array.length, key = keys[depth++], keyValue, object, valuesByKey = new d3_Map, values, o = {};
  while (++i < n) {
  if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
  values.push(object);
  } else {
  valuesByKey.set(keyValue, [ object ]);
  }
  }
  valuesByKey.forEach(function(keyValue, values) {
  o[keyValue] = map(values, depth);
  });
  return o;
  }
  function entries(map, depth) {
  if (depth >= keys.length) return map;
  var a = [], sortKey = sortKeys[depth++], key;
  for (key in map) {
  a.push({
  key: key,
  values: entries(map[key], depth)
  });
  }
  if (sortKey) a.sort(function(a, b) {
  return sortKey(a.key, b.key);
  });
  return a;
  }
  var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
  nest.map = function(array) {
  return map(array, 0);
  };
  nest.entries = function(array) {
  return entries(map(array, 0), 0);
  };
  nest.key = function(d) {
  keys.push(d);
  return nest;
  };
  nest.sortKeys = function(order) {
  sortKeys[keys.length - 1] = order;
  return nest;
  };
  nest.sortValues = function(order) {
  sortValues = order;
  return nest;
  };
  nest.rollup = function(f) {
  rollup = f;
  return nest;
  };
  return nest;
  };
  d3.keys = function(map) {
  var keys = [];
  for (var key in map) keys.push(key);
  return keys;
  };
  d3.values = function(map) {
  var values = [];
  for (var key in map) values.push(map[key]);
  return values;
  };
  d3.entries = function(map) {
  var entries = [];
  for (var key in map) entries.push({
  key: key,
  value: map[key]
  });
  return entries;
  };
  d3.permute = function(array, indexes) {
  var permutes = [], i = -1, n = indexes.length;
  while (++i < n) permutes[i] = array[indexes[i]];
  return permutes;
  };
  d3.merge = function(arrays) {
  return Array.prototype.concat.apply([], arrays);
  };
  d3.split = function(array, f) {
  var arrays = [], values = [], value, i = -1, n = array.length;
  if (arguments.length < 2) f = d3_splitter;
  while (++i < n) {
  if (f.call(values, value = array[i], i)) {
  values = [];
  } else {
  if (!values.length) arrays.push(values);
  values.push(value);
  }
  }
  return arrays;
  };
  d3.range = function(start, stop, step) {
  if (arguments.length < 3) {
  step = 1;
  if (arguments.length < 2) {
  stop = start;
  start = 0;
  }
  }
  if ((stop - start) / step === Infinity) throw new Error("infinite range");
  var range = [], k = d3_range_integerScale(Math.abs(step)), i = -1, j;
  start *= k, stop *= k, step *= k;
  if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
  return range;
  };
  d3.requote = function(s) {
  return s.replace(d3_requote_re, "\\$&");
  };
  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
  d3.round = function(x, n) {
  return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
  };
  d3.xhr = function(url, mime, callback) {
  var req = new XMLHttpRequest;
  if (arguments.length < 3) callback = mime, mime = null; else if (mime && req.overrideMimeType) req.overrideMimeType(mime);
  req.open("GET", url, true);
  if (mime) req.setRequestHeader("Accept", mime);
  req.onreadystatechange = function() {
  if (req.readyState === 4) {
  var s = req.status;
  callback(!s && req.response || s >= 200 && s < 300 || s === 304 ? req : null);
  }
  };
  req.send(null);
  };
  d3.text = function(url, mime, callback) {
  function ready(req) {
  callback(req && req.responseText);
  }
  if (arguments.length < 3) {
  callback = mime;
  mime = null;
  }
  d3.xhr(url, mime, ready);
  };
  d3.json = function(url, callback) {
  d3.text(url, "application/json", function(text) {
  callback(text ? JSON.parse(text) : null);
  });
  };
  d3.html = function(url, callback) {
  d3.text(url, "text/html", function(text) {
  if (text != null) {
  var range = document.createRange();
  range.selectNode(document.body);
  text = range.createContextualFragment(text);
  }
  callback(text);
  });
  };
  d3.xml = function(url, mime, callback) {
  function ready(req) {
  callback(req && req.responseXML);
  }
  if (arguments.length < 3) {
  callback = mime;
  mime = null;
  }
  d3.xhr(url, mime, ready);
  };
  var d3_nsPrefix = {
  svg: "http://www.w3.org/2000/svg",
  xhtml: "http://www.w3.org/1999/xhtml",
  xlink: "http://www.w3.org/1999/xlink",
  xml: "http://www.w3.org/XML/1998/namespace",
  xmlns: "http://www.w3.org/2000/xmlns/"
  };
  d3.ns = {
  prefix: d3_nsPrefix,
  qualify: function(name) {
  var i = name.indexOf(":"), prefix = name;
  if (i >= 0) {
  prefix = name.substring(0, i);
  name = name.substring(i + 1);
  }
  return d3_nsPrefix.hasOwnProperty(prefix) ? {
  space: d3_nsPrefix[prefix],
  local: name
  } : name;
  }
  };
  d3.dispatch = function() {
  var dispatch = new d3_dispatch, i = -1, n = arguments.length;
  while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
  return dispatch;
  };
  d3_dispatch.prototype.on = function(type, listener) {
  var i = type.indexOf("."), name = "";
  if (i > 0) {
  name = type.substring(i + 1);
  type = type.substring(0, i);
  }
  return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
  };
  d3.format = function(specifier) {
  var match = d3_format_re.exec(specifier), fill = match[1] || " ", sign = match[3] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false;
  if (precision) precision = +precision.substring(1);
  if (zfill) {
  fill = "0";
  if (comma) width -= Math.floor((width - 1) / 4);
  }
  switch (type) {
  case "n":
  comma = true;
  type = "g";
  break;
  case "%":
  scale = 100;
  suffix = "%";
  type = "f";
  break;
  case "p":
  scale = 100;
  suffix = "%";
  type = "r";
  break;
  case "d":
  integer = true;
  precision = 0;
  break;
  case "s":
  scale = -1;
  type = "r";
  break;
  }
  if (type == "r" && !precision) type = "g";
  type = d3_format_types.get(type) || d3_format_typeDefault;
  return function(value) {
  if (integer && value % 1) return "";
  var negative = value < 0 && (value = -value) ? "-" : sign;
  if (scale < 0) {
  var prefix = d3.formatPrefix(value, precision);
  value = prefix.scale(value);
  suffix = prefix.symbol;
  } else {
  value *= scale;
  }
  value = type(value, precision);
  if (zfill) {
  var length = value.length + negative.length;
  if (length < width) value = (new Array(width - length + 1)).join(fill) + value;
  if (comma) value = d3_format_group(value);
  value = negative + value;
  } else {
  if (comma) value = d3_format_group(value);
  value = negative + value;
  var length = value.length;
  if (length < width) value = (new Array(width - length + 1)).join(fill) + value;
  }
  return value + suffix;
  };
  };
  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
  var d3_format_types = d3.map({
  g: function(x, p) {
  return x.toPrecision(p);
  },
  e: function(x, p) {
  return x.toExponential(p);
  },
  f: function(x, p) {
  return x.toFixed(p);
  },
  r: function(x, p) {
  return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p)));
  }
  });
  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
  d3.formatPrefix = function(value, precision) {
  var i = 0;
  if (value) {
  if (value < 0) value *= -1;
  if (precision) value = d3.round(value, d3_format_precision(value, precision));
  i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
  i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
  }
  return d3_formatPrefixes[8 + i / 3];
  };
  var d3_ease_quad = d3_ease_poly(2), d3_ease_cubic = d3_ease_poly(3), d3_ease_default = function() {
  return d3_ease_identity;
  };
  var d3_ease = d3.map({
  linear: d3_ease_default,
  poly: d3_ease_poly,
  quad: function() {
  return d3_ease_quad;
  },
  cubic: function() {
  return d3_ease_cubic;
  },
  sin: function() {
  return d3_ease_sin;
  },
  exp: function() {
  return d3_ease_exp;
  },
  circle: function() {
  return d3_ease_circle;
  },
  elastic: d3_ease_elastic,
  back: d3_ease_back,
  bounce: function() {
  return d3_ease_bounce;
  }
  });
  var d3_ease_mode = d3.map({
  "in": d3_ease_identity,
  out: d3_ease_reverse,
  "in-out": d3_ease_reflect,
  "out-in": function(f) {
  return d3_ease_reflect(d3_ease_reverse(f));
  }
  });
  d3.ease = function(name) {
  var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in";
  t = d3_ease.get(t) || d3_ease_default;
  m = d3_ease_mode.get(m) || d3_ease_identity;
  return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));
  };
  d3.event = null;
  d3.transform = function(string) {
  var g = document.createElementNS(d3.ns.prefix.svg, "g");
  return (d3.transform = function(string) {
  g.setAttribute("transform", string);
  var t = g.transform.baseVal.consolidate();
  return new d3_transform(t ? t.matrix : d3_transformIdentity);
  })(string);
  };
  d3_transform.prototype.toString = function() {
  return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
  };
  var d3_transformDegrees = 180 / Math.PI, d3_transformIdentity = {
  a: 1,
  b: 0,
  c: 0,
  d: 1,
  e: 0,
  f: 0
  };
  d3.interpolate = function(a, b) {
  var i = d3.interpolators.length, f;
  while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
  return f;
  };
  d3.interpolateNumber = function(a, b) {
  b -= a;
  return function(t) {
  return a + b * t;
  };
  };
  d3.interpolateRound = function(a, b) {
  b -= a;
  return function(t) {
  return Math.round(a + b * t);
  };
  };
  d3.interpolateString = function(a, b) {
  var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
  d3_interpolate_number.lastIndex = 0;
  for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
  if (m.index) s.push(b.substring(s0, s1 = m.index));
  q.push({
  i: s.length,
  x: m[0]
  });
  s.push(null);
  s0 = d3_interpolate_number.lastIndex;
  }
  if (s0 < b.length) s.push(b.substring(s0));
  for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
  o = q[i];
  if (o.x == m[0]) {
  if (o.i) {
  if (s[o.i + 1] == null) {
  s[o.i - 1] += o.x;
  s.splice(o.i, 1);
  for (j = i + 1; j < n; ++j) q[j].i--;
  } else {
  s[o.i - 1] += o.x + s[o.i + 1];
  s.splice(o.i, 2);
  for (j = i + 1; j < n; ++j) q[j].i -= 2;
  }
  } else {
  if (s[o.i + 1] == null) {
  s[o.i] = o.x;
  } else {
  s[o.i] = o.x + s[o.i + 1];
  s.splice(o.i + 1, 1);
  for (j = i + 1; j < n; ++j) q[j].i--;
  }
  }
  q.splice(i, 1);
  n--;
  i--;
  } else {
  o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
  }
  }
  while (i < n) {
  o = q.pop();
  if (s[o.i + 1] == null) {
  s[o.i] = o.x;
  } else {
  s[o.i] = o.x + s[o.i + 1];
  s.splice(o.i + 1, 1);
  }
  n--;
  }
  if (s.length === 1) {
  return s[0] == null ? q[0].x : function() {
  return b;
  };
  }
  return function(t) {
  for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
  return s.join("");
  };
  };
  d3.interpolateTransform = function(a, b) {
  var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
  if (ta[0] != tb[0] || ta[1] != tb[1]) {
  s.push("translate(", null, ",", null, ")");
  q.push({
  i: 1,
  x: d3.interpolateNumber(ta[0], tb[0])
  }, {
  i: 3,
  x: d3.interpolateNumber(ta[1], tb[1])
  });
  } else if (tb[0] || tb[1]) {
  s.push("translate(" + tb + ")");
  } else {
  s.push("");
  }
  if (ra != rb) {
  if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
  q.push({
  i: s.push(s.pop() + "rotate(", null, ")") - 2,
  x: d3.interpolateNumber(ra, rb)
  });
  } else if (rb) {
  s.push(s.pop() + "rotate(" + rb + ")");
  }
  if (wa != wb) {
  q.push({
  i: s.push(s.pop() + "skewX(", null, ")") - 2,
  x: d3.interpolateNumber(wa, wb)
  });
  } else if (wb) {
  s.push(s.pop() + "skewX(" + wb + ")");
  }
  if (ka[0] != kb[0] || ka[1] != kb[1]) {
  n = s.push(s.pop() + "scale(", null, ",", null, ")");
  q.push({
  i: n - 4,
  x: d3.interpolateNumber(ka[0], kb[0])
  }, {
  i: n - 2,
  x: d3.interpolateNumber(ka[1], kb[1])
  });
  } else if (kb[0] != 1 || kb[1] != 1) {
  s.push(s.pop() + "scale(" + kb + ")");
  }
  n = q.length;
  return function(t) {
  var i = -1, o;
  while (++i < n) s[(o = q[i]).i] = o.x(t);
  return s.join("");
  };
  };
  d3.interpolateRgb = function(a, b) {
  a = d3.rgb(a);
  b = d3.rgb(b);
  var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
  return function(t) {
  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));
  };
  };
  d3.interpolateHsl = function(a, b) {
  a = d3.hsl(a);
  b = d3.hsl(b);
  var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0;
  if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360;
  return function(t) {
  return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + "";
  };
  };
  d3.interpolateLab = function(a, b) {
  a = d3.lab(a);
  b = d3.lab(b);
  var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
  return function(t) {
  return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
  };
  };
  d3.interpolateHcl = function(a, b) {
  a = d3.hcl(a);
  b = d3.hcl(b);
  var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
  if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
  return function(t) {
  return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
  };
  };
  d3.interpolateArray = function(a, b) {
  var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
  for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));
  for (; i < na; ++i) c[i] = a[i];
  for (; i < nb; ++i) c[i] = b[i];
  return function(t) {
  for (i = 0; i < n0; ++i) c[i] = x[i](t);
  return c;
  };
  };
  d3.interpolateObject = function(a, b) {
  var i = {}, c = {}, k;
  for (k in a) {
  if (k in b) {
  i[k] = d3_interpolateByName(k)(a[k], b[k]);
  } else {
  c[k] = a[k];
  }
  }
  for (k in b) {
  if (!(k in a)) {
  c[k] = b[k];
  }
  }
  return function(t) {
  for (k in i) c[k] = i[k](t);
  return c;
  };
  };
  var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
  d3.interpolators = [ d3.interpolateObject, function(a, b) {
  return b instanceof Array && d3.interpolateArray(a, b);
  }, function(a, b) {
  return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + "");
  }, function(a, b) {
  return (typeof b === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Color) && d3.interpolateRgb(a, b);
  }, function(a, b) {
  return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b);
  } ];
  d3_Color.prototype.toString = function() {
  return this.rgb() + "";
  };
  d3.rgb = function(r, g, b) {
  return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
  };
  var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color;
  d3_rgbPrototype.brighter = function(k) {
  k = Math.pow(.7, arguments.length ? k : 1);
  var r = this.r, g = this.g, b = this.b, i = 30;
  if (!r && !g && !b) return d3_rgb(i, i, i);
  if (r && r < i) r = i;
  if (g && g < i) g = i;
  if (b && b < i) b = i;
  return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));
  };
  d3_rgbPrototype.darker = function(k) {
  k = Math.pow(.7, arguments.length ? k : 1);
  return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b));
  };
  d3_rgbPrototype.hsl = function() {
  return d3_rgb_hsl(this.r, this.g, this.b);
  };
  d3_rgbPrototype.toString = function() {
  return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
  };
  var d3_rgb_names = d3.map({
  aliceblue: "#f0f8ff",
  antiquewhite: "#faebd7",
  aqua: "#00ffff",
  aquamarine: "#7fffd4",
  azure: "#f0ffff",
  beige: "#f5f5dc",
  bisque: "#ffe4c4",
  black: "#000000",
  blanchedalmond: "#ffebcd",
  blue: "#0000ff",
  blueviolet: "#8a2be2",
  brown: "#a52a2a",
  burlywood: "#deb887",
  cadetblue: "#5f9ea0",
  chartreuse: "#7fff00",
  chocolate: "#d2691e",
  coral: "#ff7f50",
  cornflowerblue: "#6495ed",
  cornsilk: "#fff8dc",
  crimson: "#dc143c",
  cyan: "#00ffff",
  darkblue: "#00008b",
  darkcyan: "#008b8b",
  darkgoldenrod: "#b8860b",
  darkgray: "#a9a9a9",
  darkgreen: "#006400",
  darkgrey: "#a9a9a9",
  darkkhaki: "#bdb76b",
  darkmagenta: "#8b008b",
  darkolivegreen: "#556b2f",
  darkorange: "#ff8c00",
  darkorchid: "#9932cc",
  darkred: "#8b0000",
  darksalmon: "#e9967a",
  darkseagreen: "#8fbc8f",
  darkslateblue: "#483d8b",
  darkslategray: "#2f4f4f",
  darkslategrey: "#2f4f4f",
  darkturquoise: "#00ced1",
  darkviolet: "#9400d3",
  deeppink: "#ff1493",
  deepskyblue: "#00bfff",
  dimgray: "#696969",
  dimgrey: "#696969",
  dodgerblue: "#1e90ff",
  firebrick: "#b22222",
  floralwhite: "#fffaf0",
  forestgreen: "#228b22",
  fuchsia: "#ff00ff",
  gainsboro: "#dcdcdc",
  ghostwhite: "#f8f8ff",
  gold: "#ffd700",
  goldenrod: "#daa520",
  gray: "#808080",
  green: "#008000",
  greenyellow: "#adff2f",
  grey: "#808080",
  honeydew: "#f0fff0",
  hotpink: "#ff69b4",
  indianred: "#cd5c5c",
  indigo: "#4b0082",
  ivory: "#fffff0",
  khaki: "#f0e68c",
  lavender: "#e6e6fa",
  lavenderblush: "#fff0f5",
  lawngreen: "#7cfc00",
  lemonchiffon: "#fffacd",
  lightblue: "#add8e6",
  lightcoral: "#f08080",
  lightcyan: "#e0ffff",
  lightgoldenrodyellow: "#fafad2",
  lightgray: "#d3d3d3",
  lightgreen: "#90ee90",
  lightgrey: "#d3d3d3",
  lightpink: "#ffb6c1",
  lightsalmon: "#ffa07a",
  lightseagreen: "#20b2aa",
  lightskyblue: "#87cefa",
  lightslategray: "#778899",
  lightslategrey: "#778899",
  lightsteelblue: "#b0c4de",
  lightyellow: "#ffffe0",
  lime: "#00ff00",
  limegreen: "#32cd32",
  linen: "#faf0e6",
  magenta: "#ff00ff",
  maroon: "#800000",
  mediumaquamarine: "#66cdaa",
  mediumblue: "#0000cd",
  mediumorchid: "#ba55d3",
  mediumpurple: "#9370db",
  mediumseagreen: "#3cb371",
  mediumslateblue: "#7b68ee",
  mediumspringgreen: "#00fa9a",
  mediumturquoise: "#48d1cc",
  mediumvioletred: "#c71585",
  midnightblue: "#191970",
  mintcream: "#f5fffa",
  mistyrose: "#ffe4e1",
  moccasin: "#ffe4b5",
  navajowhite: "#ffdead",
  navy: "#000080",
  oldlace: "#fdf5e6",
  olive: "#808000",
  olivedrab: "#6b8e23",
  orange: "#ffa500",
  orangered: "#ff4500",
  orchid: "#da70d6",
  palegoldenrod: "#eee8aa",
  palegreen: "#98fb98",
  paleturquoise: "#afeeee",
  palevioletred: "#db7093",
  papayawhip: "#ffefd5",
  peachpuff: "#ffdab9",
  peru: "#cd853f",
  pink: "#ffc0cb",
  plum: "#dda0dd",
  powderblue: "#b0e0e6",
  purple: "#800080",
  red: "#ff0000",
  rosybrown: "#bc8f8f",
  royalblue: "#4169e1",
  saddlebrown: "#8b4513",
  salmon: "#fa8072",
  sandybrown: "#f4a460",
  seagreen: "#2e8b57",
  seashell: "#fff5ee",
  sienna: "#a0522d",
  silver: "#c0c0c0",
  skyblue: "#87ceeb",
  slateblue: "#6a5acd",
  slategray: "#708090",
  slategrey: "#708090",
  snow: "#fffafa",
  springgreen: "#00ff7f",
  steelblue: "#4682b4",
  tan: "#d2b48c",
  teal: "#008080",
  thistle: "#d8bfd8",
  tomato: "#ff6347",
  turquoise: "#40e0d0",
  violet: "#ee82ee",
  wheat: "#f5deb3",
  white: "#ffffff",
  whitesmoke: "#f5f5f5",
  yellow: "#ffff00",
  yellowgreen: "#9acd32"
  });
  d3_rgb_names.forEach(function(key, value) {
  d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb));
  });
  d3.hsl = function(h, s, l) {
  return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
  };
  var d3_hslPrototype = d3_Hsl.prototype = new d3_Color;
  d3_hslPrototype.brighter = function(k) {
  k = Math.pow(.7, arguments.length ? k : 1);
  return d3_hsl(this.h, this.s, this.l / k);
  };
  d3_hslPrototype.darker = function(k) {
  k = Math.pow(.7, arguments.length ? k : 1);
  return d3_hsl(this.h, this.s, k * this.l);
  };
  d3_hslPrototype.rgb = function() {
  return d3_hsl_rgb(this.h, this.s, this.l);
  };
  d3.hcl = function(h, c, l) {
  return arguments.length === 1 ? h instanceof d3_Hcl ? 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) : d3_hcl(+h, +c, +l);
  };
  var d3_hclPrototype = d3_Hcl.prototype = new d3_Color;
  d3_hclPrototype.brighter = function(k) {
  return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
  };
  d3_hclPrototype.darker = function(k) {
  return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
  };
  d3_hclPrototype.rgb = function() {
  return d3_hcl_lab(this.h, this.c, this.l).rgb();
  };
  d3.lab = function(l, a, b) {
  return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
  };
  var d3_lab_K = 18;
  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
  var d3_labPrototype = d3_Lab.prototype = new d3_Color;
  d3_labPrototype.brighter = function(k) {
  return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
  };
  d3_labPrototype.darker = function(k) {
  return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
  };
  d3_labPrototype.rgb = function() {
  return d3_lab_rgb(this.l, this.a, this.b);
  };
  var d3_select = function(s, n) {
  return n.querySelector(s);
  }, d3_selectAll = function(s, n) {
  return n.querySelectorAll(s);
  }, d3_selectRoot = document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) {
  return d3_selectMatcher.call(n, s);
  };
  if (typeof Sizzle === "function") {
  d3_select = function(s, n) {
  return Sizzle(s, n)[0] || null;
  };
  d3_selectAll = function(s, n) {
  return Sizzle.uniqueSort(Sizzle(s, n));
  };
  d3_selectMatches = Sizzle.matchesSelector;
  }
  var d3_selectionPrototype = [];
  d3.selection = function() {
  return d3_selectionRoot;
  };
  d3.selection.prototype = d3_selectionPrototype;
  d3_selectionPrototype.select = function(selector) {
  var subgroups = [], subgroup, subnode, group, node;
  if (typeof selector !== "function") selector = d3_selection_selector(selector);
  for (var j = -1, m = this.length; ++j < m; ) {
  subgroups.push(subgroup = []);
  subgroup.parentNode = (group = this[j]).parentNode;
  for (var i = -1, n = group.length; ++i < n; ) {
  if (node = group[i]) {
  subgroup.push(subnode = selector.call(node, node.__data__, i));
  if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
  } else {
  subgroup.push(null);
  }
  }
  }
  return d3_selection(subgroups);
  };
  d3_selectionPrototype.selectAll = function(selector) {
  var subgroups = [], subgroup, node;
  if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
  for (var j = -1, m = this.length; ++j < m; ) {
  for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  if (node = group[i]) {
  subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));
  subgroup.parentNode = node;
  }
  }
  }
  return d3_selection(subgroups);
  };
  d3_selectionPrototype.attr = function(name, value) {
  if (arguments.length < 2) {
  if (typeof name === "string") {
  var node = this.node();
  name = d3.ns.qualify(name);
  return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
  }
  for (value in name) this.each(d3_selection_attr(value, name[value]));
  return this;
  }
  return this.each(d3_selection_attr(name, value));
  };
  d3_selectionPrototype.classed = function(name, value) {
  if (arguments.length < 2) {
  if (typeof name === "string") {
  var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1;
  if (value = node.classList) {
  while (++i < n) if (!value.contains(name[i])) return false;
  } else {
  value = node.className;
  if (value.baseVal != null) value = value.baseVal;
  while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
  }
  return true;
  }
  for (value in name) this.each(d3_selection_classed(value, name[value]));
  return this;
  }
  return this.each(d3_selection_classed(name, value));
  };
  d3_selectionPrototype.style = function(name, value, priority) {
  var n = arguments.length;
  if (n < 3) {
  if (typeof name !== "string") {
  if (n < 2) value = "";
  for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
  return this;
  }
  if (n < 2) return window.getComputedStyle(this.node(), null).getPropertyValue(name);
  priority = "";
  }
  return this.each(d3_selection_style(name, value, priority));
  };
  d3_selectionPrototype.property = function(name, value) {
  if (arguments.length < 2) {
  if (typeof name === "string") return this.node()[name];
  for (value in name) this.each(d3_selection_property(value, name[value]));
  return this;
  }
  return this.each(d3_selection_property(name, value));
  };
  d3_selectionPrototype.text = function(value) {
  return arguments.length < 1 ? this.node().textContent : this.each(typeof value === "function" ? function() {
  var v = value.apply(this, arguments);
  this.textContent = v == null ? "" : v;
  } : value == null ? function() {
  this.textContent = "";
  } : function() {
  this.textContent = value;
  });
  };
  d3_selectionPrototype.html = function(value) {
  return arguments.length < 1 ? this.node().innerHTML : this.each(typeof value === "function" ? function() {
  var v = value.apply(this, arguments);
  this.innerHTML = v == null ? "" : v;
  } : value == null ? function() {
  this.innerHTML = "";
  } : function() {
  this.innerHTML = value;
  });
  };
  d3_selectionPrototype.append = function(name) {
  function append() {
  return this.appendChild(document.createElementNS(this.namespaceURI, name));
  }
  function appendNS() {
  return this.appendChild(document.createElementNS(name.space, name.local));
  }
  name = d3.ns.qualify(name);
  return this.select(name.local ? appendNS : append);
  };
  d3_selectionPrototype.insert = function(name, before) {
  function insert() {
  return this.insertBefore(document.createElementNS(this.namespaceURI, name), d3_select(before, this));
  }
  function insertNS() {
  return this.insertBefore(document.createElementNS(name.space, name.local), d3_select(before, this));
  }
  name = d3.ns.qualify(name);
  return this.select(name.local ? insertNS : insert);
  };
  d3_selectionPrototype.remove = function() {
  return this.each(function() {
  var parent = this.parentNode;
  if (parent) parent.removeChild(this);
  });
  };
  d3_selectionPrototype.data = function(value, key) {
  function bind(group, groupData) {
  var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), n1 = Math.max(n, m), updateNodes = [], enterNodes = [], exitNodes = [], node, nodeData;
  if (key) {
  var nodeByKeyValue = new d3_Map, keyValues = [], keyValue, j = groupData.length;
  for (i = -1; ++i < n; ) {
  keyValue = key.call(node = group[i], node.__data__, i);
  if (nodeByKeyValue.has(keyValue)) {
  exitNodes[j++] = node;
  } else {
  nodeByKeyValue.set(keyValue, node);
  }
  keyValues.push(keyValue);
  }
  for (i = -1; ++i < m; ) {
  keyValue = key.call(groupData, nodeData = groupData[i], i);
  if (nodeByKeyValue.has(keyValue)) {
  updateNodes[i] = node = nodeByKeyValue.get(keyValue);
  node.__data__ = nodeData;
  enterNodes[i] = exitNodes[i] = null;
  } else {
  enterNodes[i] = d3_selection_dataNode(nodeData);
  updateNodes[i] = exitNodes[i] = null;
  }
  nodeByKeyValue.remove(keyValue);
  }
  for (i = -1; ++i < n; ) {
  if (nodeByKeyValue.has(keyValues[i])) {
  exitNodes[i] = group[i];
  }
  }
  } else {
  for (i = -1; ++i < n0; ) {
  node = group[i];
  nodeData = groupData[i];
  if (node) {
  node.__data__ = nodeData;
  updateNodes[i] = node;
  enterNodes[i] = exitNodes[i] = null;
  } else {
  enterNodes[i] = d3_selection_dataNode(nodeData);
  updateNodes[i] = exitNodes[i] = null;
  }
  }
  for (; i < m; ++i) {
  enterNodes[i] = d3_selection_dataNode(groupData[i]);
  updateNodes[i] = exitNodes[i] = null;
  }
  for (; i < n1; ++i) {
  exitNodes[i] = group[i];
  enterNodes[i] = updateNodes[i] = null;
  }
  }
  enterNodes.update = updateNodes;
  enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
  enter.push(enterNodes);
  update.push(updateNodes);
  exit.push(exitNodes);
  }
  var i = -1, n = this.length, group, node;
  if (!arguments.length) {
  value = new Array(n = (group = this[0]).length);
  while (++i < n) {
  if (node = group[i]) {
  value[i] = node.__data__;
  }
  }
  return value;
  }
  var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
  if (typeof value === "function") {
  while (++i < n) {
  bind(group = this[i], value.call(group, group.parentNode.__data__, i));
  }
  } else {
  while (++i < n) {
  bind(group = this[i], value);
  }
  }
  update.enter = function() {
  return enter;
  };
  update.exit = function() {
  return exit;
  };
  return update;
  };
  d3_selectionPrototype.datum = d3_selectionPrototype.map = function(value) {
  return arguments.length < 1 ? this.property("__data__") : this.property("__data__", value);
  };
  d3_selectionPrototype.filter = function(filter) {
  var subgroups = [], subgroup, group, node;
  if (typeof filter !== "function") filter = d3_selection_filter(filter);
  for (var j = 0, m = this.length; j < m; j++) {
  subgroups.push(subgroup = []);
  subgroup.parentNode = (group = this[j]).parentNode;
  for (var i = 0, n = group.length; i < n; i++) {
  if ((node = group[i]) && filter.call(node, node.__data__, i)) {
  subgroup.push(node);
  }
  }
  }
  return d3_selection(subgroups);
  };
  d3_selectionPrototype.order = function() {
  for (var j = -1, m = this.length; ++j < m; ) {
  for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
  if (node = group[i]) {
  if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
  next = node;
  }
  }
  }
  return this;
  };
  d3_selectionPrototype.sort = function(comparator) {
  comparator = d3_selection_sortComparator.apply(this, arguments);
  for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
  return this.order();
  };
  d3_selectionPrototype.on = function(type, listener, capture) {
  var n = arguments.length;
  if (n < 3) {
  if (typeof type !== "string") {
  if (n < 2) listener = false;
  for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
  return this;
  }
  if (n < 2) return (n = this.node()["__on" + type]) && n._;
  capture = false;
  }
  return this.each(d3_selection_on(type, listener, capture));
  };
  d3_selectionPrototype.each = function(callback) {
  return d3_selection_each(this, function(node, i, j) {
  callback.call(node, node.__data__, i, j);
  });
  };
  d3_selectionPrototype.call = function(callback) {
  callback.apply(this, (arguments[0] = this, arguments));
  return this;
  };
  d3_selectionPrototype.empty = function() {
  return !this.node();
  };
  d3_selectionPrototype.node = function(callback) {
  for (var j = 0, m = this.length; j < m; j++) {
  for (var group = this[j], i = 0, n = group.length; i < n; i++) {
  var node = group[i];
  if (node) return node;
  }
  }
  return null;
  };
  d3_selectionPrototype.transition = function() {
  var subgroups = [], subgroup, node;
  for (var j = -1, m = this.length; ++j < m; ) {
  subgroups.push(subgroup = []);
  for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  subgroup.push((node = group[i]) ? {
  node: node,
  delay: d3_transitionDelay,
  duration: d3_transitionDuration
  } : null);
  }
  }
  return d3_transition(subgroups, d3_transitionId || ++d3_transitionNextId, Date.now());
  };
  var d3_selectionRoot = d3_selection([ [ document ] ]);
  d3_selectionRoot[0].parentNode = d3_selectRoot;
  d3.select = function(selector) {
  return typeof selector === "string" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]);
  };
  d3.selectAll = function(selector) {
  return typeof selector === "string" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]);
  };
  var d3_selection_enterPrototype = [];
  d3.selection.enter = d3_selection_enter;
  d3.selection.enter.prototype = d3_selection_enterPrototype;
  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
  d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;
  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
  d3_selection_enterPrototype.select = function(selector) {
  var subgroups = [], subgroup, subnode, upgroup, group, node;
  for (var j = -1, m = this.length; ++j < m; ) {
  upgroup = (group = this[j]).update;
  subgroups.push(subgroup = []);
  subgroup.parentNode = group.parentNode;
  for (var i = -1, n = group.length; ++i < n; ) {
  if (node = group[i]) {
  subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));
  subnode.__data__ = node.__data__;
  } else {
  subgroup.push(null);
  }
  }
  }
  return d3_selection(subgroups);
  };
  var d3_transitionPrototype = [], d3_transitionNextId = 0, d3_transitionId = 0, d3_transitionDefaultDelay = 0, d3_transitionDefaultDuration = 250, d3_transitionDefaultEase = d3.ease("cubic-in-out"), d3_transitionDelay = d3_transitionDefaultDelay, d3_transitionDuration = d3_transitionDefaultDuration, d3_transitionEase = d3_transitionDefaultEase;
  d3_transitionPrototype.call = d3_selectionPrototype.call;
  d3.transition = function(selection) {
  return arguments.length ? d3_transitionId ? selection.transition() : selection : d3_selectionRoot.transition();
  };
  d3.transition.prototype = d3_transitionPrototype;
  d3_transitionPrototype.select = function(selector) {
  var subgroups = [], subgroup, subnode, node;
  if (typeof selector !== "function") selector = d3_selection_selector(selector);
  for (var j = -1, m = this.length; ++j < m; ) {
  subgroups.push(subgroup = []);
  for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) {
  if ("__data__" in node.node) subnode.__data__ = node.node.__data__;
  subgroup.push({
  node: subnode,
  delay: node.delay,
  duration: node.duration
  });
  } else {
  subgroup.push(null);
  }
  }
  }
  return d3_transition(subgroups, this.id, this.time).ease(this.ease());
  };
  d3_transitionPrototype.selectAll = function(selector) {
  var subgroups = [], subgroup, subnodes, node;
  if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
  for (var j = -1, m = this.length; ++j < m; ) {
  for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
  if (node = group[i]) {
  subnodes = selector.call(node.node, node.node.__data__, i);
  subgroups.push(subgroup = []);
  for (var k = -1, o = subnodes.length; ++k < o; ) {
  subgroup.push({
  node: subnodes[k],
  delay: node.delay,
  duration: node.duration
  });
  }
  }
  }
  }
  return d3_transition(subgroups, this.id, this.time).ease(this.ease());
  };
  d3_transitionPrototype.filter = function(filter) {
  var subgroups = [], subgroup, group, node;
  if (typeof filter !== "function") filter = d3_selection_filter(filter);
  for (var j = 0, m = this.length; j < m; j++) {
  subgroups.push(subgroup = []);
  for (var group = this[j], i = 0, n = group.length; i < n; i++) {
  if ((node = group[i]) && filter.call(node.node, node.node.__data__, i)) {
  subgroup.push(node);
  }
  }
  }
  return d3_transition(subgroups, this.id, this.time).ease(this.ease());
  };
  d3_transitionPrototype.attr = function(name, value) {
  if (arguments.length < 2) {
  for (value in name) this.attrTween(value, d3_tweenByName(name[value], value));
  return this;
  }
  return this.attrTween(name, d3_tweenByName(value, name));
  };
  d3_transitionPrototype.attrTween = function(nameNS, tween) {
  function attrTween(d, i) {
  var f = tween.call(this, d, i, this.getAttribute(name));
  return f === d3_tweenRemove ? (this.removeAttribute(name), null) : f && function(t) {
  this.setAttribute(name, f(t));
  };
  }
  function attrTweenNS(d, i) {
  var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
  return f === d3_tweenRemove ? (this.removeAttributeNS(name.space, name.local), null) : f && function(t) {
  this.setAttributeNS(name.space, name.local, f(t));
  };
  }
  var name = d3.ns.qualify(nameNS);
  return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
  };
  d3_transitionPrototype.style = function(name, value, priority) {
  var n = arguments.length;
  if (n < 3) {
  if (typeof name !== "string") {
  if (n < 2) value = "";
  for (priority in name) this.styleTween(priority, d3_tweenByName(name[priority], priority), value);
  return this;
  }
  priority = "";
  }
  return this.styleTween(name, d3_tweenByName(value, name), priority);
  };
  d3_transitionPrototype.styleTween = function(name, tween, priority) {
  if (arguments.length < 3) priority = "";
  return this.tween("style." + name, function(d, i) {
  var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
  return f === d3_tweenRemove ? (this.style.removeProperty(name), null) : f && function(t) {
  this.style.setProperty(name, f(t), priority);
  };
  });
  };
  d3_transitionPrototype.text = function(value) {
  return this.tween("text", function(d, i) {
  this.textContent = typeof value === "function" ? value.call(this, d, i) : value;
  });
  };
  d3_transitionPrototype.remove = function() {
  return this.each("end.transition", function() {
  var p;
  if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
  });
  };
  d3_transitionPrototype.delay = function(value) {
  return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
  node.delay = value.call(node = node.node, node.__data__, i, j) | 0;
  } : (value = value | 0, function(node) {
  node.delay = value;
  }));
  };
  d3_transitionPrototype.duration = function(value) {
  return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
  node.duration = Math.max(1, value.call(node = node.node, node.__data__, i, j) | 0);
  } : (value = Math.max(1, value | 0), function(node) {
  node.duration = value;
  }));
  };
  d3_transitionPrototype.transition = function() {
  return this.select(d3_this);
  };
  d3.tween = function(b, interpolate) {
  function tweenFunction(d, i, a) {
  var v = b.call(this, d, i);
  return v == null ? a != "" && d3_tweenRemove : a != v && interpolate(a, v + "");
  }
  function tweenString(d, i, a) {
  return a != b && interpolate(a, b);
  }
  return typeof b === "function" ? tweenFunction : b == null ? d3_tweenNull : (b += "", tweenString);
  };
  var d3_tweenRemove = {};
  var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
  d3.timer = function(callback, delay, then) {
  if (arguments.length < 3) {
  if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
  then = Date.now();
  }
  var timer = d3_timer_byId[callback.id];
  if (timer && timer.callback === callback) {
  timer.then = then;
  timer.delay = delay;
  } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
  callback: callback,
  then: then,
  delay: delay,
  next: d3_timer_queue
  };
  if (!d3_timer_interval) {
  d3_timer_timeout = clearTimeout(d3_timer_timeout);
  d3_timer_interval = 1;
  d3_timer_frame(d3_timer_step);
  }
  };
  d3.timer.flush = function() {
  var elapsed, now = Date.now(), t1 = d3_timer_queue;
  while (t1) {
  elapsed = now - t1.then;
  if (!t1.delay) t1.flush = t1.callback(elapsed);
  t1 = t1.next;
  }
  d3_timer_flush();
  };
  var d3_timer_frame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
  setTimeout(callback, 17);
  };
  d3.mouse = function(container) {
  return d3_mousePoint(container, d3_eventSource());
  };
  var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
  d3.touches = function(container, touches) {
  if (arguments.length < 2) touches = d3_eventSource().touches;
  return touches ? d3_array(touches).map(function(touch) {
  var point = d3_mousePoint(container, touch);
  point.identifier = touch.identifier;
  return point;
  }) : [];
  };
  d3.scale = {};
  d3.scale.linear = function() {
  return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3.interpolate, false);
  };
  d3.scale.log = function() {
  return d3_scale_log(d3.scale.linear(), d3_scale_logp);
  };
  var d3_scale_logFormat = d3.format(".0e");
  d3_scale_logp.pow = function(x) {
  return Math.pow(10, x);
  };
  d3_scale_logn.pow = function(x) {
  return -Math.pow(10, -x);
  };
  d3.scale.pow = function() {
  return d3_scale_pow(d3.scale.linear(), 1);
  };
  d3.scale.sqrt = function() {
  return d3.scale.pow().exponent(.5);
  };
  d3.scale.ordinal = function() {
  return d3_scale_ordinal([], {
  t: "range",
  a: [ [] ]
  });
  };
  d3.scale.category10 = function() {
  return d3.scale.ordinal().range(d3_category10);
  };
  d3.scale.category20 = function() {
  return d3.scale.ordinal().range(d3_category20);
  };
  d3.scale.category20b = function() {
  return d3.scale.ordinal().range(d3_category20b);
  };
  d3.scale.category20c = function() {
  return d3.scale.ordinal().range(d3_category20c);
  };
  var d3_category10 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ];
  var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ];
  var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ];
  var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ];
  d3.scale.quantile = function() {
  return d3_scale_quantile([], []);
  };
  d3.scale.quantize = function() {
  return d3_scale_quantize(0, 1, [ 0, 1 ]);
  };
  d3.scale.threshold = function() {
  return d3_scale_threshold([ .5 ], [ 0, 1 ]);
  };
  d3.scale.identity = function() {
  return d3_scale_identity([ 0, 1 ]);
  };
  d3.svg = {};
  d3.svg.arc = function() {
  function arc() {
  var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0), df = da < Math.PI ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
  return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
  }
  var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
  arc.innerRadius = function(v) {
  if (!arguments.length) return innerRadius;
  innerRadius = d3_functor(v);
  return arc;
  };
  arc.outerRadius = function(v) {
  if (!arguments.length) return outerRadius;
  outerRadius = d3_functor(v);
  return arc;
  };
  arc.startAngle = function(v) {
  if (!arguments.length) return startAngle;
  startAngle = d3_functor(v);
  return arc;
  };
  arc.endAngle = function(v) {
  if (!arguments.length) return endAngle;
  endAngle = d3_functor(v);
  return arc;
  };
  arc.centroid = function() {
  var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
  return [ Math.cos(a) * r, Math.sin(a) * r ];
  };
  return arc;
  };
  var d3_svg_arcOffset = -Math.PI / 2, d3_svg_arcMax = 2 * Math.PI - 1e-6;
  d3.svg.line = function() {
  return d3_svg_line(d3_identity);
  };
  var d3_svg_lineInterpolators = d3.map({
  linear: d3_svg_lineLinear,
  "linear-closed": d3_svg_lineLinearClosed,
  "step-before": d3_svg_lineStepBefore,
  "step-after": d3_svg_lineStepAfter,
  basis: d3_svg_lineBasis,
  "basis-open": d3_svg_lineBasisOpen,
  "basis-closed": d3_svg_lineBasisClosed,
  bundle: d3_svg_lineBundle,
  cardinal: d3_svg_lineCardinal,
  "cardinal-open": d3_svg_lineCardinalOpen,
  "cardinal-closed": d3_svg_lineCardinalClosed,
  monotone: d3_svg_lineMonotone
  });
  d3_svg_lineInterpolators.forEach(function(key, value) {
  value.key = key;
  value.closed = /-closed$/.test(key);
  });
  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 ];
  d3.svg.line.radial = function() {
  var line = d3_svg_line(d3_svg_lineRadial);
  line.radius = line.x, delete line.x;
  line.angle = line.y, delete line.y;
  return line;
  };
  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
  d3.svg.area = function() {
  return d3_svg_area(d3_identity);
  };
  d3.svg.area.radial = function() {
  var area = d3_svg_area(d3_svg_lineRadial);
  area.radius = area.x, delete area.x;
  area.innerRadius = area.x0, delete area.x0;
  area.outerRadius = area.x1, delete area.x1;
  area.angle = area.y, delete area.y;
  area.startAngle = area.y0, delete area.y0;
  area.endAngle = area.y1, delete area.y1;
  return area;
  };
  d3.svg.chord = function() {
  function chord(d, i) {
  var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
  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";
  }
  function subgroup(self, f, d, i) {
  var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
  return {
  r: r,
  a0: a0,
  a1: a1,
  p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
  p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
  };
  }
  function equals(a, b) {
  return a.a0 == b.a0 && a.a1 == b.a1;
  }
  function arc(r, p, a) {
  return "A" + r + "," + r + " 0 " + +(a > Math.PI) + ",1 " + p;
  }
  function curve(r0, p0, r1, p1) {
  return "Q 0,0 " + p1;
  }
  var source = d3_svg_chordSource, target = d3_svg_chordTarget, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
  chord.radius = function(v) {
  if (!arguments.length) return radius;
  radius = d3_functor(v);
  return chord;
  };
  chord.source = function(v) {
  if (!arguments.length) return source;
  source = d3_functor(v);
  return chord;
  };
  chord.target = function(v) {
  if (!arguments.length) return target;
  target = d3_functor(v);
  return chord;
  };
  chord.startAngle = function(v) {
  if (!arguments.length) return startAngle;
  startAngle = d3_functor(v);
  return chord;
  };
  chord.endAngle = function(v) {
  if (!arguments.length) return endAngle;
  endAngle = d3_functor(v);
  return chord;
  };
  return chord;
  };
  d3.svg.diagonal = function() {
  function diagonal(d, i) {
  var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
  x: p0.x,
  y: m
  }, {
  x: p3.x,
  y: m
  }, p3 ];
  p = p.map(projection);
  return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
  }
  var source = d3_svg_chordSource, target = d3_svg_chordTarget, projection = d3_svg_diagonalProjection;
  diagonal.source = function(x) {
  if (!arguments.length) return source;
  source = d3_functor(x);
  return diagonal;
  };
  diagonal.target = function(x) {
  if (!arguments.length) return target;
  target = d3_functor(x);
  return diagonal;
  };
  diagonal.projection = function(x) {
  if (!arguments.length) return projection;
  projection = x;
  return diagonal;
  };
  return diagonal;
  };
  d3.svg.diagonal.radial = function() {
  var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
  diagonal.projection = function(x) {
  return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
  };
  return diagonal;
  };
  d3.svg.mouse = d3.mouse;
  d3.svg.touches = d3.touches;
  d3.svg.symbol = function() {
  function symbol(d, i) {
  return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
  }
  var type = d3_svg_symbolType, size = d3_svg_symbolSize;
  symbol.type = function(x) {
  if (!arguments.length) return type;
  type = d3_functor(x);
  return symbol;
  };
  symbol.size = function(x) {
  if (!arguments.length) return size;
  size = d3_functor(x);
  return symbol;
  };
  return symbol;
  };
  var d3_svg_symbols = d3.map({
  circle: d3_svg_symbolCircle,
  cross: function(size) {
  var r = Math.sqrt(size / 5) / 2;
  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";
  },
  diamond: function(size) {
  var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
  return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
  },
  square: function(size) {
  var r = Math.sqrt(size) / 2;
  return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
  },
  "triangle-down": function(size) {
  var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
  return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
  },
  "triangle-up": function(size) {
  var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
  return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
  }
  });
  d3.svg.symbolTypes = d3_svg_symbols.keys();
  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180);
  d3.svg.axis = function() {
  function axis(g) {
  g.each(function() {
  var g = d3.select(this);
  var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;
  var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", "g").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1);
  var tick = g.selectAll("g").data(ticks, String), tickEnter = tick.enter().insert("g", "path").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
  var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathEnter = path.enter().append("path").attr("class", "domain"), pathUpdate = d3.transition(path);
  var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;
  this.__chart__ = scale1;
  tickEnter.append("line").attr("class", "tick");
  tickEnter.append("text");
  var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
  switch (orient) {
  case "bottom":
  {
  tickTransform = d3_svg_axisX;
  subtickEnter.attr("y2", tickMinorSize);
  subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
  lineEnter.attr("y2", tickMajorSize);
  textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding);
  lineUpdate.attr("x2", 0).attr("y2", tickMajorSize);
  textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding);
  text.attr("dy", ".71em").attr("text-anchor", "middle");
  pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
  break;
  }
  case "top":
  {
  tickTransform = d3_svg_axisX;
  subtickEnter.attr("y2", -tickMinorSize);
  subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
  lineEnter.attr("y2", -tickMajorSize);
  textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
  lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize);
  textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
  text.attr("dy", "0em").attr("text-anchor", "middle");
  pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
  break;
  }
  case "left":
  {
  tickTransform = d3_svg_axisY;
  subtickEnter.attr("x2", -tickMinorSize);
  subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
  lineEnter.attr("x2", -tickMajorSize);
  textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding));
  lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0);
  textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0);
  text.attr("dy", ".32em").attr("text-anchor", "end");
  pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
  break;
  }
  case "right":
  {
  tickTransform = d3_svg_axisY;
  subtickEnter.attr("x2", tickMinorSize);
  subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
  lineEnter.attr("x2", tickMajorSize);
  textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding);
  lineUpdate.attr("x2", tickMajorSize).attr("y2", 0);
  textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0);
  text.attr("dy", ".32em").attr("text-anchor", "start");
  pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
  break;
  }
  }
  if (scale.ticks) {
  tickEnter.call(tickTransform, scale0);
  tickUpdate.call(tickTransform, scale1);
  tickExit.call(tickTransform, scale1);
  subtickEnter.call(tickTransform, scale0);
  subtickUpdate.call(tickTransform, scale1);
  subtickExit.call(tickTransform, scale1);
  } else {
  var dx = scale1.rangeBand() / 2, x = function(d) {
  return scale1(d) + dx;
  };
  tickEnter.call(tickTransform, x);
  tickUpdate.call(tickTransform, x);
  }
  });
  }
  var scale = d3.scale.linear(), orient = "bottom", tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;
  axis.scale = function(x) {
  if (!arguments.length) return scale;
  scale = x;
  return axis;
  };
  axis.orient = function(x) {
  if (!arguments.length) return orient;
  orient = x;
  return axis;
  };
  axis.ticks = function() {
  if (!arguments.length) return tickArguments_;
  tickArguments_ = arguments;
  return axis;
  };
  axis.tickValues = function(x) {
  if (!arguments.length) return tickValues;
  tickValues = x;
  return axis;
  };
  axis.tickFormat = function(x) {
  if (!arguments.length) return tickFormat_;
  tickFormat_ = x;
  return axis;
  };
  axis.tickSize = function(x, y, z) {
  if (!arguments.length) return tickMajorSize;
  var n = arguments.length - 1;
  tickMajorSize = +x;
  tickMinorSize = n > 1 ? +y : tickMajorSize;
  tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
  return axis;
  };
  axis.tickPadding = function(x) {
  if (!arguments.length) return tickPadding;
  tickPadding = +x;
  return axis;
  };
  axis.tickSubdivide = function(x) {
  if (!arguments.length) return tickSubdivide;
  tickSubdivide = +x;
  return axis;
  };
  return axis;
  };
  d3.svg.brush = function() {
  function brush(g) {
  g.each(function() {
  var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e;
  g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
  bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
  fg.enter().append("rect").attr("class", "extent").style("cursor", "move");
  tz.enter().append("g").attr("class", function(d) {
  return "resize " + d;
  }).style("cursor", function(d) {
  return d3_svg_brushCursor[d];
  }).append("rect").attr("x", function(d) {
  return /[ew]$/.test(d) ? -3 : null;
  }).attr("y", function(d) {
  return /^[ns]/.test(d) ? -3 : null;
  }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
  tz.style("display", brush.empty() ? "none" : null);
  tz.exit().remove();
  if (x) {
  e = d3_scaleRange(x);
  bg.attr("x", e[0]).attr("width", e[1] - e[0]);
  redrawX(g);
  }
  if (y) {
  e = d3_scaleRange(y);
  bg.attr("y", e[0]).attr("height", e[1] - e[0]);
  redrawY(g);
  }
  redraw(g);
  });
  }
  function redraw(g) {
  g.selectAll(".resize").attr("transform", function(d) {
  return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")";
  });
  }
  function redrawX(g) {
  g.select(".extent").attr("x", extent[0][0]);
  g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]);
  }
  function redrawY(g) {
  g.select(".extent").attr("y", extent[0][1]);
  g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]);
  }
  function brushstart() {
  function mouse() {
  var touches = d3.event.changedTouches;
  return touches ? d3.touches(target, touches)[0] : d3.mouse(target);
  }
  function keydown() {
  if (d3.event.keyCode == 32) {
  if (!dragging) {
  center = null;
  origin[0] -= extent[1][0];
  origin[1] -= extent[1][1];
  dragging = 2;
  }
  d3_eventCancel();
  }
  }
  function keyup() {
  if (d3.event.keyCode == 32 && dragging == 2) {
  origin[0] += extent[1][0];
  origin[1] += extent[1][1];
  dragging = 0;
  d3_eventCancel();
  }
  }
  function brushmove() {
  var point = mouse(), moved = false;
  if (offset) {
  point[0] += offset[0];
  point[1] += offset[1];
  }
  if (!dragging) {
  if (d3.event.altKey) {
  if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];
  origin[0] = extent[+(point[0] < center[0])][0];
  origin[1] = extent[+(point[1] < center[1])][1];
  } else center = null;
  }
  if (resizingX && move1(point, x, 0)) {
  redrawX(g);
  moved = true;
  }
  if (resizingY && move1(point, y, 1)) {
  redrawY(g);
  moved = true;
  }
  if (moved) {
  redraw(g);
  event_({
  type: "brush",
  mode: dragging ? "move" : "resize"
  });
  }
  }
  function move1(point, scale, i) {
  var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;
  if (dragging) {
  r0 -= position;
  r1 -= size + position;
  }
  min = Math.max(r0, Math.min(r1, point[i]));
  if (dragging) {
  max = (min += position) + size;
  } else {
  if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
  if (position < min) {
  max = min;
  min = position;
  } else {
  max = position;
  }
  }
  if (extent[0][i] !== min || extent[1][i] !== max) {
  extentDomain = null;
  extent[0][i] = min;
  extent[1][i] = max;
  return true;
  }
  }
  function brushend() {
  brushmove();
  g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
  d3.select("body").style("cursor", null);
  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);
  event_({
  type: "brushend"
  });
  d3_eventCancel();
  }
  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"), center, origin = mouse(), offset;
  var w = d3.select(window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup);
  if (dragging) {
  origin[0] = extent[0][0] - origin[0];
  origin[1] = extent[0][1] - origin[1];
  } else if (resizing) {
  var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
  offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];
  origin[0] = extent[ex][0];
  origin[1] = extent[ey][1];
  } else if (d3.event.altKey) center = origin.slice();
  g.style("pointer-events", "none").selectAll(".resize").style("display", null);
  d3.select("body").style("cursor", eventTarget.style("cursor"));
  event_({
  type: "brushstart"
  });
  brushmove();
  d3_eventCancel();
  }
  var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;
  brush.x = function(z) {
  if (!arguments.length) return x;
  x = z;
  resizes = d3_svg_brushResizes[!x << 1 | !y];
  return brush;
  };
  brush.y = function(z) {
  if (!arguments.length) return y;
  y = z;
  resizes = d3_svg_brushResizes[!x << 1 | !y];
  return brush;
  };
  brush.extent = function(z) {
  var x0, x1, y0, y1, t;
  if (!arguments.length) {
  z = extentDomain || extent;
  if (x) {
  x0 = z[0][0], x1 = z[1][0];
  if (!extentDomain) {
  x0 = extent[0][0], x1 = extent[1][0];
  if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
  if (x1 < x0) t = x0, x0 = x1, x1 = t;
  }
  }
  if (y) {
  y0 = z[0][1], y1 = z[1][1];
  if (!extentDomain) {
  y0 = extent[0][1], y1 = extent[1][1];
  if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
  if (y1 < y0) t = y0, y0 = y1, y1 = t;
  }
  }
  return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
  }
  extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];
  if (x) {
  x0 = z[0], x1 = z[1];
  if (y) x0 = x0[0], x1 = x1[0];
  extentDomain[0][0] = x0, extentDomain[1][0] = x1;
  if (x.invert) x0 = x(x0), x1 = x(x1);
  if (x1 < x0) t = x0, x0 = x1, x1 = t;
  extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;
  }
  if (y) {
  y0 = z[0], y1 = z[1];
  if (x) y0 = y0[1], y1 = y1[1];
  extentDomain[0][1] = y0, extentDomain[1][1] = y1;
  if (y.invert) y0 = y(y0), y1 = y(y1);
  if (y1 < y0) t = y0, y0 = y1, y1 = t;
  extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;
  }
  return brush;
  };
  brush.clear = function() {
  extentDomain = null;
  extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;
  return brush;
  };
  brush.empty = function() {
  return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];
  };
  return d3.rebind(brush, event, "on");
  };
  var d3_svg_brushCursor = {
  n: "ns-resize",
  e: "ew-resize",
  s: "ns-resize",
  w: "ew-resize",
  nw: "nwse-resize",
  ne: "nesw-resize",
  se: "nwse-resize",
  sw: "nesw-resize"
  };
  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
  d3.behavior = {};
  d3.behavior.drag = function() {
  function drag() {
  this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown);
  }
  function mousedown() {
  function point() {
  var p = target.parentNode;
  return touchId ? d3.touches(p).filter(function(p) {
  return p.identifier === touchId;
  })[0] : d3.mouse(p);
  }
  function dragmove() {
  if (!target.parentNode) return dragend();
  var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
  moved |= dx | dy;
  origin_ = p;
  d3_eventCancel();
  event_({
  type: "drag",
  x: p[0] + offset[0],
  y: p[1] + offset[1],
  dx: dx,
  dy: dy
  });
  }
  function dragend() {
  event_({
  type: "dragend"
  });
  if (moved) {
  d3_eventCancel();
  if (d3.event.target === eventTarget) w.on("click.drag", click, true);
  }
  w.on(touchId ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId ? "touchend.drag-" + touchId : "mouseup.drag", null);
  }
  function click() {
  d3_eventCancel();
  w.on("click.drag", null);
  }
  var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches && d3.event.changedTouches[0].identifier, offset, origin_ = point(), moved = 0;
  var w = d3.select(window).on(touchId ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
  if (origin) {
  offset = origin.apply(target, arguments);
  offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
  } else {
  offset = [ 0, 0 ];
  }
  if (!touchId) d3_eventCancel();
  event_({
  type: "dragstart"
  });
  }
  var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null;
  drag.origin = function(x) {
  if (!arguments.length) return origin;
  origin = x;
  return drag;
  };
  return d3.rebind(drag, event, "on");
  };
  d3.behavior.zoom = function() {
  function zoom() {
  this.on("mousedown.zoom", mousedown).on("mousewheel.zoom", mousewheel).on("mousemove.zoom", mousemove).on("DOMMouseScroll.zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart);
  }
  function location(p) {
  return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];
  }
  function point(l) {
  return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];
  }
  function scaleTo(s) {
  scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
  }
  function translateTo(p, l) {
  l = point(l);
  translate[0] += p[0] - l[0];
  translate[1] += p[1] - l[1];
  }
  function dispatch(event) {
  if (x1) x1.domain(x0.range().map(function(x) {
  return (x - translate[0]) / scale;
  }).map(x0.invert));
  if (y1) y1.domain(y0.range().map(function(y) {
  return (y - translate[1]) / scale;
  }).map(y0.invert));
  d3.event.preventDefault();
  event({
  type: "zoom",
  scale: scale,
  translate: translate
  });
  }
  function mousedown() {
  function mousemove() {
  moved = 1;
  translateTo(d3.mouse(target), l);
  dispatch(event_);
  }
  function mouseup() {
  if (moved) d3_eventCancel();
  w.on("mousemove.zoom", null).on("mouseup.zoom", null);
  if (moved && d3.event.target === eventTarget) w.on("click.zoom", click, true);
  }
  function click() {
  d3_eventCancel();
  w.on("click.zoom", null);
  }
  var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target));
  window.focus();
  d3_eventCancel();
  }
  function mousewheel() {
  if (!translate0) translate0 = location(d3.mouse(this));
  scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
  translateTo(d3.mouse(this), translate0);
  dispatch(event.of(this, arguments));
  }
  function mousemove() {
  translate0 = null;
  }
  function dblclick() {
  var p = d3.mouse(this), l = location(p);
  scaleTo(d3.event.shiftKey ? scale / 2 : scale * 2);
  translateTo(p, l);
  dispatch(event.of(this, arguments));
  }
  function touchstart() {
  var touches = d3.touches(this), now = Date.now();
  scale0 = scale;
  translate0 = {};
  touches.forEach(function(t) {
  translate0[t.identifier] = location(t);
  });
  d3_eventCancel();
  if (touches.length === 1) {
  if (now - touchtime < 500) {
  var p = touches[0], l = location(touches[0]);
  scaleTo(scale * 2);
  translateTo(p, l);
  dispatch(event.of(this, arguments));
  }
  touchtime = now;
  }
  }
  function touchmove() {
  var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];
  if (p1 = touches[1]) {
  var p1, l1 = translate0[p1.identifier];
  p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
  l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
  scaleTo(d3.event.scale * scale0);
  }
  translateTo(p0, l0);
  touchtime = null;
  dispatch(event.of(this, arguments));
  }
  var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime;
  zoom.translate = function(x) {
  if (!arguments.length) return translate;
  translate = x.map(Number);
  return zoom;
  };
  zoom.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return zoom;
  };
  zoom.scaleExtent = function(x) {
  if (!arguments.length) return scaleExtent;
  scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
  return zoom;
  };
  zoom.x = function(z) {
  if (!arguments.length) return x1;
  x1 = z;
  x0 = z.copy();
  return zoom;
  };
  zoom.y = function(z) {
  if (!arguments.length) return y1;
  y1 = z;
  y0 = z.copy();
  return zoom;
  };
  return d3.rebind(zoom, event, "on");
  };
  var d3_behavior_zoomDiv, d3_behavior_zoomInfinity = [ 0, Infinity ];
  d3.layout = {};
  d3.layout.bundle = function() {
  return function(links) {
  var paths = [], i = -1, n = links.length;
  while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
  return paths;
  };
  };
  d3.layout.chord = function() {
  function relayout() {
  var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
  chords = [];
  groups = [];
  k = 0, i = -1;
  while (++i < n) {
  x = 0, j = -1;
  while (++j < n) {
  x += matrix[i][j];
  }
  groupSums.push(x);
  subgroupIndex.push(d3.range(n));
  k += x;
  }
  if (sortGroups) {
  groupIndex.sort(function(a, b) {
  return sortGroups(groupSums[a], groupSums[b]);
  });
  }
  if (sortSubgroups) {
  subgroupIndex.forEach(function(d, i) {
  d.sort(function(a, b) {
  return sortSubgroups(matrix[i][a], matrix[i][b]);
  });
  });
  }
  k = (2 * Math.PI - padding * n) / k;
  x = 0, i = -1;
  while (++i < n) {
  x0 = x, j = -1;
  while (++j < n) {
  var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
  subgroups[di + "-" + dj] = {
  index: di,
  subindex: dj,
  startAngle: a0,
  endAngle: a1,
  value: v
  };
  }
  groups[di] = {
  index: di,
  startAngle: x0,
  endAngle: x,
  value: (x - x0) / k
  };
  x += padding;
  }
  i = -1;
  while (++i < n) {
  j = i - 1;
  while (++j < n) {
  var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
  if (source.value || target.value) {
  chords.push(source.value < target.value ? {
  source: target,
  target: source
  } : {
  source: source,
  target: target
  });
  }
  }
  }
  if (sortChords) resort();
  }
  function resort() {
  chords.sort(function(a, b) {
  return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
  });
  }
  var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
  chord.matrix = function(x) {
  if (!arguments.length) return matrix;
  n = (matrix = x) && matrix.length;
  chords = groups = null;
  return chord;
  };
  chord.padding = function(x) {
  if (!arguments.length) return padding;
  padding = x;
  chords = groups = null;
  return chord;
  };
  chord.sortGroups = function(x) {
  if (!arguments.length) return sortGroups;
  sortGroups = x;
  chords = groups = null;
  return chord;
  };
  chord.sortSubgroups = function(x) {
  if (!arguments.length) return sortSubgroups;
  sortSubgroups = x;
  chords = null;
  return chord;
  };
  chord.sortChords = function(x) {
  if (!arguments.length) return sortChords;
  sortChords = x;
  if (chords) resort();
  return chord;
  };
  chord.chords = function() {
  if (!chords) relayout();
  return chords;
  };
  chord.groups = function() {
  if (!groups) relayout();
  return groups;
  };
  return chord;
  };
  d3.layout.force = function() {
  function repulse(node) {
  return function(quad, x1, y1, x2, y2) {
  if (quad.point !== node) {
  var dx = quad.cx - node.x, dy = quad.cy - node.y, dn = 1 / Math.sqrt(dx * dx + dy * dy);
  if ((x2 - x1) * dn < theta) {
  var k = quad.charge * dn * dn;
  node.px -= dx * k;
  node.py -= dy * k;
  return true;
  }
  if (quad.point && isFinite(dn)) {
  var k = quad.pointCharge * dn * dn;
  node.px -= dx * k;
  node.py -= dy * k;
  }
  }
  return !quad.charge;
  };
  }
  function dragmove(d) {
  d.px = d3.event.x;
  d.py = d3.event.y;
  force.resume();
  }
  var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, gravity = .1, theta = .8, interval, nodes = [], links = [], distances, strengths, charges;
  force.tick = function() {
  if ((alpha *= .99) < .005) {
  event.end({
  type: "end",
  alpha: alpha = 0
  });
  return true;
  }
  var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
  for (i = 0; i < m; ++i) {
  o = links[i];
  s = o.source;
  t = o.target;
  x = t.x - s.x;
  y = t.y - s.y;
  if (l = x * x + y * y) {
  l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
  x *= l;
  y *= l;
  t.x -= x * (k = s.weight / (t.weight + s.weight));
  t.y -= y * k;
  s.x += x * (k = 1 - k);
  s.y += y * k;
  }
  }
  if (k = alpha * gravity) {
  x = size[0] / 2;
  y = size[1] / 2;
  i = -1;
  if (k) while (++i < n) {
  o = nodes[i];
  o.x += (x - o.x) * k;
  o.y += (y - o.y) * k;
  }
  }
  if (charge) {
  d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
  i = -1;
  while (++i < n) {
  if (!(o = nodes[i]).fixed) {
  q.visit(repulse(o));
  }
  }
  }
  i = -1;
  while (++i < n) {
  o = nodes[i];
  if (o.fixed) {
  o.x = o.px;
  o.y = o.py;
  } else {
  o.x -= (o.px - (o.px = o.x)) * friction;
  o.y -= (o.py - (o.py = o.y)) * friction;
  }
  }
  event.tick({
  type: "tick",
  alpha: alpha
  });
  };
  force.nodes = function(x) {
  if (!arguments.length) return nodes;
  nodes = x;
  return force;
  };
  force.links = function(x) {
  if (!arguments.length) return links;
  links = x;
  return force;
  };
  force.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return force;
  };
  force.linkDistance = function(x) {
  if (!arguments.length) return linkDistance;
  linkDistance = d3_functor(x);
  return force;
  };
  force.distance = force.linkDistance;
  force.linkStrength = function(x) {
  if (!arguments.length) return linkStrength;
  linkStrength = d3_functor(x);
  return force;
  };
  force.friction = function(x) {
  if (!arguments.length) return friction;
  friction = x;
  return force;
  };
  force.charge = function(x) {
  if (!arguments.length) return charge;
  charge = typeof x === "function" ? x : +x;
  return force;
  };
  force.gravity = function(x) {
  if (!arguments.length) return gravity;
  gravity = x;
  return force;
  };
  force.theta = function(x) {
  if (!arguments.length) return theta;
  theta = x;
  return force;
  };
  force.alpha = function(x) {
  if (!arguments.length) return alpha;
  if (alpha) {
  if (x > 0) alpha = x; else alpha = 0;
  } else if (x > 0) {
  event.start({
  type: "start",
  alpha: alpha = x
  });
  d3.timer(force.tick);
  }
  return force;
  };
  force.start = function() {
  function position(dimension, size) {
  var neighbors = neighbor(i), j = -1, m = neighbors.length, x;
  while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
  return Math.random() * size;
  }
  function neighbor() {
  if (!neighbors) {
  neighbors = [];
  for (j = 0; j < n; ++j) {
  neighbors[j] = [];
  }
  for (j = 0; j < m; ++j) {
  var o = links[j];
  neighbors[o.source.index].push(o.target);
  neighbors[o.target.index].push(o.source);
  }
  }
  return neighbors[i];
  }
  var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
  for (i = 0; i < n; ++i) {
  (o = nodes[i]).index = i;
  o.weight = 0;
  }
  distances = [];
  strengths = [];
  for (i = 0; i < m; ++i) {
  o = links[i];
  if (typeof o.source == "number") o.source = nodes[o.source];
  if (typeof o.target == "number") o.target = nodes[o.target];
  distances[i] = linkDistance.call(this, o, i);
  strengths[i] = linkStrength.call(this, o, i);
  ++o.source.weight;
  ++o.target.weight;
  }
  for (i = 0; i < n; ++i) {
  o = nodes[i];
  if (isNaN(o.x)) o.x = position("x", w);
  if (isNaN(o.y)) o.y = position("y", h);
  if (isNaN(o.px)) o.px = o.x;
  if (isNaN(o.py)) o.py = o.y;
  }
  charges = [];
  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;
  }
  }
  return force.resume();
  };
  force.resume = function() {
  return force.alpha(.1);
  };
  force.stop = function() {
  return force.alpha(0);
  };
  force.drag = function() {
  if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart", d3_layout_forceDragstart).on("drag", dragmove).on("dragend", d3_layout_forceDragend);
  this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
  };
  return d3.rebind(force, event, "on");
  };
  d3.layout.partition = function() {
  function position(node, x, dx, dy) {
  var children = node.children;
  node.x = x;
  node.y = node.depth * dy;
  node.dx = dx;
  node.dy = dy;
  if (children && (n = children.length)) {
  var i = -1, n, c, d;
  dx = node.value ? dx / node.value : 0;
  while (++i < n) {
  position(c = children[i], x, d = c.value * dx, dy);
  x += d;
  }
  }
  }
  function depth(node) {
  var children = node.children, d = 0;
  if (children && (n = children.length)) {
  var i = -1, n;
  while (++i < n) d = Math.max(d, depth(children[i]));
  }
  return 1 + d;
  }
  function partition(d, i) {
  var nodes = hierarchy.call(this, d, i);
  position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
  return nodes;
  }
  var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
  partition.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return partition;
  };
  return d3_layout_hierarchyRebind(partition, hierarchy);
  };
  d3.layout.pie = function() {
  function pie(data, i) {
  var values = data.map(function(d, i) {
  return +value.call(pie, d, i);
  });
  var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
  var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values);
  var index = d3.range(data.length);
  if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
  return values[j] - values[i];
  } : function(i, j) {
  return sort(data[i], data[j]);
  });
  var arcs = [];
  index.forEach(function(i) {
  var d;
  arcs[i] = {
  data: data[i],
  value: d = values[i],
  startAngle: a,
  endAngle: a += d * k
  };
  });
  return arcs;
  }
  var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * Math.PI;
  pie.value = function(x) {
  if (!arguments.length) return value;
  value = x;
  return pie;
  };
  pie.sort = function(x) {
  if (!arguments.length) return sort;
  sort = x;
  return pie;
  };
  pie.startAngle = function(x) {
  if (!arguments.length) return startAngle;
  startAngle = x;
  return pie;
  };
  pie.endAngle = function(x) {
  if (!arguments.length) return endAngle;
  endAngle = x;
  return pie;
  };
  return pie;
  };
  var d3_layout_pieSortByValue = {};
  d3.layout.stack = function() {
  function stack(data, index) {
  var series = data.map(function(d, i) {
  return values.call(stack, d, i);
  });
  var points = series.map(function(d, i) {
  return d.map(function(v, i) {
  return [ x.call(stack, v, i), y.call(stack, v, i) ];
  });
  });
  var orders = order.call(stack, points, index);
  series = d3.permute(series, orders);
  points = d3.permute(points, orders);
  var offsets = offset.call(stack, points, index);
  var n = series.length, m = series[0].length, i, j, o;
  for (j = 0; j < m; ++j) {
  out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
  for (i = 1; i < n; ++i) {
  out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
  }
  }
  return data;
  }
  var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
  stack.values = function(x) {
  if (!arguments.length) return values;
  values = x;
  return stack;
  };
  stack.order = function(x) {
  if (!arguments.length) return order;
  order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
  return stack;
  };
  stack.offset = function(x) {
  if (!arguments.length) return offset;
  offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
  return stack;
  };
  stack.x = function(z) {
  if (!arguments.length) return x;
  x = z;
  return stack;
  };
  stack.y = function(z) {
  if (!arguments.length) return y;
  y = z;
  return stack;
  };
  stack.out = function(z) {
  if (!arguments.length) return out;
  out = z;
  return stack;
  };
  return stack;
  };
  var d3_layout_stackOrders = d3.map({
  "inside-out": function(data) {
  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) {
  return max[a] - max[b];
  }), top = 0, bottom = 0, tops = [], bottoms = [];
  for (i = 0; i < n; ++i) {
  j = index[i];
  if (top < bottom) {
  top += sums[j];
  tops.push(j);
  } else {
  bottom += sums[j];
  bottoms.push(j);
  }
  }
  return bottoms.reverse().concat(tops);
  },
  reverse: function(data) {
  return d3.range(data.length).reverse();
  },
  "default": d3_layout_stackOrderDefault
  });
  var d3_layout_stackOffsets = d3.map({
  silhouette: function(data) {
  var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
  for (j = 0; j < m; ++j) {
  for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
  if (o > max) max = o;
  sums.push(o);
  }
  for (j = 0; j < m; ++j) {
  y0[j] = (max - sums[j]) / 2;
  }
  return y0;
  },
  wiggle: function(data) {
  var n = data.length, x = data[0], m = x.length, max = 0, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
  y0[0] = o = o0 = 0;
  for (j = 1; j < m; ++j) {
  for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
  for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
  for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
  s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
  }
  s2 += s3 * data[i][j][1];
  }
  y0[j] = o -= s1 ? s2 / s1 * dx : 0;
  if (o < o0) o0 = o;
  }
  for (j = 0; j < m; ++j) y0[j] -= o0;
  return y0;
  },
  expand: function(data) {
  var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
  for (j = 0; j < m; ++j) {
  for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
  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;
  }
  for (j = 0; j < m; ++j) y0[j] = 0;
  return y0;
  },
  zero: d3_layout_stackOffsetZero
  });
  d3.layout.histogram = function() {
  function histogram(data, i) {
  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;
  while (++i < m) {
  bin = bins[i] = [];
  bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
  bin.y = 0;
  }
  if (m > 0) {
  i = -1;
  while (++i < n) {
  x = values[i];
  if (x >= range[0] && x <= range[1]) {
  bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
  bin.y += k;
  bin.push(data[i]);
  }
  }
  }
  return bins;
  }
  var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
  histogram.value = function(x) {
  if (!arguments.length) return valuer;
  valuer = x;
  return histogram;
  };
  histogram.range = function(x) {
  if (!arguments.length) return ranger;
  ranger = d3_functor(x);
  return histogram;
  };
  histogram.bins = function(x) {
  if (!arguments.length) return binner;
  binner = typeof x === "number" ? function(range) {
  return d3_layout_histogramBinFixed(range, x);
  } : d3_functor(x);
  return histogram;
  };
  histogram.frequency = function(x) {
  if (!arguments.length) return frequency;
  frequency = !!x;
  return histogram;
  };
  return histogram;
  };
  d3.layout.hierarchy = function() {
  function recurse(data, depth, nodes) {
  var childs = children.call(hierarchy, data, depth), node = d3_layout_hierarchyInline ? data : {
  data: data
  };
  node.depth = depth;
  nodes.push(node);
  if (childs && (n = childs.length)) {
  var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d;
  while (++i < n) {
  d = recurse(childs[i], j, nodes);
  d.parent = node;
  c.push(d);
  v += d.value;
  }
  if (sort) c.sort(sort);
  if (value) node.value = v;
  } else if (value) {
  node.value = +value.call(hierarchy, data, depth) || 0;
  }
  return node;
  }
  function revalue(node, depth) {
  var children = node.children, v = 0;
  if (children && (n = children.length)) {
  var i = -1, n, j = depth + 1;
  while (++i < n) v += revalue(children[i], j);
  } else if (value) {
  v = +value.call(hierarchy, d3_layout_hierarchyInline ? node : node.data, depth) || 0;
  }
  if (value) node.value = v;
  return v;
  }
  function hierarchy(d) {
  var nodes = [];
  recurse(d, 0, nodes);
  return nodes;
  }
  var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
  hierarchy.sort = function(x) {
  if (!arguments.length) return sort;
  sort = x;
  return hierarchy;
  };
  hierarchy.children = function(x) {
  if (!arguments.length) return children;
  children = x;
  return hierarchy;
  };
  hierarchy.value = function(x) {
  if (!arguments.length) return value;
  value = x;
  return hierarchy;
  };
  hierarchy.revalue = function(root) {
  revalue(root, 0);
  return root;
  };
  return hierarchy;
  };
  var d3_layout_hierarchyInline = false;
  d3.layout.pack = function() {
  function pack(d, i) {
  var nodes = hierarchy.call(this, d, i), root = nodes[0];
  root.x = 0;
  root.y = 0;
  d3_layout_treeVisitAfter(root, function(d) {
  d.r = Math.sqrt(d.value);
  });
  d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
  var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);
  if (padding > 0) {
  var dr = padding * k / 2;
  d3_layout_treeVisitAfter(root, function(d) {
  d.r += dr;
  });
  d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
  d3_layout_treeVisitAfter(root, function(d) {
  d.r -= dr;
  });
  k = Math.max(2 * root.r / w, 2 * root.r / h);
  }
  d3_layout_packTransform(root, w / 2, h / 2, 1 / k);
  return nodes;
  }
  var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];
  pack.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return pack;
  };
  pack.padding = function(_) {
  if (!arguments.length) return padding;
  padding = +_;
  return pack;
  };
  return d3_layout_hierarchyRebind(pack, hierarchy);
  };
  d3.layout.cluster = function() {
  function cluster(d, i) {
  var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0, kx, ky;
  d3_layout_treeVisitAfter(root, function(node) {
  var children = node.children;
  if (children && children.length) {
  node.x = d3_layout_clusterX(children);
  node.y = d3_layout_clusterY(children);
  } else {
  node.x = previousNode ? x += separation(node, previousNode) : 0;
  node.y = 0;
  previousNode = node;
  }
  });
  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;
  d3_layout_treeVisitAfter(root, function(node) {
  node.x = (node.x - x0) / (x1 - x0) * size[0];
  node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
  });
  return nodes;
  }
  var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
  cluster.separation = function(x) {
  if (!arguments.length) return separation;
  separation = x;
  return cluster;
  };
  cluster.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return cluster;
  };
  return d3_layout_hierarchyRebind(cluster, hierarchy);
  };
  d3.layout.tree = function() {
  function tree(d, i) {
  function firstWalk(node, previousSibling) {
  var children = node.children, layout = node._tree;
  if (children && (n = children.length)) {
  var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
  while (++i < n) {
  child = children[i];
  firstWalk(child, previousChild);
  ancestor = apportion(child, previousChild, ancestor);
  previousChild = child;
  }
  d3_layout_treeShift(node);
  var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
  if (previousSibling) {
  layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
  layout.mod = layout.prelim - midpoint;
  } else {
  layout.prelim = midpoint;
  }
  } else {
  if (previousSibling) {
  layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
  }
  }
  }
  function secondWalk(node, x) {
  node.x = node._tree.prelim + x;
  var children = node.children;
  if (children && (n = children.length)) {
  var i = -1, n;
  x += node._tree.mod;
  while (++i < n) {
  secondWalk(children[i], x);
  }
  }
  }
  function apportion(node, previousSibling, ancestor) {
  if (previousSibling) {
  var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
  while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
  vom = d3_layout_treeLeft(vom);
  vop = d3_layout_treeRight(vop);
  vop._tree.ancestor = node;
  shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
  if (shift > 0) {
  d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
  sip += shift;
  sop += shift;
  }
  sim += vim._tree.mod;
  sip += vip._tree.mod;
  som += vom._tree.mod;
  sop += vop._tree.mod;
  }
  if (vim && !d3_layout_treeRight(vop)) {
  vop._tree.thread = vim;
  vop._tree.mod += sim - sop;
  }
  if (vip && !d3_layout_treeLeft(vom)) {
  vom._tree.thread = vip;
  vom._tree.mod += sip - som;
  ancestor = node;
  }
  }
  return ancestor;
  }
  var nodes = hierarchy.call(this, d, i), root = nodes[0];
  d3_layout_treeVisitAfter(root, function(node, previousSibling) {
  node._tree = {
  ancestor: node,
  prelim: 0,
  mod: 0,
  change: 0,
  shift: 0,
  number: previousSibling ? previousSibling._tree.number + 1 : 0
  };
  });
  firstWalk(root);
  secondWalk(root, -root._tree.prelim);
  var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
  d3_layout_treeVisitAfter(root, function(node) {
  node.x = (node.x - x0) / (x1 - x0) * size[0];
  node.y = node.depth / y1 * size[1];
  delete node._tree;
  });
  return nodes;
  }
  var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
  tree.separation = function(x) {
  if (!arguments.length) return separation;
  separation = x;
  return tree;
  };
  tree.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return tree;
  };
  return d3_layout_hierarchyRebind(tree, hierarchy);
  };
  d3.layout.treemap = function() {
  function scale(children, k) {
  var i = -1, n = children.length, child, area;
  while (++i < n) {
  area = (child = children[i]).value * (k < 0 ? 0 : k);
  child.area = isNaN(area) || area <= 0 ? 0 : area;
  }
  }
  function squarify(node) {
  var children = node.children;
  if (children && children.length) {
  var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = Math.min(rect.dx, rect.dy), n;
  scale(remaining, rect.dx * rect.dy / node.value);
  row.area = 0;
  while ((n = remaining.length) > 0) {
  row.push(child = remaining[n - 1]);
  row.area += child.area;
  if ((score = worst(row, u)) <= best) {
  remaining.pop();
  best = score;
  } else {
  row.area -= row.pop().area;
  position(row, u, rect, false);
  u = Math.min(rect.dx, rect.dy);
  row.length = row.area = 0;
  best = Infinity;
  }
  }
  if (row.length) {
  position(row, u, rect, true);
  row.length = row.area = 0;
  }
  children.forEach(squarify);
  }
  }
  function stickify(node) {
  var children = node.children;
  if (children && children.length) {
  var rect = pad(node), remaining = children.slice(), child, row = [];
  scale(remaining, rect.dx * rect.dy / node.value);
  row.area = 0;
  while (child = remaining.pop()) {
  row.push(child);
  row.area += child.area;
  if (child.z != null) {
  position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
  row.length = row.area = 0;
  }
  }
  children.forEach(stickify);
  }
  }
  function worst(row, u) {
  var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
  while (++i < n) {
  if (!(r = row[i].area)) continue;
  if (r < rmin) rmin = r;
  if (r > rmax) rmax = r;
  }
  s *= s;
  u *= u;
  return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
  }
  function position(row, u, rect, flush) {
  var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
  if (u == rect.dx) {
  if (flush || v > rect.dy) v = rect.dy;
  while (++i < n) {
  o = row[i];
  o.x = x;
  o.y = y;
  o.dy = v;
  x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
  }
  o.z = true;
  o.dx += rect.x + rect.dx - x;
  rect.y += v;
  rect.dy -= v;
  } else {
  if (flush || v > rect.dx) v = rect.dx;
  while (++i < n) {
  o = row[i];
  o.x = x;
  o.y = y;
  o.dx = v;
  y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
  }
  o.z = false;
  o.dy += rect.y + rect.dy - y;
  rect.x += v;
  rect.dx -= v;
  }
  }
  function treemap(d) {
  var nodes = stickies || hierarchy(d), root = nodes[0];
  root.x = 0;
  root.y = 0;
  root.dx = size[0];
  root.dy = size[1];
  if (stickies) hierarchy.revalue(root);
  scale([ root ], root.dx * root.dy / root.value);
  (stickies ? stickify : squarify)(root);
  if (sticky) stickies = nodes;
  return nodes;
  }
  var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, ratio = .5 * (1 + Math.sqrt(5));
  treemap.size = function(x) {
  if (!arguments.length) return size;
  size = x;
  return treemap;
  };
  treemap.padding = function(x) {
  function padFunction(node) {
  var p = x.call(treemap, node, node.depth);
  return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
  }
  function padConstant(node) {
  return d3_layout_treemapPad(node, x);
  }
  if (!arguments.length) return padding;
  var type;
  pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], padConstant) : padConstant;
  return treemap;
  };
  treemap.round = function(x) {
  if (!arguments.length) return round != Number;
  round = x ? Math.round : Number;
  return treemap;
  };
  treemap.sticky = function(x) {
  if (!arguments.length) return sticky;
  sticky = x;
  stickies = null;
  return treemap;
  };
  treemap.ratio = function(x) {
  if (!arguments.length) return ratio;
  ratio = x;
  return treemap;
  };
  return d3_layout_hierarchyRebind(treemap, hierarchy);
  };
  d3.csv = d3_dsv(",", "text/csv");
  d3.tsv = d3_dsv(" ", "text/tab-separated-values");
  d3.geo = {};
  var d3_geo_radians = Math.PI / 180;
  d3.geo.azimuthal = function() {
  function azimuthal(coordinates) {
  var x1 = coordinates[0] * d3_geo_radians - x0, y1 = coordinates[1] * d3_geo_radians, cx1 = Math.cos(x1), sx1 = Math.sin(x1), cy1 = Math.cos(y1), sy1 = Math.sin(y1), cc = mode !== "orthographic" ? sy0 * sy1 + cy0 * cy1 * cx1 : null, c, k = mode === "stereographic" ? 1 / (1 + cc) : mode === "gnomonic" ? 1 / cc : mode === "equidistant" ? (c = Math.acos(cc), c ? c / Math.sin(c) : 0) : mode === "equalarea" ? Math.sqrt(2 / (1 + cc)) : 1, x = k * cy1 * sx1, y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
  return [ scale * x + translate[0], scale * y + translate[1] ];
  }
  var mode = "orthographic", origin, scale = 200, translate = [ 480, 250 ], x0, y0, cy0, sy0;
  azimuthal.invert = function(coordinates) {
  var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale, p = Math.sqrt(x * x + y * y), c = mode === "stereographic" ? 2 * Math.atan(p) : mode === "gnomonic" ? Math.atan(p) : mode === "equidistant" ? p : mode === "equalarea" ? 2 * Math.asin(.5 * p) : Math.asin(p), sc = Math.sin(c), cc = Math.cos(c);
  return [ (x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_geo_radians, Math.asin(cc * sy0 - (p ? y * sc * cy0 / p : 0)) / d3_geo_radians ];
  };
  azimuthal.mode = function(x) {
  if (!arguments.length) return mode;
  mode = x + "";
  return azimuthal;
  };
  azimuthal.origin = function(x) {
  if (!arguments.length) return origin;
  origin = x;
  x0 = origin[0] * d3_geo_radians;
  y0 = origin[1] * d3_geo_radians;
  cy0 = Math.cos(y0);
  sy0 = Math.sin(y0);
  return azimuthal;
  };
  azimuthal.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return azimuthal;
  };
  azimuthal.translate = function(x) {
  if (!arguments.length) return translate;
  translate = [ +x[0], +x[1] ];
  return azimuthal;
  };
  return azimuthal.origin([ 0, 0 ]);
  };
  d3.geo.albers = function() {
  function albers(coordinates) {
  var t = n * (d3_geo_radians * coordinates[0] - lng0), p = Math.sqrt(C - 2 * n * Math.sin(d3_geo_radians * coordinates[1])) / n;
  return [ scale * p * Math.sin(t) + translate[0], scale * (p * Math.cos(t) - p0) + translate[1] ];
  }
  function reload() {
  var phi1 = d3_geo_radians * parallels[0], phi2 = d3_geo_radians * parallels[1], lat0 = d3_geo_radians * origin[1], s = Math.sin(phi1), c = Math.cos(phi1);
  lng0 = d3_geo_radians * origin[0];
  n = .5 * (s + Math.sin(phi2));
  C = c * c + 2 * n * s;
  p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;
  return albers;
  }
  var origin = [ -98, 38 ], parallels = [ 29.5, 45.5 ], scale = 1e3, translate = [ 480, 250 ], lng0, n, C, p0;
  albers.invert = function(coordinates) {
  var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale, p0y = p0 + y, t = Math.atan2(x, p0y), p = Math.sqrt(x * x + p0y * p0y);
  return [ (lng0 + t / n) / d3_geo_radians, Math.asin((C - p * p * n * n) / (2 * n)) / d3_geo_radians ];
  };
  albers.origin = function(x) {
  if (!arguments.length) return origin;
  origin = [ +x[0], +x[1] ];
  return reload();
  };
  albers.parallels = function(x) {
  if (!arguments.length) return parallels;
  parallels = [ +x[0], +x[1] ];
  return reload();
  };
  albers.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return albers;
  };
  albers.translate = function(x) {
  if (!arguments.length) return translate;
  translate = [ +x[0], +x[1] ];
  return albers;
  };
  return reload();
  };
  d3.geo.albersUsa = function() {
  function albersUsa(coordinates) {
  var lon = coordinates[0], lat = coordinates[1];
  return (lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48)(coordinates);
  }
  var lower48 = d3.geo.albers();
  var alaska = d3.geo.albers().origin([ -160, 60 ]).parallels([ 55, 65 ]);
  var hawaii = d3.geo.albers().origin([ -160, 20 ]).parallels([ 8, 18 ]);
  var puertoRico = d3.geo.albers().origin([ -60, 10 ]).parallels([ 8, 18 ]);
  albersUsa.scale = function(x) {
  if (!arguments.length) return lower48.scale();
  lower48.scale(x);
  alaska.scale(x * .6);
  hawaii.scale(x);
  puertoRico.scale(x * 1.5);
  return albersUsa.translate(lower48.translate());
  };
  albersUsa.translate = function(x) {
  if (!arguments.length) return lower48.translate();
  var dz = lower48.scale() / 1e3, dx = x[0], dy = x[1];
  lower48.translate(x);
  alaska.translate([ dx - 400 * dz, dy + 170 * dz ]);
  hawaii.translate([ dx - 190 * dz, dy + 200 * dz ]);
  puertoRico.translate([ dx + 580 * dz, dy + 430 * dz ]);
  return albersUsa;
  };
  return albersUsa.scale(lower48.scale());
  };
  d3.geo.bonne = function() {
  function bonne(coordinates) {
  var x = coordinates[0] * d3_geo_radians - x0, y = coordinates[1] * d3_geo_radians - y0;
  if (y1) {
  var p = c1 + y1 - y, E = x * Math.cos(y) / p;
  x = p * Math.sin(E);
  y = p * Math.cos(E) - c1;
  } else {
  x *= Math.cos(y);
  y *= -1;
  }
  return [ scale * x + translate[0], scale * y + translate[1] ];
  }
  var scale = 200, translate = [ 480, 250 ], x0, y0, y1, c1;
  bonne.invert = function(coordinates) {
  var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;
  if (y1) {
  var c = c1 + y, p = Math.sqrt(x * x + c * c);
  y = c1 + y1 - p;
  x = x0 + p * Math.atan2(x, c) / Math.cos(y);
  } else {
  y *= -1;
  x /= Math.cos(y);
  }
  return [ x / d3_geo_radians, y / d3_geo_radians ];
  };
  bonne.parallel = function(x) {
  if (!arguments.length) return y1 / d3_geo_radians;
  c1 = 1 / Math.tan(y1 = x * d3_geo_radians);
  return bonne;
  };
  bonne.origin = function(x) {
  if (!arguments.length) return [ x0 / d3_geo_radians, y0 / d3_geo_radians ];
  x0 = x[0] * d3_geo_radians;
  y0 = x[1] * d3_geo_radians;
  return bonne;
  };
  bonne.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return bonne;
  };
  bonne.translate = function(x) {
  if (!arguments.length) return translate;
  translate = [ +x[0], +x[1] ];
  return bonne;
  };
  return bonne.origin([ 0, 0 ]).parallel(45);
  };
  d3.geo.equirectangular = function() {
  function equirectangular(coordinates) {
  var x = coordinates[0] / 360, y = -coordinates[1] / 360;
  return [ scale * x + translate[0], scale * y + translate[1] ];
  }
  var scale = 500, translate = [ 480, 250 ];
  equirectangular.invert = function(coordinates) {
  var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;
  return [ 360 * x, -360 * y ];
  };
  equirectangular.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return equirectangular;
  };
  equirectangular.translate = function(x) {
  if (!arguments.length) return translate;
  translate = [ +x[0], +x[1] ];
  return equirectangular;
  };
  return equirectangular;
  };
  d3.geo.mercator = function() {
  function mercator(coordinates) {
  var x = coordinates[0] / 360, y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_geo_radians / 2)) / d3_geo_radians) / 360;
  return [ scale * x + translate[0], scale * Math.max(-.5, Math.min(.5, y)) + translate[1] ];
  }
  var scale = 500, translate = [ 480, 250 ];
  mercator.invert = function(coordinates) {
  var x = (coordinates[0] - translate[0]) / scale, y = (coordinates[1] - translate[1]) / scale;
  return [ 360 * x, 2 * Math.atan(Math.exp(-360 * y * d3_geo_radians)) / d3_geo_radians - 90 ];
  };
  mercator.scale = function(x) {
  if (!arguments.length) return scale;
  scale = +x;
  return mercator;
  };
  mercator.translate = function(x) {
  if (!arguments.length) return translate;
  translate = [ +x[0], +x[1] ];
  return mercator;
  };
  return mercator;
  };
  d3.geo.path = function() {
  function path(d, i) {
  if (typeof pointRadius === "function") pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
  pathType(d);
  var result = buffer.length ? buffer.join("") : null;
  buffer = [];
  return result;
  }
  function project(coordinates) {
  return projection(coordinates).join(",");
  }
  function polygonArea(coordinates) {
  var sum = area(coordinates[0]), i = 0, n = coordinates.length;
  while (++i < n) sum -= area(coordinates[i]);
  return sum;
  }
  function polygonCentroid(coordinates) {
  var polygon = d3.geom.polygon(coordinates[0].map(projection)), area = polygon.area(), centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1), x = centroid[0], y = centroid[1], z = area, i = 0, n = coordinates.length;
  while (++i < n) {
  polygon = d3.geom.polygon(coordinates[i].map(projection));
  area = polygon.area();
  centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);
  x -= centroid[0];
  y -= centroid[1];
  z -= area;
  }
  return [ x, y, 6 * z ];
  }
  function area(coordinates) {
  return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
  }
  var pointRadius = 4.5, pointCircle = d3_path_circle(pointRadius), projection = d3.geo.albersUsa(), buffer = [];
  var pathType = d3_geo_type({
  FeatureCollection: function(o) {
  var features = o.features, i = -1, n = features.length;
  while (++i < n) buffer.push(pathType(features[i].geometry));
  },
  Feature: function(o) {
  pathType(o.geometry);
  },
  Point: function(o) {
  buffer.push("M", project(o.coordinates), pointCircle);
  },
  MultiPoint: function(o) {
  var coordinates = o.coordinates, i = -1, n = coordinates.length;
  while (++i < n) buffer.push("M", project(coordinates[i]), pointCircle);
  },
  LineString: function(o) {
  var coordinates = o.coordinates, i = -1, n = coordinates.length;
  buffer.push("M");
  while (++i < n) buffer.push(project(coordinates[i]), "L");
  buffer.pop();
  },
  MultiLineString: function(o) {
  var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m;
  while (++i < n) {
  subcoordinates = coordinates[i];
  j = -1;
  m = subcoordinates.length;
  buffer.push("M");
  while (++j < m) buffer.push(project(subcoordinates[j]), "L");
  buffer.pop();
  }
  },
  Polygon: function(o) {
  var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m;
  while (++i < n) {
  subcoordinates = coordinates[i];
  j = -1;
  if ((m = subcoordinates.length - 1) > 0) {
  buffer.push("M");
  while (++j < m) buffer.push(project(subcoordinates[j]), "L");
  buffer[buffer.length - 1] = "Z";
  }
  }
  },
  MultiPolygon: function(o) {
  var coordinates = o.coordinates, i = -1, n = coordinates.length, subcoordinates, j, m, subsubcoordinates, k, p;
  while (++i < n) {
  subcoordinates = coordinates[i];
  j = -1;
  m = subcoordinates.length;
  while (++j < m) {
  subsubcoordinates = subcoordinates[j];
  k = -1;
  if ((p = subsubcoordinates.length - 1) > 0) {
  buffer.push("M");
  while (++k < p) buffer.push(project(subsubcoordinates[k]), "L");
  buffer[buffer.length - 1] = "Z";
  }
  }
  }
  },
  GeometryCollection: function(o) {
  var geometries = o.geometries, i = -1, n = geometries.length;
  while (++i < n) buffer.push(pathType(geometries[i]));
  }
  });
  var areaType = path.area = d3_geo_type({
  FeatureCollection: function(o) {
  var area = 0, features = o.features, i = -1, n = features.length;
  while (++i < n) area += areaType(features[i]);
  return area;
  },
  Feature: function(o) {
  return areaType(o.geometry);
  },
  Polygon: function(o) {
  return polygonArea(o.coordinates);
  },
  MultiPolygon: function(o) {
  var sum = 0, coordinates = o.coordinates, i = -1, n = coordinates.length;
  while (++i < n) sum += polygonArea(coordinates[i]);
  return sum;
  },
  GeometryCollection: function(o) {
  var sum = 0, geometries = o.geometries, i = -1, n = geometries.length;
  while (++i < n) sum += areaType(geometries[i]);
  return sum;
  }
  }, 0);
  var centroidType = path.centroid = d3_geo_type({
  Feature: function(o) {
  return centroidType(o.geometry);
  },
  Polygon: function(o) {
  var centroid = polygonCentroid(o.coordinates);
  return [ centroid[0] / centroid[2], centroid[1] / centroid[2] ];
  },
  MultiPolygon: function(o) {
  var area = 0, coordinates = o.coordinates, centroid, x = 0, y = 0, z = 0, i = -1, n = coordinates.length;
  while (++i < n) {
  centroid = polygonCentroid(coordinates[i]);
  x += centroid[0];
  y += centroid[1];
  z += centroid[2];
  }
  return [ x / z, y / z ];
  }
  });
  path.projection = function(x) {
  projection = x;
  return path;
  };
  path.pointRadius = function(x) {
  if (typeof x === "function") pointRadius = x; else {
  pointRadius = +x;
  pointCircle = d3_path_circle(pointRadius);
  }
  return path;
  };
  return path;
  };
  d3.geo.bounds = function(feature) {
  var left = Infinity, bottom = Infinity, right = -Infinity, top = -Infinity;
  d3_geo_bounds(feature, function(x, y) {
  if (x < left) left = x;
  if (x > right) right = x;
  if (y < bottom) bottom = y;
  if (y > top) top = y;
  });
  return [ [ left, bottom ], [ right, top ] ];
  };
  var d3_geo_boundsTypes = {
  Feature: d3_geo_boundsFeature,
  FeatureCollection: d3_geo_boundsFeatureCollection,
  GeometryCollection: d3_geo_boundsGeometryCollection,
  LineString: d3_geo_boundsLineString,
  MultiLineString: d3_geo_boundsMultiLineString,
  MultiPoint: d3_geo_boundsLineString,
  MultiPolygon: d3_geo_boundsMultiPolygon,
  Point: d3_geo_boundsPoint,
  Polygon: d3_geo_boundsPolygon
  };
  d3.geo.circle = function() {
  function circle() {}
  function visible(point) {
  return arc.distance(point) < radians;
  }
  function clip(coordinates) {
  var i = -1, n = coordinates.length, clipped = [], p0, p1, p2, d0, d1;
  while (++i < n) {
  d1 = arc.distance(p2 = coordinates[i]);
  if (d1 < radians) {
  if (p1) clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));
  clipped.push(p2);
  p0 = p1 = null;
  } else {
  p1 = p2;
  if (!p0 && clipped.length) {
  clipped.push(d3_geo_greatArcInterpolate(clipped[clipped.length - 1], p1)((radians - d0) / (d1 - d0)));
  p0 = p1;
  }
  }
  d0 = d1;
  }
  p0 = coordinates[0];
  p1 = clipped[0];
  if (p1 && p2[0] === p0[0] && p2[1] === p0[1] && !(p2[0] === p1[0] && p2[1] === p1[1])) {
  clipped.push(p1);
  }
  return resample(clipped);
  }
  function resample(coordinates) {
  var i = 0, n = coordinates.length, j, m, resampled = n ? [ coordinates[0] ] : coordinates, resamples, origin = arc.source();
  while (++i < n) {
  resamples = arc.source(coordinates[i - 1])(coordinates[i]).coordinates;
  for (j = 0, m = resamples.length; ++j < m; ) resampled.push(resamples[j]);
  }
  arc.source(origin);
  return resampled;
  }
  var origin = [ 0, 0 ], degrees = 90 - .01, radians = degrees * d3_geo_radians, arc = d3.geo.greatArc().source(origin).target(d3_identity);
  circle.clip = function(d) {
  if (typeof origin === "function") arc.source(origin.apply(this, arguments));
  return clipType(d) || null;
  };
  var clipType = d3_geo_type({
  FeatureCollection: function(o) {
  var features = o.features.map(clipType).filter(d3_identity);
  return features && (o = Object.create(o), o.features = features, o);
  },
  Feature: function(o) {
  var geometry = clipType(o.geometry);
  return geometry && (o = Object.create(o), o.geometry = geometry, o);
  },
  Point: function(o) {
  return visible(o.coordinates) && o;
  },
  MultiPoint: function(o) {
  var coordinates = o.coordinates.filter(visible);
  return coordinates.length && {
  type: o.type,
  coordinates: coordinates
  };
  },
  LineString: function(o) {
  var coordinates = clip(o.coordinates);
  return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
  },
  MultiLineString: function(o) {
  var coordinates = o.coordinates.map(clip).filter(function(d) {
  return d.length;
  });
  return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
  },
  Polygon: function(o) {
  var coordinates = o.coordinates.map(clip);
  return coordinates[0].length && (o = Object.create(o), o.coordinates = coordinates, o);
  },
  MultiPolygon: function(o) {
  var coordinates = o.coordinates.map(function(d) {
  return d.map(clip);
  }).filter(function(d) {
  return d[0].length;
  });
  return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
  },
  GeometryCollection: function(o) {
  var geometries = o.geometries.map(clipType).filter(d3_identity);
  return geometries.length && (o = Object.create(o), o.geometries = geometries, o);
  }
  });
  circle.origin = function(x) {
  if (!arguments.length) return origin;
  origin = x;
  if (typeof origin !== "function") arc.source(origin);
  return circle;
  };
  circle.angle = function(x) {
  if (!arguments.length) return degrees;
  radians = (degrees = +x) * d3_geo_radians;
  return circle;
  };
  return d3.rebind(circle, arc, "precision");
  };
  d3.geo.greatArc = function() {
  function greatArc() {
  var d = greatArc.distance.apply(this, arguments), t = 0, dt = precision / d, coordinates = [ p0 ];
  while ((t += dt) < 1) coordinates.push(interpolate(t));
  coordinates.push(p1);
  return {
  type: "LineString",
  coordinates: coordinates
  };
  }
  var source = d3_geo_greatArcSource, p0, target = d3_geo_greatArcTarget, p1, precision = 6 * d3_geo_radians, interpolate = d3_geo_greatArcInterpolator();
  greatArc.distance = function() {
  if (typeof source === "function") interpolate.source(p0 = source.apply(this, arguments));
  if (typeof target === "function") interpolate.target(p1 = target.apply(this, arguments));
  return interpolate.distance();
  };
  greatArc.source = function(_) {
  if (!arguments.length) return source;
  source = _;
  if (typeof source !== "function") interpolate.source(p0 = source);
  return greatArc;
  };
  greatArc.target = function(_) {
  if (!arguments.length) return target;
  target = _;
  if (typeof target !== "function") interpolate.target(p1 = target);
  return greatArc;
  };
  greatArc.precision = function(_) {
  if (!arguments.length) return precision / d3_geo_radians;
  precision = _ * d3_geo_radians;
  return greatArc;
  };
  return greatArc;
  };
  d3.geo.greatCircle = d3.geo.circle;
  d3.geom = {};
  d3.geom.contour = function(grid, start) {
  var s = start || d3_geom_contourStart(grid), c = [], x = s[0], y = s[1], dx = 0, dy = 0, pdx = NaN, pdy = NaN, i = 0;
  do {
  i = 0;
  if (grid(x - 1, y - 1)) i += 1;
  if (grid(x, y - 1)) i += 2;
  if (grid(x - 1, y)) i += 4;
  if (grid(x, y)) i += 8;
  if (i === 6) {
  dx = pdy === -1 ? -1 : 1;
  dy = 0;
  } else if (i === 9) {
  dx = 0;
  dy = pdx === 1 ? -1 : 1;
  } else {
  dx = d3_geom_contourDx[i];
  dy = d3_geom_contourDy[i];
  }
  if (dx != pdx && dy != pdy) {
  c.push([ x, y ]);
  pdx = dx;
  pdy = dy;
  }
  x += dx;
  y += dy;
  } while (s[0] != x || s[1] != y);
  return c;
  };
  var d3_geom_contourDx = [ 1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 0, 0, -1, 0, -1, NaN ], d3_geom_contourDy = [ 0, -1, 0, 0, 0, -1, 0, 0, 1, -1, 1, 1, 0, -1, 0, NaN ];
  d3.geom.hull = function(vertices) {
  if (vertices.length < 3) return [];
  var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;
  for (i = 1; i < len; ++i) {
  if (vertices[i][1] < vertices[h][1]) {
  h = i;
  } else if (vertices[i][1] == vertices[h][1]) {
  h = vertices[i][0] < vertices[h][0] ? i : h;
  }
  }
  for (i = 0; i < len; ++i) {
  if (i === h) continue;
  y1 = vertices[i][1] - vertices[h][1];
  x1 = vertices[i][0] - vertices[h][0];
  points.push({
  angle: Math.atan2(y1, x1),
  index: i
  });
  }
  points.sort(function(a, b) {
  return a.angle - b.angle;
  });
  a = points[0].angle;
  v = points[0].index;
  u = 0;
  for (i = 1; i < plen; ++i) {
  j = points[i].index;
  if (a == points[i].angle) {
  x1 = vertices[v][0] - vertices[h][0];
  y1 = vertices[v][1] - vertices[h][1];
  x2 = vertices[j][0] - vertices[h][0];
  y2 = vertices[j][1] - vertices[h][1];
  if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {
  points[i].index = -1;
  } else {
  points[u].index = -1;
  a = points[i].angle;
  u = i;
  v = j;
  }
  } else {
  a = points[i].angle;
  u = i;
  v = j;
  }
  }
  stack.push(h);
  for (i = 0, j = 0; i < 2; ++j) {
  if (points[j].index !== -1) {
  stack.push(points[j].index);
  i++;
  }
  }
  sp = stack.length;
  for (; j < plen; ++j) {
  if (points[j].index === -1) continue;
  while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {
  --sp;
  }
  stack[sp++] = points[j].index;
  }
  var poly = [];
  for (i = 0; i < sp; ++i) {
  poly.push(vertices[stack[i]]);
  }
  return poly;
  };
  d3.geom.polygon = function(coordinates) {
  coordinates.area = function() {
  var i = 0, n = coordinates.length, a = coordinates[n - 1][0] * coordinates[0][1], b = coordinates[n - 1][1] * coordinates[0][0];
  while (++i < n) {
  a += coordinates[i - 1][0] * coordinates[i][1];
  b += coordinates[i - 1][1] * coordinates[i][0];
  }
  return (b - a) * .5;
  };
  coordinates.centroid = function(k) {
  var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;
  if (!arguments.length) k = -1 / (6 * coordinates.area());
  while (++i < n) {
  a = b;
  b = coordinates[i];
  c = a[0] * b[1] - b[0] * a[1];
  x += (a[0] + b[0]) * c;
  y += (a[1] + b[1]) * c;
  }
  return [ x * k, y * k ];
  };
  coordinates.clip = function(subject) {
  var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;
  while (++i < n) {
  input = subject.slice();
  subject.length = 0;
  b = coordinates[i];
  c = input[(m = input.length) - 1];
  j = -1;
  while (++j < m) {
  d = input[j];
  if (d3_geom_polygonInside(d, a, b)) {
  if (!d3_geom_polygonInside(c, a, b)) {
  subject.push(d3_geom_polygonIntersect(c, d, a, b));
  }
  subject.push(d);
  } else if (d3_geom_polygonInside(c, a, b)) {
  subject.push(d3_geom_polygonIntersect(c, d, a, b));
  }
  c = d;
  }
  a = b;
  }
  return subject;
  };
  return coordinates;
  };
  d3.geom.voronoi = function(vertices) {
  var polygons = vertices.map(function() {
  return [];
  });
  d3_voronoi_tessellate(vertices, function(e) {
  var s1, s2, x1, x2, y1, y2;
  if (e.a === 1 && e.b >= 0) {
  s1 = e.ep.r;
  s2 = e.ep.l;
  } else {
  s1 = e.ep.l;
  s2 = e.ep.r;
  }
  if (e.a === 1) {
  y1 = s1 ? s1.y : -1e6;
  x1 = e.c - e.b * y1;
  y2 = s2 ? s2.y : 1e6;
  x2 = e.c - e.b * y2;
  } else {
  x1 = s1 ? s1.x : -1e6;
  y1 = e.c - e.a * x1;
  x2 = s2 ? s2.x : 1e6;
  y2 = e.c - e.a * x2;
  }
  var v1 = [ x1, y1 ], v2 = [ x2, y2 ];
  polygons[e.region.l.index].push(v1, v2);
  polygons[e.region.r.index].push(v1, v2);
  });
  return polygons.map(function(polygon, i) {
  var cx = vertices[i][0], cy = vertices[i][1];
  polygon.forEach(function(v) {
  v.angle = Math.atan2(v[0] - cx, v[1] - cy);
  });
  return polygon.sort(function(a, b) {
  return a.angle - b.angle;
  }).filter(function(d, i) {
  return !i || d.angle - polygon[i - 1].angle > 1e-10;
  });
  });
  };
  var d3_voronoi_opposite = {
  l: "r",
  r: "l"
  };
  d3.geom.delaunay = function(vertices) {
  var edges = vertices.map(function() {
  return [];
  }), triangles = [];
  d3_voronoi_tessellate(vertices, function(e) {
  edges[e.region.l.index].push(vertices[e.region.r.index]);
  });
  edges.forEach(function(edge, i) {
  var v = vertices[i], cx = v[0], cy = v[1];
  edge.forEach(function(v) {
  v.angle = Math.atan2(v[0] - cx, v[1] - cy);
  });
  edge.sort(function(a, b) {
  return a.angle - b.angle;
  });
  for (var j = 0, m = edge.length - 1; j < m; j++) {
  triangles.push([ v, edge[j], edge[j + 1] ]);
  }
  });
  return triangles;
  };
  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
  function insert(n, p, x1, y1, x2, y2) {
  if (isNaN(p.x) || isNaN(p.y)) return;
  if (n.leaf) {
  var v = n.point;
  if (v) {
  if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) {
  insertChild(n, p, x1, y1, x2, y2);
  } else {
  n.point = null;
  insertChild(n, v, x1, y1, x2, y2);
  insertChild(n, p, x1, y1, x2, y2);
  }
  } else {
  n.point = p;
  }
  } else {
  insertChild(n, p, x1, y1, x2, y2);
  }
  }
  function insertChild(n, p, x1, y1, x2, y2) {
  var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right;
  n.leaf = false;
  n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
  if (right) x1 = sx; else x2 = sx;
  if (bottom) y1 = sy; else y2 = sy;
  insert(n, p, x1, y1, x2, y2);
  }
  var p, i = -1, n = points.length;
  if (n && isNaN(points[0].x)) points = points.map(d3_geom_quadtreePoint);
  if (arguments.length < 5) {
  if (arguments.length === 3) {
  y2 = x2 = y1;
  y1 = x1;
  } else {
  x1 = y1 = Infinity;
  x2 = y2 = -Infinity;
  while (++i < n) {
  p = points[i];
  if (p.x < x1) x1 = p.x;
  if (p.y < y1) y1 = p.y;
  if (p.x > x2) x2 = p.x;
  if (p.y > y2) y2 = p.y;
  }
  var dx = x2 - x1, dy = y2 - y1;
  if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy;
  }
  }
  var root = d3_geom_quadtreeNode();
  root.add = function(p) {
  insert(root, p, x1, y1, x2, y2);
  };
  root.visit = function(f) {
  d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2);
  };
  points.forEach(root.add);
  return root;
  };
  d3.time = {};
  var d3_time = Date, d3_time_daySymbols = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
  d3_time_utc.prototype = {
  getDate: function() {
  return this._.getUTCDate();
  },
  getDay: function() {
  return this._.getUTCDay();
  },
  getFullYear: function() {
  return this._.getUTCFullYear();
  },
  getHours: function() {
  return this._.getUTCHours();
  },
  getMilliseconds: function() {
  return this._.getUTCMilliseconds();
  },
  getMinutes: function() {
  return this._.getUTCMinutes();
  },
  getMonth: function() {
  return this._.getUTCMonth();
  },
  getSeconds: function() {
  return this._.getUTCSeconds();
  },
  getTime: function() {
  return this._.getTime();
  },
  getTimezoneOffset: function() {
  return 0;
  },
  valueOf: function() {
  return this._.valueOf();
  },
  setDate: function() {
  d3_time_prototype.setUTCDate.apply(this._, arguments);
  },
  setDay: function() {
  d3_time_prototype.setUTCDay.apply(this._, arguments);
  },
  setFullYear: function() {
  d3_time_prototype.setUTCFullYear.apply(this._, arguments);
  },
  setHours: function() {
  d3_time_prototype.setUTCHours.apply(this._, arguments);
  },
  setMilliseconds: function() {
  d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
  },
  setMinutes: function() {
  d3_time_prototype.setUTCMinutes.apply(this._, arguments);
  },
  setMonth: function() {
  d3_time_prototype.setUTCMonth.apply(this._, arguments);
  },
  setSeconds: function() {
  d3_time_prototype.setUTCSeconds.apply(this._, arguments);
  },
  setTime: function() {
  d3_time_prototype.setTime.apply(this._, arguments);
  }
  };
  var d3_time_prototype = Date.prototype;
  var d3_time_formatDateTime = "%a %b %e %H:%M:%S %Y", d3_time_formatDate = "%m/%d/%y", d3_time_formatTime = "%H:%M:%S";
  var d3_time_days = d3_time_daySymbols, d3_time_dayAbbreviations = d3_time_days.map(d3_time_formatAbbreviate), d3_time_months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], d3_time_monthAbbreviations = d3_time_months.map(d3_time_formatAbbreviate);
  d3.time.format = function(template) {
  function format(date) {
  var string = [], i = -1, j = 0, c, f;
  while (++i < n) {
  if (template.charCodeAt(i) == 37) {
  string.push(template.substring(j, i), (f = d3_time_formats[c = template.charAt(++i)]) ? f(date) : c);
  j = i + 1;
  }
  }
  string.push(template.substring(j, i));
  return string.join("");
  }
  var n = template.length;
  format.parse = function(string) {
  var d = {
  y: 1900,
  m: 0,
  d: 1,
  H: 0,
  M: 0,
  S: 0,
  L: 0
  }, i = d3_time_parse(d, template, string, 0);
  if (i != string.length) return null;
  if ("p" in d) d.H = d.H % 12 + d.p * 12;
  var date = new d3_time;
  date.setFullYear(d.y, d.m, d.d);
  date.setHours(d.H, d.M, d.S, d.L);
  return date;
  };
  format.toString = function() {
  return template;
  };
  return format;
  };
  var d3_time_zfill2 = d3.format("02d"), d3_time_zfill3 = d3.format("03d"), d3_time_zfill4 = d3.format("04d"), d3_time_sfill2 = d3.format("2d");
  var d3_time_dayRe = d3_time_formatRe(d3_time_days), d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations), d3_time_monthRe = d3_time_formatRe(d3_time_months), d3_time_monthLookup = d3_time_formatLookup(d3_time_months), d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations), d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations);
  var d3_time_formats = {
  a: function(d) {
  return d3_time_dayAbbreviations[d.getDay()];
  },
  A: function(d) {
  return d3_time_days[d.getDay()];
  },
  b: function(d) {
  return d3_time_monthAbbreviations[d.getMonth()];
  },
  B: function(d) {
  return d3_time_months[d.getMonth()];
  },
  c: d3.time.format(d3_time_formatDateTime),
  d: function(d) {
  return d3_time_zfill2(d.getDate());
  },
  e: function(d) {
  return d3_time_sfill2(d.getDate());
  },
  H: function(d) {
  return d3_time_zfill2(d.getHours());
  },
  I: function(d) {
  return d3_time_zfill2(d.getHours() % 12 || 12);
  },
  j: function(d) {
  return d3_time_zfill3(1 + d3.time.dayOfYear(d));
  },
  L: function(d) {
  return d3_time_zfill3(d.getMilliseconds());
  },
  m: function(d) {
  return d3_time_zfill2(d.getMonth() + 1);
  },
  M: function(d) {
  return d3_time_zfill2(d.getMinutes());
  },
  p: function(d) {
  return d.getHours() >= 12 ? "PM" : "AM";
  },
  S: function(d) {
  return d3_time_zfill2(d.getSeconds());
  },
  U: function(d) {
  return d3_time_zfill2(d3.time.sundayOfYear(d));
  },
  w: function(d) {
  return d.getDay();
  },
  W: function(d) {
  return d3_time_zfill2(d3.time.mondayOfYear(d));
  },
  x: d3.time.format(d3_time_formatDate),
  X: d3.time.format(d3_time_formatTime),
  y: function(d) {
  return d3_time_zfill2(d.getFullYear() % 100);
  },
  Y: function(d) {
  return d3_time_zfill4(d.getFullYear() % 1e4);
  },
  Z: d3_time_zone,
  "%": function(d) {
  return "%";
  }
  };
  var d3_time_parsers = {
  a: d3_time_parseWeekdayAbbrev,
  A: d3_time_parseWeekday,
  b: d3_time_parseMonthAbbrev,
  B: d3_time_parseMonth,
  c: d3_time_parseLocaleFull,
  d: d3_time_parseDay,
  e: d3_time_parseDay,
  H: d3_time_parseHour24,
  I: d3_time_parseHour24,
  L: d3_time_parseMilliseconds,
  m: d3_time_parseMonthNumber,
  M: d3_time_parseMinutes,
  p: d3_time_parseAmPm,
  S: d3_time_parseSeconds,
  x: d3_time_parseLocaleDate,
  X: d3_time_parseLocaleTime,
  y: d3_time_parseYear,
  Y: d3_time_parseFullYear
  };
  var d3_time_numberRe = /^\s*\d+/;
  var d3_time_amPmLookup = d3.map({
  am: 0,
  pm: 1
  });
  d3.time.format.utc = function(template) {
  function format(date) {
  try {
  d3_time = d3_time_utc;
  var utc = new d3_time;
  utc._ = date;
  return local(utc);
  } finally {
  d3_time = Date;
  }
  }
  var local = d3.time.format(template);
  format.parse = function(string) {
  try {
  d3_time = d3_time_utc;
  var date = local.parse(string);
  return date && date._;
  } finally {
  d3_time = Date;
  }
  };
  format.toString = local.toString;
  return format;
  };
  var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
  d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
  d3_time_formatIsoNative.parse = function(string) {
  var date = new Date(string);
  return isNaN(date) ? null : date;
  };
  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
  d3.time.second = d3_time_interval(function(date) {
  return new d3_time(Math.floor(date / 1e3) * 1e3);
  }, function(date, offset) {
  date.setTime(date.getTime() + Math.floor(offset) * 1e3);
  }, function(date) {
  return date.getSeconds();
  });
  d3.time.seconds = d3.time.second.range;
  d3.time.seconds.utc = d3.time.second.utc.range;
  d3.time.minute = d3_time_interval(function(date) {
  return new d3_time(Math.floor(date / 6e4) * 6e4);
  }, function(date, offset) {
  date.setTime(date.getTime() + Math.floor(offset) * 6e4);
  }, function(date) {
  return date.getMinutes();
  });
  d3.time.minutes = d3.time.minute.range;
  d3.time.minutes.utc = d3.time.minute.utc.range;
  d3.time.hour = d3_time_interval(function(date) {
  var timezone = date.getTimezoneOffset() / 60;
  return new d3_time((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
  }, function(date, offset) {
  date.setTime(date.getTime() + Math.floor(offset) * 36e5);
  }, function(date) {
  return date.getHours();
  });
  d3.time.hours = d3.time.hour.range;
  d3.time.hours.utc = d3.time.hour.utc.range;
  d3.time.day = d3_time_interval(function(date) {
  var day = new d3_time(1970, 0);
  day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
  return day;
  }, function(date, offset) {
  date.setDate(date.getDate() + offset);
  }, function(date) {
  return date.getDate() - 1;
  });
  d3.time.days = d3.time.day.range;
  d3.time.days.utc = d3.time.day.utc.range;
  d3.time.dayOfYear = function(date) {
  var year = d3.time.year(date);
  return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
  };
  d3_time_daySymbols.forEach(function(day, i) {
  day = day.toLowerCase();
  i = 7 - i;
  var interval = d3.time[day] = d3_time_interval(function(date) {
  (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
  return date;
  }, function(date, offset) {
  date.setDate(date.getDate() + Math.floor(offset) * 7);
  }, function(date) {
  var day = d3.time.year(date).getDay();
  return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
  });
  d3.time[day + "s"] = interval.range;
  d3.time[day + "s"].utc = interval.utc.range;
  d3.time[day + "OfYear"] = function(date) {
  var day = d3.time.year(date).getDay();
  return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7);
  };
  });
  d3.time.week = d3.time.sunday;
  d3.time.weeks = d3.time.sunday.range;
  d3.time.weeks.utc = d3.time.sunday.utc.range;
  d3.time.weekOfYear = d3.time.sundayOfYear;
  d3.time.month = d3_time_interval(function(date) {
  date = d3.time.day(date);
  date.setDate(1);
  return date;
  }, function(date, offset) {
  date.setMonth(date.getMonth() + offset);
  }, function(date) {
  return date.getMonth();
  });
  d3.time.months = d3.time.month.range;
  d3.time.months.utc = d3.time.month.utc.range;
  d3.time.year = d3_time_interval(function(date) {
  date = d3.time.day(date);
  date.setMonth(0, 1);
  return date;
  }, function(date, offset) {
  date.setFullYear(date.getFullYear() + offset);
  }, function(date) {
  return date.getFullYear();
  });
  d3.time.years = d3.time.year.range;
  d3.time.years.utc = d3.time.year.utc.range;
  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
  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 ] ];
  var d3_time_scaleLocalFormats = [ [ d3.time.format("%Y"), function(d) {
  return true;
  } ], [ d3.time.format("%B"), function(d) {
  return d.getMonth();
  } ], [ d3.time.format("%b %d"), function(d) {
  return d.getDate() != 1;
  } ], [ d3.time.format("%a %d"), function(d) {
  return d.getDay() && d.getDate() != 1;
  } ], [ d3.time.format("%I %p"), function(d) {
  return d.getHours();
  } ], [ d3.time.format("%I:%M"), function(d) {
  return d.getMinutes();
  } ], [ d3.time.format(":%S"), function(d) {
  return d.getSeconds();
  } ], [ d3.time.format(".%L"), function(d) {
  return d.getMilliseconds();
  } ] ];
  var d3_time_scaleLinear = d3.scale.linear(), d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats);
  d3_time_scaleLocalMethods.year = function(extent, m) {
  return d3_time_scaleLinear.domain(extent.map(d3_time_scaleGetYear)).ticks(m).map(d3_time_scaleSetYear);
  };
  d3.time.scale = function() {
  return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
  };
  var d3_time_scaleUTCMethods = d3_time_scaleLocalMethods.map(function(m) {
  return [ m[0].utc, m[1] ];
  });
  var d3_time_scaleUTCFormats = [ [ d3.time.format.utc("%Y"), function(d) {
  return true;
  } ], [ d3.time.format.utc("%B"), function(d) {
  return d.getUTCMonth();
  } ], [ d3.time.format.utc("%b %d"), function(d) {
  return d.getUTCDate() != 1;
  } ], [ d3.time.format.utc("%a %d"), function(d) {
  return d.getUTCDay() && d.getUTCDate() != 1;
  } ], [ d3.time.format.utc("%I %p"), function(d) {
  return d.getUTCHours();
  } ], [ d3.time.format.utc("%I:%M"), function(d) {
  return d.getUTCMinutes();
  } ], [ d3.time.format.utc(":%S"), function(d) {
  return d.getUTCSeconds();
  } ], [ d3.time.format.utc(".%L"), function(d) {
  return d.getUTCMilliseconds();
  } ] ];
  var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats);
  d3_time_scaleUTCMethods.year = function(extent, m) {
  return d3_time_scaleLinear.domain(extent.map(d3_time_scaleUTCGetYear)).ticks(m).map(d3_time_scaleUTCSetYear);
  };
  d3.time.scale.utc = function() {
  return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);
  };
  })();
  .rickshaw_graph .detail{pointer-events:none;position:absolute;top:0;z-index:2;background:rgba(0,0,0,.1);bottom:0;width:1px;transition:opacity .25s linear;-moz-transition:opacity .25s linear;-o-transition:opacity .25s linear;-webkit-transition:opacity .25s linear}.rickshaw_graph .detail.inactive{opacity:0}.rickshaw_graph .detail .item.active{opacity:1}.rickshaw_graph .detail .x_label{font-family:Arial,sans-serif;border-radius:3px;padding:6px;opacity:.5;border:1px solid #e0e0e0;font-size:12px;position:absolute;background:#fff;white-space:nowrap}.rickshaw_graph .detail .item{position:absolute;z-index:2;border-radius:3px;padding:.25em;font-size:12px;font-family:Arial,sans-serif;opacity:0;background:rgba(0,0,0,.4);color:#fff;border:1px solid rgba(0,0,0,.4);margin-left:1em;margin-top:-1em;white-space:nowrap}.rickshaw_graph .detail .item.active{opacity:1;background:rgba(0,0,0,.8)}.rickshaw_graph .detail .item:before{content:"\25c2";position:absolute;left:-.5em;color:rgba(0,0,0,.7);width:0}.rickshaw_graph .detail .dot{width:4px;height:4px;margin-left:-4px;margin-top:-3px;border-radius:5px;position:absolute;box-shadow:0 0 2px rgba(0,0,0,.6);background:#fff;border-width:2px;border-style:solid;display:none;background-clip:padding-box}.rickshaw_graph .detail .dot.active{display:block}.rickshaw_graph{position:relative}.rickshaw_graph svg{display:block;overflow:hidden}.rickshaw_graph .x_tick{position:absolute;top:0;bottom:0;width:0;border-left:1px dotted rgba(0,0,0,.2);pointer-events:none}.rickshaw_graph .x_tick .title{position:absolute;font-size:12px;font-family:Arial,sans-serif;opacity:.5;white-space:nowrap;margin-left:3px;bottom:1px}.rickshaw_annotation_timeline{height:1px;border-top:1px solid #e0e0e0;margin-top:10px;position:relative}.rickshaw_annotation_timeline .annotation{position:absolute;height:6px;width:6px;margin-left:-2px;top:-3px;border-radius:5px;background-color:rgba(0,0,0,.25)}.rickshaw_graph .annotation_line{position:absolute;top:0;bottom:-6px;width:0;border-left:2px solid rgba(0,0,0,.3);display:none}.rickshaw_graph .annotation_line.active{display:block}.rickshaw_graph .annotation_range{background:rgba(0,0,0,.1);display:none;position:absolute;top:0;bottom:-6px;z-index:-10}.rickshaw_graph .annotation_range.active{display:block}.rickshaw_graph .annotation_range.active.offscreen{display:none}.rickshaw_annotation_timeline .annotation .content{background:#fff;color:#000;opacity:.9;padding:5px 5px;box-shadow:0 0 2px rgba(0,0,0,.8);border-radius:3px;position:relative;z-index:20;font-size:12px;padding:6px 8px 8px;top:18px;left:-11px;width:160px;display:none;cursor:pointer}.rickshaw_annotation_timeline .annotation .content:before{content:"\25b2";position:absolute;top:-11px;color:#fff;text-shadow:0 -1px 1px rgba(0,0,0,.8)}.rickshaw_annotation_timeline .annotation.active,.rickshaw_annotation_timeline .annotation:hover{background-color:rgba(0,0,0,.8);cursor:none}.rickshaw_annotation_timeline .annotation .content:hover{z-index:50}.rickshaw_annotation_timeline .annotation.active .content{display:block}.rickshaw_annotation_timeline .annotation:hover .content{display:block;z-index:50}.rickshaw_graph .y_axis{fill:none}.rickshaw_graph .y_ticks .tick{stroke:rgba(0,0,0,.16);stroke-width:2px;shape-rendering:crisp-edges;pointer-events:none}.rickshaw_graph .y_grid .tick{z-index:-1;stroke:rgba(0,0,0,.20);stroke-width:1px;stroke-dasharray:1 1}.rickshaw_graph .y_grid path{fill:none;stroke:none}.rickshaw_graph .y_ticks path{fill:none;stroke:#808080}.rickshaw_graph .y_ticks text{opacity:.5;font-size:12px;pointer-events:none}.rickshaw_graph .x_tick.glow .title,.rickshaw_graph .y_ticks.glo