ó
¤Ç>Yc           @@  s‘  d  Z  d d l m Z d d l Z d d l m Z d d l m Z d d l	 m
 Z
 d d l m Z m Z m Z m Z m Z m Z m Z m Z m Z d d l m Z m Z m Z d d	 l m Z d
 d l m Z m Z m Z d
 d l m  Z  d
 d l! m" Z" m# Z# d
 d l$ m% Z% d
 d l& m' Z' m( Z( d
 d l) m* Z* m+ Z+ m, Z, d „  Z- d e
 f d „  ƒ  YZ. d e. f d „  ƒ  YZ/ d e. f d „  ƒ  YZ0 d S(   sÉ    This is the Bokeh charts interface. It gives you a high level API to build
complex plot in a simple way.

This is the Builder class, a minimal prototype class to build more chart
types on top of it.

i    (   t   absolute_importN(   t   string_types(   t   SortDirection(   t   HasProps(	   t   Boolt   Colort   Dictt   Eithert   Enumt   Instancet   Listt   Stringt   Tuple(   t   FactorRanget   Ranget   Range1d(   t   ColumnDataSourcei   (   t   AttrSpect   CatAttrt	   ColorAttr(   t   Chart(   t   ChartDataSourcet   OrderedAssigner(   t   CompositeGlyph(   t	   Dimensiont   ColumnLabel(   t   build_hover_tooltipst   collect_attribute_columnst   label_from_index_dictc   	      @  s4  t  |  d ƒ d k r+ t d |  j ƒ ‚ n  t  |  d ƒ d k rV t d |  j ƒ ‚ n  t |  j ƒ  ƒ t t  |  d g  ƒ ƒ B‰  x |  j D] } ˆ  j | ƒ qˆ Wx$ |  j j	 ƒ  D] } ˆ  j | ƒ q¯ W‡  f d †  | j
 ƒ  Dƒ } |  | | Ž  } ‡  f d †  | j
 ƒ  Dƒ } t |   } | j | ƒ | j ƒ  | S(	   sg   A factory function for handling Chart and Builder generation.

    Returns:
        :class:`Chart`
    t
   dimensionss6   Each builder must specify its dimensions, %s does not.t   default_attributess>   Each builder must specify its default_attributes, %s does not.t   __deprecated_attributes__c         @  s+   i  |  ]! \ } } | ˆ  k r | | “ q S(    (    (   t   .0t   kt   v(   t   builder_props(    s/   lib/python2.7/site-packages/bkcharts/builder.pys
   <dictcomp>2   s   	 c         @  s+   i  |  ]! \ } } | ˆ  k r | | “ q S(    (    (   R    R!   R"   (   R#   (    s/   lib/python2.7/site-packages/bkcharts/builder.pys
   <dictcomp>6   s   	 N(   t   getattrt   Nonet   NotImplementedErrort   __name__t   sett
   propertiesR   t   addR   t   keyst   itemsR   t   add_buildert
   start_plot(	   t   builder_classt   datat   kwst   dimt	   attr_namet   builder_kwst   buildert	   chart_kwst   chart(    (   R#   s/   lib/python2.7/site-packages/bkcharts/builder.pyt   create_and_build   s"    
t   Builderc           B@  sý  e  Z d  Z e e ƒ Z e e ƒ Z e ƒ  Z e ƒ  Z	 e ƒ  Z
 e ƒ  Z e e d d ƒZ d Z g  Z e e e e ƒ d d ƒZ d Z e e d d ƒZ e e e ƒ d d ƒZ e e d d ƒZ g  Z e Z e e e ƒ ƒ Z e e e d i  ƒZ  e d d ƒ Z! e" e# d d	 ƒZ$ e e% ƒ Z& e' e e( e e ƒ ƒ e e ƒ e d d d d
 ƒZ) d Z* d „  Z+ d „  Z, d „  Z- d „  Z. d „  Z/ d „  Z0 d „  Z1 d „  Z2 d d „ Z3 e4 d „  ƒ Z5 d „  Z6 d „  Z7 d d „ Z8 e9 d „  ƒ Z: e4 d „  ƒ Z; RS(   sâ   A prototype class to inherit each new chart Builder type.

    It provides useful methods to be used by the inherited builder classes,
    in order to automate most of the charts creation tasks and leave the
    core customization to specialized builder classes. In that pattern
    inherited builders just need to provide the following methods:

    Required:

    * :meth:`~bkcharts.builder.Builder.yield_renderers`: yields the glyphs to be
      rendered into the plot. Here you should call the
      :meth:`~bkcharts.builder.Builder.add_glyph` method so that the builder can
      setup the legend for you.
    * :meth:`~bkcharts.builder.Builder.set_ranges`: setup the ranges for the
      glyphs. This is called after glyph creation, so you are able to inspect the
      comp_glyphs for their minimum and maximum values. See the
      :meth:`~bkcharts.builder.Builder.create` method for more information on
      when this is called and how the builder provides the ranges to the containing
      :class:`Chart` using the :meth:`Chart.add_ranges` method.

    Optional:

    * :meth:`~bkcharts.builder.Builder.setup`: provides an area
      where subclasses of builder can introspect properties, setup attributes, or change
      property values. This is called before
      :meth:`~bkcharts.builder.Builder.process_data`.
    * :meth:`~bkcharts.builder.Builder.process_data`: provides an area
      where subclasses of builder can manipulate the source data before renderers are
      created.

    t   helps\   Optional input to override the default palette used
        by any color attribute.
        sç  
        The attribute specs used to group data. This is a mapping between the role of
        the attribute spec (e.g. 'color') and the
        :class:`~bkcharts.attributes.AttrSpec` class (e.g.,
        :class:`~bkcharts.attributes.ColorAttr`). The Builder will use this
        attributes property during runtime, which will consist of any attribute specs
        that are passed into the chart creation function (e.g.,
        :class:`~bkcharts.Bar`), ones that are created for the user from simple
        input types (e.g. `Bar(..., color='red')` or `Bar(..., color=<column_name>)`),
        or lastly, the attribute spec found in the default_attributes configured for
        the subclass of :class:`~bkcharts.builder.Builder`.
        sí   
        All columns used for specifying attributes for the Chart. The Builder will set
        this value on creation so that the subclasses can know the distinct set of columns
        that are being used to assign attributes.
        sn  
        A list of composite glyphs, where each represents a unique subset of data. The
        composite glyph is a helper class that encapsulates all low level
        :class:`~bokeh.models.glyphs.Glyph`, that represent a higher level group of
        data. For example, the :class:`BoxGlyph` is a single class that yields
        each :class:`GlyphRenderer` needed to produce a Box on a :class:`BoxPlot`. The
        single Box represents a full array of values that are aggregated, and is made
        up of multiple :class:`~bokeh.models.glyphs.Rect` and
        :class:`~bokeh.models.glyphs.Segment` glyphs.
        s4   Represents the unique labels to be used for legends.t   defaultsµ   
        Attribute that should be used to sort the legend, for example: color,
        dash, maker, etc. Valid values for this property depend on the type
        of chart.
        s†   
    Sort direction to apply to :attr:`~bkcharts.builder.Builder.sort_legend`.
    Valid values are: `ascending` or `descending`.
    sF  
        Tells the builder to add tooltips to the chart by either using the columns
        specified to the chart attributes (True), or by generating tooltips for each
        column specified (list(str)), or by explicit specification of the tooltips
        using the valid input for the `HoverTool` tooltips kwarg.
        c   
      O@  sÀ  d } t | ƒ d k s* t | ƒ d k r8t |  j j ƒ  ƒ } |  j | } i  } x1 | D]) } | | j ƒ  k rY | | | | <qY qY Wt | ƒ | d <t |  j ƒ | d <| | d <|  j | d <t	 j
 | | Ž  } x- |  j D]" } t t |  | ƒ d ƒ | ƒ qÜ W|  j | | ƒ } x* | D] } | j | d ƒ qWn	 t ƒ  } | | d <t t |  ƒ j |   t |  j   |  _ x4 |  j D]) }	 |	 | k r}t |  |	 | |	 ƒ q}q}W| |  _ g  |  _ d S(	   s™  Common arguments to be used by all the inherited classes.

        Args:
            data (:ref:`userguide_charts_data_types`): source data for the chart
            legend (str, bool): the legend of your plot. The legend content is
                inferred from incoming input.It can be ``top_left``,
                ``top_right``, ``bottom_left``, ``bottom_right``.
                It is ``top_right`` is you set it as True.

        Attributes:
            source (obj): datasource object for your plot,
                initialized as a dummy None.
            x_range (obj): x-associated datarange object for you plot,
                initialized as a dummy None.
            y_range (obj): y-associated datarange object for you plot,
                initialized as a dummy None.
            groups (list): to be filled with the incoming groups of data.
                Useful for legend construction.
            data (dict): to be filled with the incoming data and be passed
                to the ChartDataSource for each Builder class.
            attr (list(AttrSpec)): to be filled with the new attributes created after
                loading the data dict.
        i    t   dimst   required_dimst   attrst   column_assignert   set_datat
   attributesN(   R%   t   lent   listR   R+   R   t   tuplet   req_dimensionst   column_selectorR   t	   from_dataR$   t   _setup_attrst   popt   dictt   superR9   t   __init__R   RA   t   attribute_columnsR   t   setattrt   _datat   _legends(
   t   selft   argsR1   R0   R>   R<   t	   data_argsR2   RA   R!   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRL   ß   s6    $
 	
	c   	      C@  sy  t  | j ƒ } |  j j ƒ  } | j d ƒ } t ƒ  } x| D]} | j | d ƒ } t | t	 ƒ rq | | | <q= t | t
 t f ƒ rì |  j | j ƒ  | | <t | | t ƒ rÏ | d k	 rÏ | | | _ qÏ n  | | j d | d | ƒ q= t |  j | t ƒ r5| d k	 r5|  j | j ƒ  | | <| | | _ q= |  j | j ƒ  | | <q= Wx" | D] } | | j d | ƒ qWW| S(   sø   Handle overridden attributes and initialize them with data.

        Makes sure that all attributes have access to the data
        source, which is used for mapping attributes to groups
        of data.

        Returns:
            None

        t   paletteR0   t   columnsN(   R   t   dfR   R+   t   getRJ   RI   R%   t
   isinstanceR   t   strRC   t   _cloneR   t   iterablet   setupt   update_data(	   RQ   R0   R1   t   sourcet
   attr_namest   custom_paletteRA   R3   t   attr(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRH   %  s,    	c         C@  s   d S(   sb   Perform any initial pre-processing, attribute config.

        Returns:
            None

        N(    (   RQ   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyR\   X  s    c         C@  s   d S(   s  Make any global data manipulations before grouping.

        It has to be implemented by any of the inherited class
        representing each different chart type. It is the place
        where we make specific calculations for each chart.

        Returns:
            None

        N(    (   RQ   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   process_dataa  s    c         C@  s   t  d |  j j ƒ ‚ d S(   så    Generator that yields the glyphs to be draw on the plot

        It has to be implemented by any of the inherited class
        representing each different chart type.

        Yields:
            :class:`GlyphRenderer`
        s1   Subclasses of %s must implement _yield_renderers.N(   R&   t	   __class__R'   (   RQ   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   yield_renderersn  s    	c         C@  s   t  d |  j j ƒ ‚ d S(   sý   Calculate and set the x and y ranges.

        It has to be implemented by any of the subclasses of builder
        representing each different chart type, and is called after
        :meth:`yield_renderers`.

        Returns:
            None

        s,   Subclasses of %s must implement _set_ranges.N(   R&   Rc   R'   (   RQ   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt
   set_rangesz  s    c         C@  sœ   i t  g  |  j D] } | j ^ q ƒ d 6t  g  |  j D] } | j ^ q6 ƒ d 6t g  |  j D] } | j ^ q\ ƒ d 6t g  |  j D] } | j ^ q‚ ƒ d 6S(   s±   Helper method to retrieve maximum extents of all the renderers.

        Returns:
            a dict mapping between dimension and value for x_max, y_max, x_min, y_min

        t   x_maxt   y_maxt   x_mint   y_min(   t   maxt   comp_glyphsRf   Rg   t   minRh   Ri   (   RQ   t   renderer(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   get_dim_extentsˆ  s    )&&c         C@  s  t  | t ƒ r3 x1 | D] } |  j j | ƒ q Wn |  j j | ƒ d } t |  j ƒ d k r£ xB |  j D]4 } |  j | j d k	 rh |  j	 | d | ƒ} qh qh Wn  | d k rÇ |  j	 | d d ƒ} n  t
 | ƒ |  j k r| d k	 r|  j j | | j f ƒ |  j j | ƒ n  d S(   sc  Add a composite glyph.

        Manages the legend, since the builder might not want all attribute types
        used for the legend.

        Args:
            group (:class:`DataGroup`): the data the `glyph` is associated with
            glyph (:class:`CompositeGlyph`): the glyph associated with the `group`

        Returns:
            None
        i    Ra   t   labelN(   RX   RC   Rk   t   appendR%   RB   t   label_attributesRA   RU   t   _get_group_labelRY   t   labelsRP   t	   renderers(   RQ   t   groupt   glypht	   sub_glyphRo   Ra   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt	   add_glyph•  s    !Ro   c         C@  sS   | d k r | j  } n. | | } t | t ƒ rF t | j ƒ  ƒ } n  |  j | ƒ S(   s,  Get the label of the group by the attribute name.

        Args:
            group (:attr:`DataGroup`: the group of data
            attr (str, optional): the attribute name containing the label, defaults to
                'label'.

        Returns:
            str: the label for the group
        Ro   (   Ro   RX   RJ   RD   t   valuest
   _get_label(   RQ   Ru   Ra   Ro   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRr   ¹  s    
c         C@  su   |  d k r d St |  t ƒ s. t |  t ƒ rM t |  ƒ d k rM |  d }  n t |  t ƒ rk t |  ƒ }  n  t |  ƒ S(   sò   Converts a label by string or tuple to a string representation.

        Args:
            raw_label (str or tuple(any, any)): a unique identifier for the data group

        Returns:
            str: a label that is usable in charts
        i   i    N(   R%   RX   RD   RC   RB   RJ   R   RY   (   t	   raw_label(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRz   Í  s    c         C@  se   t  t |  j |  ƒ d ƒ rX t |  j j ƒ  ƒ t t |  j |  ƒ j pH i  j ƒ  ƒ } n	 t ƒ  } | S(   NR   (   t   hasattrRK   Rc   R(   R   R+   (   RQ   R>   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   collect_attr_kwargsã  s
    (	c         @  s   ‡  f d †  | Dƒ S(   Nc         @  s   i  |  ] } ˆ  | | “ q S(    (    (   R    Ra   (   Ru   (    s/   lib/python2.7/site-packages/bkcharts/builder.pys
   <dictcomp>ì  s   	 (    (   RQ   Ru   R>   (    (   Ru   s/   lib/python2.7/site-packages/bkcharts/builder.pyt   get_group_kwargsë  s    c         C@  s9  |  j  ƒ  |  j ƒ  |  j ƒ  } | d k r8 t ƒ  } n  | j |  | ƒ |  j ƒ  | j d |  j ƒ | j d |  j	 ƒ |  j
 |  j |  j |  j |  j ƒ |  _ | j |  j ƒ | j d |  j ƒ | j d |  j ƒ | j d |  j ƒ | j d |  j ƒ |  j d k	 r5t d |  j d |  j ƒ } | j | ƒ n  | S(   s  Builds the renderers, adding them and other components to the chart.

        Args:
            chart (:class:`Chart`, optional): the chart that will contain the glyph
                renderers that the `Builder` produces.

        Returns:
            :class:`Chart`
        t   xt   yt
   hover_spect
   chart_colsN(   R\   Rb   Rd   R%   R   t   add_renderersRe   t
   add_rangest   x_ranget   y_ranget   _sort_legendt   legend_sort_fieldt   legend_sort_directionRP   RA   t
   add_legendt
   add_labelst   xlabelt   ylabelt
   add_scalest   xscalet   yscalet   tooltipsR   RM   t   add_tooltips(   RQ   R7   Rt   R‘   (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   createî  s,    


c         C@  s4   d } x' |  j  D] } | t | j ƒ  ƒ 7} q W| S(   Nt    (   t   comp_glyph_typesRY   t   glyph_properties(   t   clst   help_strt
   comp_glyph(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   generate_help  s    c         @  sÊ   |  rÆ t  | |  j ƒ d k rÆ g  | |  j D]% } t | t ƒ rL | d n | ^ q- ‰  g  ˆ  D]' } t | t ƒ s€ t | ƒ n | ^ q_ ‰  ‡  f d †  } | d k } t t | d | d | ƒƒ Sn  | S(   s|   Sort legends sorted by looping though sort_legend items (
        see :attr:`Builder.sort_legend` for more details)
        i    c         @  s   ˆ  j  |  d ƒ S(   Ni    (   t   index(   t   leg(   t
   item_order(    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   foo8  s    t
   descendingt   keyt   reverse(	   RB   RU   R,   RX   RD   R   RY   RC   t   sorted(   Rˆ   R‰   t   legendsRA   R   Rž   R¡   (    (   R   s/   lib/python2.7/site-packages/bkcharts/builder.pyR‡   %  s    61N(    (<   R'   t
   __module__t   __doc__R	   R   R…   R†   R   RŒ   R   R   R   R
   R   RT   R%   R   RE   R   R   RA   R   R   RM   R   Rk   Rs   Rq   R   RF   R•   R   t   sort_dimRˆ   R   R   R‰   R   R^   R   R   R‘   R   RL   RH   R\   Rb   Rd   Re   Rn   Rx   Rr   t   staticmethodRz   R}   R~   R“   t   classmethodRš   R‡   (    (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyR9   >   s\   														*		F	3							$		/t	   XYBuilderc           B@  so   e  Z d  Z e d ƒ Z e d ƒ Z d d g Z d g d g d d g g Z i e ƒ  d 6Z	 d „  Z
 d „  Z RS(   s0   Implements common functionality for XY Builders.R   R€   t   colorc         C@  s:  |  j  ƒ  } | d } | d } |  j d | | ƒ |  _ | d } | d } |  j d | | ƒ |  _ |  j d	 k rÍ |  j j d	 k	 r¯ |  j j } t | t	 ƒ s¸ | g } q¸ n	 d g } d j
 | ƒ |  _ n  |  j d	 k r6|  j j d	 k	 r|  j j } t | t	 ƒ s!| g } q!n	 d g } d j
 | ƒ |  _ n  d	 S(
   s%   Calculate and set the x and y ranges.Rf   Rh   R   Rg   Ri   R€   R”   s   , N(   Rn   t
   _get_rangeR…   R†   RŒ   R%   R   t	   selectionRX   RC   t   joinR   R€   (   RQ   t   extentst   endxt   startxt   endyt   startyt   select(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRe   L  s*    



		c   
      C@  sw  t  |  | ƒ } | j } | j } |  j j | ƒ } | j d k r¶ | j ƒ  } | r y | j d t ƒ Wq t	 k
 r‹ | j
 d t ƒ q Xn  t |  | d d ƒ t d | j ƒ  ƒ St j | t j ƒ rò t |  | d d ƒ t d | d | ƒ S| d	 k s| | d
 k r2t |  | d d ƒ t d d	 g ƒ S| | }	 t |  | d d ƒ t d | d |	 d | d |	 ƒ Sd S(   s-  Create a :class:`Range` for the :class:`Chart`.

        Args:
            dim (str): the name of the dimension, which is an attribute of the builder
            start: the starting value of the range
            end: the ending value of the range

        Returns:
            :class:`Range`
        t   objectt   inplacet   scalet   categoricalt   factorst   datetimet   startt   endR%   i    t   lineargš™™™™™¹?N(   R$   R0   t   dtypeR¦   RW   t   namet   drop_duplicatest   sort_valuest   Truet   AttributeErrort   sortRN   R   t   tolistt   npt
   issubdtypet
   datetime64R   (
   RQ   R2   Rº   R»   t   dim_refRy   R½   RÃ   R¸   t   diff(    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyR«   k  s,    		
(   R'   R¤   R¥   R   R   R€   R   RE   R   R   Re   R«   (    (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyR©   ?  s   	t   AggregateBuilderc           B@  s4   e  Z d  Z e d ƒ Z i e ƒ  d 6e ƒ  d 6Z RS(   s™   A base class for deriving specific builders performing aggregation with stats.

    The typical AggregateBuilder takes a single dimension of values.
    Ry   Ro   Rª   (   R'   R¤   R¥   R   Ry   R   R   R   (    (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyRÊ   ˜  s   (1   R¥   t
   __future__R    t   numpyRÅ   t   sixR   t   bokeh.core.enumsR   t   bokeh.core.has_propsR   t   bokeh.core.propertiesR   R   R   R   R   R	   R
   R   R   t   bokeh.models.rangesR   R   R   t   bokeh.models.sourcesR   RA   R   R   R   R7   R   t   data_sourceR   R   t   modelsR   R)   R   R   t   utilsR   R   R   R8   R9   R©   RÊ   (    (    (    s/   lib/python2.7/site-packages/bkcharts/builder.pyt   <module>   s(   @	$ÿ ÿ Y