
    eq                    J   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	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 d(d
Zd Z G d de          Z G d de          Z G d de          Z G d de          Z G d d          Zed             Z G d dej                   Z! G d dej                   Z"d Z# G d de"          Z$ G d d          Z% G d  d!e          Z& e%            Z' G d" d#ej                   Z( G d$ d%          Z) G d& d'          Z*dS ))a  
Options and OptionTrees allow different classes of options
(e.g. matplotlib-specific styles and plot specific parameters) to be
defined separately from the core data structures and away from
visualization specific code.

There are three classes that form the options system:

Cycle:

   Used to define infinite cycles over a finite set of elements, using
   either an explicit list or some pre-defined collection (e.g. from
   matplotlib rcParams). For instance, a Cycle object can be used loop
   a set of display colors for multiple curves on a single axis.

Options:

   Containers of arbitrary keyword values, including optional keyword
   validation, support for Cycle objects and inheritance.

OptionTree:

   A subclass of AttrTree that is used to define the inheritance
   relationships between a collection of Options objects. Each node
   of the tree supports a group of Options objects and the leaf nodes
   inherit their keyword values from parent nodes up to the root.

Store:

   A singleton class that stores all global and custom options and
   links HoloViews objects, the chosen plotting backend and the IPython
   extension together.

    N)defaultdict)contextmanager   )Opts)InfoPrinter)AttrTree)group_sanitizerlabel_sanitizersanitize_identifierc                    	 t           j        rdS t           j                            | g           }||v r|                    |           g }t          |          D ]D} |            }||j        | k    r|                    |           /|                    |           E|sUt                                           D ];}| t           j	        |         v r%t           j	        |         
                    |            <|s"t           j        
                    | d           dS dS # t          $ r}t          d|  d| d          |d}~ww xY w)z
    Cleans up unused custom trees if all objects referencing the
    custom id have been garbage collected or tree is otherwise
    unreferenced.
    Nz(Cleanup of custom options tree with id 'z'' failed with the following exception: z4, an unreferenced orphan tree may persist in memory.)Store_options_context	_weakrefsgetremovelistidappendloaded_backends_custom_optionspop	Exception)r   weakrefweakrefsrefswrrbkes           6lib/python3.11/site-packages/holoviews/core/options.pycleanup_custom_optionsr!   3   s   ! 	F?&&r2..hOOG$$$x.. 	 	BAyADBJJ####A 	6++-- 6 6.r222)"-11"555 	*OD)))))	* 	*   1r 1 1-.1 1 1
 
 		s   D DD 
E&D==Ec                 Z   d}	 t           j        |                             |           }|j        }n# t          $ r d}Y nw xY wt                               || |          }|dk    r||                    |          S |dk    r)|r'|                    t          |j                            S |S )z
    Given a HoloViews object, a plot option group (e.g. 'style') and
    backend, return the corresponding Options object.
    Nstyleplot)	r   	renderersplotting_class
style_optsSkipRenderinglookup_optionsfilteredr   param)objgroupbackend
plot_classr'   nodes         r    r)   r)   T   s    
 J_W-<<SAA
*

   


 e44DJ2}}Z(((	&Z}}T*"233444s   ,1 A A c                       e Zd ZdZdS )CallbackErrorz,
    An error raised during a callback.
    N)__name__
__module____qualname____doc__     r    r2   r2   i   s           r8   r2   c                   $     e Zd ZdZd fd	Z xZS )r(   z
    A SkipRendering exception in the plotting code will make the display
    hooks fall back to a text repr. Used to skip rendering of
    DynamicMaps with exhausted element generators.
     Tc                 X    || _         t                                          |           d S N)warnsuper__init__)selfmessager=   	__class__s      r    r?   zSkipRendering.__init__u   s(    	!!!!!r8   )r:   T)r3   r4   r5   r6   r?   __classcell__rB   s   @r    r(   r(   o   sG         
" " " " " " " " " "r8   r(   c                   2     e Zd ZdZ	 d fd	Zd Zd Z xZS )OptionErrorz
    Custom exception raised when there is an attempt to apply invalid
    options. Stores the necessary information to construct a more
    readable message for the user if caught and processed
    appropriately.
    Nc                     t                                          |                     ||||                     || _        || _        || _        || _        d S r<   )r>   r?   rA   invalid_keywordallowed_keywords
group_namepath)r@   rH   rI   rJ   rK   rB   s        r    r?   zOptionError.__init__   s]    o&6&0$8 8 	9 	9 	9  / 0#			r8   c                 6    d|d| d}|r|rd|d| d| }|S )NzInvalid option , valid options are: .zInvalid key for group z	 on path z;
r7   )r@   rH   rI   rJ   rK   msgs         r    rA   zOptionError.message   s_    #o # ## # # 	  	QJ 	QP:PP$PP3PPC
r8   c                    | j         }|j        }|                    | j                  }|s
|j        }d}nd}t
                                          }|rd| nd}t          |          dk    rd|d         }n5d                    d	 |d
d         D                       }d| d|d         }| j	        r
| j	         dnd}d| d| j         d| | d| dt
          j
         d| dS )zG
        Return a fuzzy match message based on the OptionError
        PossibleSimilarzfor r:   r   z in loaded backend r   , c                 ,    g | ]}t          |          S r7   repr).0bs     r    
<listcomp>z4OptionError.format_options_error.<locals>.<listcomp>   s    %L%L%L!d1gg%L%L%Lr8   Nz in loaded backends z and z optionkeywordzUnexpected z 'z' z.

z# keywords in the currently active 'z' renderer are: zy

If you believe this keyword is correct, please make sure the backend has been imported or loaded with the hv.extension.)rI   targetfuzzy_matchrH   valuesr   r   lenjoinrJ   current_backend)	r@   rI   r\   matches
similarityr   loadedbackend_listr-   s	            r    format_options_errorz OptionError.format_options_error   s\     0!("..t/CDD 	#&-G#JJ"J//11$*21$$A?1+=AAFF99%L%Lss7K%L%L%LMMLVLVVr?RVVF/3M4?++++I%% % %4#7 % %6 %% %&% %,% % % % %	
r8   NN)r3   r4   r5   r6   r?   rA   rf   rC   rD   s   @r    rF   rF   z   sj          (,       
 
 
 
 
 
 
r8   rF   c                   $    e Zd ZdZd Zd Zd ZdS )AbbreviatedExceptiona  
    Raised by the abbreviate_exception context manager when it is
    appropriate to present an abbreviated the traceback and exception
    message in the notebook.

    Particularly useful when processing style options supplied by the
    user which may not be valid.
    c                 X    || _         || _        || _        t          |          | _        d S r<   )etypevalue	tracebackstrrO   r@   rk   rl   rm   s       r    r?   zAbbreviatedException.__init__   s(    

"u::r8   c                 0    | j         j         d| j         dS )Nz: zY

To view the original traceback, catch this exception and call print_traceback() method.)rk   r3   rO   r@   s    r    __str__zAbbreviatedException.__str__   s,    z" - -dh - - -	
r8   c                 P    t          j        | j        | j        | j                    dS )z[
        Print the traceback of the exception wrapped by the AbbreviatedException.
        N)rm   print_exceptionrk   rl   rq   s    r    print_tracebackz$AbbreviatedException.print_traceback   s%     	!$*dj$.IIIIIr8   N)r3   r4   r5   r6   r?   rr   ru   r7   r8   r    ri   ri      sP           
 
 
J J J J Jr8   ri   c                       e Zd ZdZd Zd ZdS )abbreviated_exceptionz
    Context manager used to to abbreviate tracebacks using an
    AbbreviatedException when a backend may raise an error due to
    incorrect style options.
    c                     | S r<   r7   rq   s    r    	__enter__zabbreviated_exception.__enter__   s    r8   c                 R    t          |t                    rt          |||          d S r<   )
isinstancer   ri   ro   s       r    __exit__zabbreviated_exception.__exit__   s3    eY'' 	@&ueY???	@ 	@r8   N)r3   r4   r5   r6   ry   r|   r7   r8   r    rw   rw      sA         
  @ @ @ @ @r8   rw   c              #      K   t           j        t           j        f}| |ct           _        t           _        	 dV  |\  t           _        t           _        dS # |\  t           _        t           _        w xY w)zo
    Context manager to temporarily set the skip_invalid and warn_on_skip
    class parameters on Options.
    N)Optionsskip_invalidwarn_on_skip)r   r   settingss      r    options_policyr      sk       $g&:;H4@,0W7/@7?4	w333x4	w3????s   A A/c                        e Zd ZdZ ej        d          Z ej        dd          Zd fd	Z	d	 Z
d
 Zd Zd Zd Zd Zd Z xZS )Keywordsa  
    A keywords objects represents a set of Python keywords. It is
    list-like and ordered but it is also a set without duplicates. When
    passed as **kwargs, Python keywords are not ordered but this class
    always lists keywords in sorted order.

    In addition to containing the list of keywords, Keywords has an
    optional target which describes what the keywords are applicable to.

    This class is for internal use only and should not be in the user
    namespace.
    z!Set of keywords as a sorted list.docTzB
       Optional string description of what the keywords apply to.
allow_Noner   Nc                     |g }d |D             }d|v rt          d|           t                                          t          |          |           d S )Nc                 8    g | ]}t          |t                    S r7   r{   rn   rW   vs     r    rY   z%Keywords.__init__.<locals>.<listcomp>  s"    666!:a%%666r8   FzAll keywords must be strings: r^   r\   )
ValueErrorr>   r?   sorted)r@   r^   r\   stringsrB   s       r    r?   zKeywords.__init__  sx    >F66v666GFfFFGGGv5; 	 	= 	= 	= 	= 	=r8   c                     | j         r&|j         r| j         |j         k    rt          d          | j         p|j         }t          t          t	          | j        |j        z                       |          S )Nz&Targets must match to combine Keywordsr\   )r\   r   r   r   setr^   )r@   otherr\   s      r    __add__zKeywords.__add__  sn    K 	FEL 	Ft{el/J/JDEEE,s4;#=>>??OOOOr8   c                 6    t          j        || j                  S )zt
        Given a string, fuzzy match against the Keyword values,
        returning a list of close matches.
        )difflibget_close_matchesr^   )r@   kws     r    r]   zKeywords.fuzzy_match  s    
 (T[999r8   c                     | j         rd}t          | j        | j                   }nd}t          | j                  } |j        di |S )Nz#Keywords({values}, target={target})r   zKeywords({values})r^   r7   )r\   dictr^   format)r@   rO   infos      r    __repr__zKeywords.__repr__  sX    ; 	,7Ct{4;???DD&Ct{+++Dsz!!D!!!r8   c                 *    t          | j                  S r<   )rn   r^   rq   s    r    rr   zKeywords.__str__"  s    DK(8(8!8r8   c                 *    t          | j                  S r<   )iterr^   rq   s    r    __iter__zKeywords.__iter__#      T[(9(9!9r8   c                 *    t          | j                  S r<   )boolr^   rq   s    r    __bool__zKeywords.__bool__$  r   r8   c                     || j         v S r<   r   )r@   vals     r    __contains__zKeywords.__contains__%  s    t{(:!:r8   rg   )r3   r4   r5   r6   r+   Listr^   Stringr\   r?   r   r]   r   rr   r   r   r   rC   rD   s   @r    r   r      s          UZ?@@@FU\T 0E F F FF= = = = = =P P P: : :" " " 988999999:::::::r8   r   c                        e Zd ZdZ ej        ddd          Z ej        g d          Zdg iZ	d fd		Z
d
 Zd ZddZd Zd Z xZS )Cyclea#  
    A simple container class that specifies cyclic options. A typical
    example would be to cycle the curve colors in an Overlay composed
    of an arbitrary number of curves. The values may be supplied as
    an explicit list or a key to look up in the default cycles
    attribute.
    default_colorsTzs
       The key in the default_cycles dictionary used to specify the
       color cycle if values is not supplied. )defaultr   r   z/
       The values the cycle will iterate over.r   r   Nc                     |%t          |t                    r||d<   n
||d<   d |d<    t                      j        di | |                                 | _        d S )Nkeyr^   r7   )r{   rn   r>   r?   _get_valuesr^   )r@   cycleparamsrB   s      r    r?   zCycle.__init__;  sm    %%% % %u#(x  $u""6"""&&((r8   c                 4     | | j         d |                   S )Nr   r   )r@   nums     r    __getitem__zCycle.__getitem__F  s     t4;tt,----r8   c                 ,   | j         r| j         S | j        r-| j        | j        v rt          | j        | j                           S | j        r=t          j        }d                    h d|hz
            }t          d| d| d          t          d          )Nz or >   bokehplotly
matplotlibz3The key you have supplied is not available for the z backend. Try to switch to z with 'hv.extension(backend)'.z'Supply either a key or explicit values.)r^   r   default_cyclesr   r   ra   r`   r   )r@   currentotherss      r    r   zCycle._get_valuesJ  s    ; 	Ht{*X 	H$(d&999+DH5666X 		H+G[[!B!B!BgY!NOOF0"0 0?E0 0 0   FGGGr8   c           	      z    |r|n| j         } | j        di t          | j                                         fd|i|S )Nr^   r7   )r^   rB   r   r+   )r@   r^   r   s      r    __call__zCycle.__call__Z  sM    !2t{t~SSTZ%6%6%8%8 R R R6 R RSSSr8   c                 *    t          | j                  S r<   )r_   r^   rq   s    r    __len__zCycle.__len___  s    4;r8   c                     | j         | j                            d          d         j        k    rd}n-| j         rt	          | j                   }nd | j        D             }t          |           j         d| dS )NFr   r:   c                 ,    g | ]}t          |          S r7   rn   rW   els     r    rY   z"Cycle.__repr__.<locals>.<listcomp>i  s    333SWW333r8   ())r   r+   objectsr   rV   r^   typer3   )r@   vreprs     r    r   zCycle.__repr__c  s|    8tz))%007???EEX 	4NNEE33t{333Et**%000000r8   r<   )r3   r4   r5   r6   r+   r   r   r   r^   r   r?   r   r   r   r   r   rC   rD   s   @r    r   r   )  s          %,/D G2 3 3 3C UZ )2 3 3 3F '+N) ) ) ) ) ). . .H H H T T T T
     1 1 1 1 1 1 1r8   r   c                     | | | dfS )Ng      ?r7   )r   s    r    	grayscaler   n  s    c3r8   c                        e Zd ZdZ ej        dd          Z ej        dd          Z ej	        dd          Z
 ej        ej        d	          Z ej        d
d          ZdeiZ fdZd Zd Z xZS )Palettea  
    Palettes allow easy specifying a discrete sampling
    of an existing colormap. Palettes may be supplied a key
    to look up a function function in the colormap class
    attribute. The function should accept a float scalar
    in the specified range and return a RGB(A) tuple.
    The number of samples may also be specified as a
    parameter.

    The range and samples may conveniently be overridden
    with the __getitem__ method.
    r   z>
       Palettes look up the Palette values based on some key.r   )r   r   z=
        The range from which the Palette values are sampled.    zU
        The number of samples in the given range to supply to
        the sample_fn.zA
        The function to generate the samples, by default linear.Fz(
        Whether to reverse the palette.c                 ~     t          t          |           j        dd|i| |                                 | _        d S )Nr   r7   )r>   r   r?   r   r^   )r@   r   r   rB   s      r    r?   zPalette.__init__  sB    #eT#666v666&&((r8   c                     | j         | j        c\  }}}t          |t                    r+|j        |j        }|j        |j        }|j        |j        }n|} | ||f|          S )z
        Provides a convenient interface to override the
        range and samples parameters of the Cycle.
        Supplying a slice step or index overrides the
        number of samples. Unsupplied slice values will be
        inherited.
        N)rangesamples)r   r   r{   slicestartstopstep)r@   slcr   r   r   s        r    r   zPalette.__getitem__  sv     #j$,tc5!! 	y$	x#xx#xDt5$-6666r8   c                     | j         | j                 | j        | j        c\  }}}fd|                     |||          D             }| j        r|d d d         n|S )Nc                 &    g | ]} |          S r7   r7   )rW   ncmaps     r    rY   z'Palette._get_values.<locals>.<listcomp>  s!    GGGq4477GGGr8   rZ   )	colormapsr   r   r   	sample_fnreverse)r@   r   r   stepsr   r   s        @r    r   zPalette._get_values  si    ~dh'#z4<uGGGGDNN5$$F$FGGG $9wttt}}'9r8   )r3   r4   r5   r6   r+   r   r   NumericTupler   Integerr   Callablenplinspacer   Booleanr   r   r   r?   r   r   rC   rD   s   @r    r   r   r  s          %,{ 1A B B BC Ev 4@ A A AE emB -   G r{ 9D E E EI emE 0+ , , ,G i(I) ) ) ) )
7 7 7*: : : : : : :r8   r   c                       e Zd ZdZdZdZg dZdgZ	 	 ddZd Z	d Z
dd	Zd
 Zd Zed             Zd Zed             Zd Zd ZdS )r~   a  
    An Options object holds a collection of keyword options. In
    addition, Options support (optional) keyword validation as well as
    infinite indexing over the set of supplied cyclic values.

    Options support inheritance of setting values via the __call__
    method. By calling an Options object with additional keywords, you
    can create a new Options object inheriting the parent options.
    T)r#   r$   normoutputr.   Nc           	      x  	 |g }g 	t                                                    D ]5}|r1||vr-| j        r	                    |           %t	          ||          6|ru|d                                         r[|| j        vrRt          d                    t          |          d
                    d | j        D                                           	D ].}t	          |||          }t                              |           /	r'| j        r | j                            d	d|           t!          	fdt                                                    D                       | _        g | _        || _        t)          |t*                    r|nt+          |          }|| _        || _        || _        d S )	Nr   zTKey {} does not start with a capitalized element class name and is not a group in {}rS   c              3   4   K   | ]}t          |          V  d S r<   rU   r   s     r    	<genexpr>z#Options.__init__.<locals>.<genexpr>  sa        Ow  Ow  ]_  PT  UW  PX  PX  Ow  Ow  Ow  Ow  Ow  Owr8   )rJ   zInvalid options rM   c                 ,    g | ]}|v||         fS r7   r7   )rW   kinvalid_kwskwargss     r    rY   z$Options.__init__.<locals>.<listcomp>  s,    aaaaAU`L`L`QvayML`L`L`r8   )r   keysr   r   rF   islower_option_groupsr   r   rV   r`   StoreOptionsrecord_skipped_optionr   r+   warningr   r   _options_max_cyclesr{   r   rI   merge_keywordsr   )
r@   r   rI   r   
max_cyclesr   kwarg
invalid_kwerrorr   s
        `   @r    r?   zOptions.__init__  sA    #!FKKMM** 	? 	?E ?E1A$A$A$ ?&&u----%e-=>>> 	y3q6>>## 	y43F(F(Fryyz~  @C  {D  {D  FJ  FO  FO  Ow  Ow  cg  cv  Ow  Ow  Ow  Fw  Fw  x  x  y  y  y% 	6 	6J
,<MMME..u5555 	l4, 	lJj+jjVfjjkkkaaaaa6&++--3H3Haaabb%0:;KX0V0V <,,!)*:!;!; 	 0,r8   c                     || j         _        | S )zZ
        Helper method to easily set the target on the allowed_keywords Keywords.
        )rI   r\   )r@   r\   s     r    keywords_targetzOptions.keywords_target  s     (.$r8   c                     fd| j                                         D             } | j        d| j        | j        | j        d|S )z
        Return a new Options object that is filtered by the specified
        list of keys. Mutating self.kwargs to filter is unsafe due to
        the option expansion that occurs on initialization.
        c                 $    i | ]\  }}|v 	||S r7   r7   )rW   r   r   alloweds      r    
<dictcomp>z$Options.filtered.<locals>.<dictcomp>  s$    BBBsqQ'\\q\\\r8   )r   rI   r   r7   )r   itemsrB   r   rI   r   )r@   r  kwss    ` r    r*   zOptions.filtered  sk     CBBBdk//11BBBt~ I$(/3/D-1-@I IDGI I 	Ir8   c           	          d|vr
| j         |d<   |dg fv r| j        n|}t          dd|i|} | j        di t          | j        fi |S )zO
        Create a new Options object that inherits the parent options.
        r   NrI   r7   )r   rI   r   rB   r   )r@   rI   r   inherited_styles       r    r   zOptions.__call__   sz      HF5M2BtBi2O2O..UeKK0@KFKKt~EET[ D DO D DEEEr8   c                 h    t          t          | j                                                            S )z.The keyword names across the supplied options.)r   r   r   r   rq   s    r    r   zOptions.keys
  s&    d4;++--..///r8   c                 b    fd| j                                         D             } | ddi|S )z
        Truncates all contained Palette objects to a maximum number
        of samples and returns a new Options object containing the
        truncated or resampled Palettes.
        c                 V    i | ]%\  }}|t          |t                    r|         n|&S r7   )r{   r   )rW   r   argr   s      r    r  z&Options.max_cycles.<locals>.<dictcomp>  sF     6 6 6b# :c7#;#;Ds3xx 6 6 6r8   r   r7   )r   r	  )r@   r   r   s    ` r    r   zOptions.max_cycles  sT    6 6 6 6!%!2!2!4!46 6 6t--s-f---r8   c                 b    t          d | j                                        D                       S )z2Returns True if the options cycle, otherwise Falsec              3   @   K   | ]}t          |t                    V  d S r<   r{   r   )rW   r   s     r    r   z!Options.cyclic.<locals>.<genexpr>  s,      JJc:c5))JJJJJJr8   )anyr   r^   rq   s    r    cycliczOptions.cyclic  s/     JJT[5G5G5I5IJJJJJJr8   c                 J   t          | j                  dk    ri S d | j                                        D             }i }|                                D ] \  }}||t          |          z           ||<   !d | j                                        D             }t          |fi |S )z
        Infinite cyclic indexing of options over the integers,
        looping over the set of defined Cycle objects.
        r   c                 N    i | ]"\  }}t          |t                    ||j        #S r7   )r{   r   r^   rW   r   r   s      r    r  z'Options.__getitem__.<locals>.<dictcomp>%  s/    TTT1z!U?S?ST!AHTTTr8   c                 D    i | ]\  }}t          |t                    ||S r7   r  r  s      r    r  z'Options.__getitem__.<locals>.<dictcomp>*  s-    QQQ#!AJq%<P<PQ!AQQQr8   )r_   r   r	  r   )r@   indexcyclesoptionsr   r^   statics          r    r   zOptions.__getitem__  s    
 t{q  ITT(9(9(;(;TTT!<<>> 	7 	7KC!%#f++"56GCLLQQ!2!2!4!4QQQF&&g&&&r8   c                 >    | j         s| d         S t          d          )z:Access of the options keywords when no cycles are defined.r   z>The options property may only be used with non-cyclic Options.)r  r   rq   s    r    r  zOptions.options-  s.     { 	97N 8 9 9 9r8   c                     d                      fdt           j                                                  D                       }t	                     j        } j        r1 j        d                                         r|r| d j        d| dS  j        r, j        d                                         r| d j        dS | d| dS )NrS   c              3   <   K   | ]}| d j         |         V  dS =N)r   )rW   r   r@   s     r    r   z#Options.__repr__.<locals>.<genexpr>7  s7      VVa111t{1~11VVVVVVr8   r   r   r   )r`   r   r   r   r   r3   r   isupper)r@   r
  cls_names   `  r    r   zOptions.__repr__6  s    iiVVVV6$+BRBRBTBT;U;UVVVVV::&8 	(++-- 	(# 	(5555s5555X 	($(1+--// 	(......''''''r8   c                      t          |           S r<   rU   rq   s    r    rr   zOptions.__str__@  s    Dzzr8   )NNTNr<   )r3   r4   r5   r6   r   r   r   _output_allowed_kwsr?   r  r*   r   r   r   propertyr  r   r  r   rr   r7   r8   r    r~   r~     s         L
 L888N$+GK    @  	I 	I 	IF F F F0 0 0. . . K K XK' ' '  9 9 X9( ( (    r8   r~   c                   f     e Zd ZdZ	 	 ddZd Z fdZ fdZ fdZdd	Z	ddZ
ddZd Z xZS )
OptionTreea  
    A subclass of AttrTree that is used to define the inheritance
    relationships between a collection of Options objects. Each node
    of the tree supports a group of Options objects and the leaf nodes
    inherit their keyword values from parent nodes up to the root.

    Supports the ability to search the tree for the closest valid path
    using the find method, or compute the appropriate Options value
    given an object and a mode. For a given node of the tree, the
    options method computes a Options object containing the result of
    inheritance for a given group up to the root of the tree.

    When constructing an OptionTree, you can specify the option groups
    as a list (i.e. empty initial option groups at the root) or as a
    dictionary (e.g. groups={'style':Option()}). You can also
    initialize the OptionTree with the options argument together with
    the **kwargs - see StoreOptions.merge_options for more information
    on the options specification syntax.

    You can use the string specifier '.' to refer to the root node in
    the options specification. This acts as an alternative was of
    specifying the options groups of the current node. Note that this
    approach method may only be used with the group lists format.
    Nc                 D  	 |t          d          t          |t                    rd |D             n|}|| j        d<   || j        d<   d| j        d<   t	          j        | |||           d| j        d<   t          j        |                                |fi |}|	                    dd           		r>t          |t                    r)	fd	|                                D             | j        d<   n	rt          d
          |rt                              ||            d S d S )Nz'Please supply groups list or dictionaryc                 ,    i | ]}|t                      S r7   )r~   )rW   gs     r    r  z'OptionTree.__init__.<locals>.<dictcomp>d  s    ///11WYY///r8   r.   groupsF_instantiatedTrN   c                 R    i | ]#}|t          d i                     |i           $S r7   )r~   r   )rW   r,  root_groupss     r    r  z'OptionTree.__init__.<locals>.<dictcomp>o  s7    &b&b&baq)I)I;??1R3H3H)I)I&b&b&br8   zgGroup specification as a dictionary only supported if the root node '.' syntax not used in the options.)r   r{   r   __dict__r   r?   r   merge_optionsr   r   r   apply_customizations)
r@   r	  
identifierparentr-  r  r.   r   _groupsr1  s
            @r    r?   zOptionTree.__init___  sW    >FGGG3=fd3K3KW//////QW#*i ")h).o&$z6:::)-o&,W\\^^WOOOOkk#t,, 	:fd33 	&b&b&b&bSZS_S_SaSa&b&b&bDM(## 	D    	=--gt<<<<<	= 	=r8   c                    || j         vrt          d| d          || j        v r| |         }|j         |         }n!t          || j         |         j                  }t          |j                  }|j        }|j        |z   |d<   	 |j        r |di |S t          |fi |S # t          $ r(}t          |j	        |j        || j
                  |d}~ww xY w)z
        Computes a merged Options object for the given group
        name from the existing Options on the node and the
        new Options which are passed in.
        zGroup z not defined on SettingTree.rI   rI   )rJ   rK   Nr7   )r-  KeyErrorchildrenr~   rI   r   r   r   rF   rH   rK   )	r@   r5  rJ   r  current_nodegroup_optionsoverride_kwargsold_allowedr   s	            r    _merge_optionszOptionTree._merge_optionsx  s,    T[((LJLLLMMM&&
+L(/
;MM $T[-D-U  M w~..#4.5.F.T*+		7% >$}77777z==_=== 	7 	7 	7a/0)3%)Y0 0 0 677	7s   B" B" "
C,#CCc                 r    || j         v r| j         |         S t                                          |          S r<   )r-  r>   r   )r@   itemrB   s     r    r   zOptionTree.__getitem__  s5    4;;t$$ww""4(((r8   c                    	 t          t          |                               |          S # t          $ r Y nw xY w|                    d          rt          t          |                    | j        dk    rt          | j        |z            t          |d          }|| j	        v r| j
        |         S |                     |d | j                                        D                        | |         S )zx
        Allows creating sub OptionTree instances using attribute
        access, inheriting the group options.
        _TFescapec                 B    i | ]\  }}|t          ||j                   S )r9  r~   rI   r  s      r    r  z*OptionTree.__getattr__.<locals>.<dictcomp>  sD     &F &F &F*-!A '(ADV(W(W(W &F &F &Fr8   )r>   r   __getattr__AttributeError
startswithrn   fixed_fixed_errorr   r;  r2  __setattr__r-  r	  )r@   r5  valid_idrB   s      r    rI  zOptionTree.__getattr__  s   
	4((44Z@@@ 	 	 	D	   %% 	A Z111Z !2Z!?@@@&z%@@@t}$$=** 	 &F &F151B1B1D1D&F &F &F 	G 	G 	GJs   '+ 
88c                 P   i t           j        | j        <   t          |d          }i }t	          |t
                    r|}nt	          |t                    r|j        t          d          t	          |t                    r[|j        d         	                                r<d
                    d t          j        D                       }t          d| d          t	          |t                    r
|j        |i}nt	          |t                    r|j        }|| j        v r| |         n| }|j        D ]E}|                    |d          }|r|                     |||          ||<   5|j        |         ||<   F|r?|| j        v r| |                                         nd }	t          |	|| || j        	          }
nt%          d
          t'                                          ||
           t	          |t                    r&|D ]%}| |                             |j        |           $d S d S )NFrE  z4Options object needs to have a group name specified.r   rS   c              3   4   K   | ]}t          |          V  d S r<   rU   r   s     r    r   z)OptionTree.__setattr__.<locals>.<genexpr>  s(      IIBtBxxIIIIIIr8   z;OptionTree only accepts Options using keys that are one of rN   )r5  r6  r-  r.   z0OptionTree only accepts a dictionary of Options.)r   _lookup_cacher.   r   r{   r   r~   r   rJ  r#  r`   r   r)  r-  r;  r   r@  r	  r   r>   rN  r5  )r@   r5  r   
new_groupsgroup_itemsr-  r<  rJ   r  datanew_nodesubtreerB   s               r    rN  zOptionTree.__setattr__  so   ,.DL)(EBBB

c4   	%KKW%% 	%#'/ F   W%% 	%#'!**<*<*>*> 	%YYII'2HIIIIIF WfWWW   W%% 	%7C.KKZ(( 	%*K+5+F+FtJ''D&- 	I 	IJ!ooj%88G I)-)<)<ZU\)])]
:&&)5)<Z)H
:&& 	Q/9T]/J/J4
#))+++PTD!$:dS]gkgstttHHOPPPJ111c:&& 	J J JZ ,,W-?IIII	J 	JJ Jr8   r0   c                 4   t          |t                    r|                    d          nt          |          }| }|D ]Jt	          d          fd|j        D             }t          |d           }|r||d                  }JK|dk    r|n|j        S )	z
        Find the closest node or path to an the arbitrary path that is
        supplied down the tree from the given node. The mode argument
        may be either 'node' or 'path' which determines the return
        type.
        rN   FrE  c              3   p   K   | ]0}                     |          s                     |          ,|V  1d S r<   )endswith)rW   cchildescaped_childs     r    r   z"OptionTree.find.<locals>.<genexpr>  sh       !T !Tq$)NN1$5$5!T9F9O9OPQ9R9R!T !T !T !T !T !T !Tr8   c                 "    t          |            S r<   r_   xs    r    <lambda>z!OptionTree.find.<locals>.<lambda>  s    Q r8   r   r   r0   )r{   rn   splitr   r   r;  r   rK   )r@   rK   moderB  matching_childrenr\  r]  s        @@r    findzOptionTree.find  s     #-T3"7"7Gtzz#T$ZZ 	 	E/eDDDM!T !T !T !T !TDM !T !T !T &'8>O>O P P P  -a01v~~tt494r8   Tc                    |j         j        t          |j                  t	          |j                  f}|pt          j        }t          j        	                    |i           }|||t          | j                  fz   }||v r||         S d                    d |D                       }|                     |                              ||||          }	|	||<   |	S )a)  
        This method is designed to be called from the root of the
        tree. Given any LabelledData object, this method will return
        the most appropriate Options object, including inheritance.

        In addition, closest supports custom options by checking the
        object
        rN   c              3      K   | ]}||V  	d S r<   r7   rW   r[  s     r    r   z%OptionTree.closest.<locals>.<genexpr>  s'      44!4!444444r8   )r\   defaultsr.   )rB   r3   r	   r-   r
   labelr   ra   rR  r   r   rootr`   rg  r  )
r@   r,   r-   rk  r.   	opts_speccache	cache_keyr\   r  s
             r    closestzOptionTree.closest  s     M"CI&&CI&&
	 2U2#''44uh49>>	##44Y44444))I&&..&8W / F F"ir8   c           
      Z   || j         }| j                            |d          dS t                              |          }| j        |r| |ur|r~| j        j        }|t          |          t          |          k    rdndz   }|	                    |d          }|
                    |          }	|	|ur|	                    |          S t          S | j        | j        |         S | j                            ||||          }
t          di t          |
j        fi | j        |         j        S )z
        Using inheritance up to the root, get the complete Options
        object for the given node and the specified group.
        Nr.   r:   rN   r7   )rK   r-  r   r   r  r6  rB   r3   r_   replacerg  EMPTY_OPTIONSr~   r   r   )r@   r-   r\   rk  r.   r  	root_namereplacement
option_keymatchparent_optss              r    r  zOptionTree.options  s4   
 >YF;??5$''/4---00;6t7/B/B/B/I#S[[C	NN-J-JrrPSTKR88JLL,,EG##}}U+++$$[ ;u%%k))%7)SSOOk0NNDK4F4MNNOOOr8   c                    | j         d         }d\  }}d|dz  z   g }}|                                D ]v}g g }}||         j        i k    r"|                    d||         j        f           t	          |                                           D ]A\  }	}
|
j        |         j        }|                    d                    |	          |f           B|D ]@\  }	|dk    rt          fddD                       r'r|                    |	f           A|rd	 |D             }t          d
 |D                       t          |          dk    r|dz  nd|                    fd|D                       z   }|                    t          |          dk    rdnd|||fz             xd|                                 d|                    |           dS )z<
        Evalable representation of the OptionTree.
        r-  )z   z,

z,
   rN   r   c              3   H   K   | ]}                     |d           d u V  dS )FNr   )rW   r   r
  s     r    r   z&OptionTree.__repr__.<locals>.<genexpr>>  s6      (f(fE):):e)C(f(f(f(f(f(fr8   )axiswise	framewisec                     g | ]I\  }}|d d                     d t          |                                          D                        dfJS )zdict(rS   c              3   *   K   | ]\  }}| d | V  dS r!  r7   r  s      r    r   z1OptionTree.__repr__.<locals>.<listcomp>.<genexpr>E  s0      )U)UAQ****)U)U)U)U)U)Ur8   r   )r`   r   r	  )rW   tr
  s      r    rY   z'OptionTree.__repr__.<locals>.<listcomp>D  sh       3 X		)U)U		ATAT)U)U)U U UXXXY  r8   c              3   :   K   | ]\  }}t          |          V  d S r<   r_  )rW   r  rD  s      r    r   z&OptionTree.__repr__.<locals>.<genexpr>H  s,      99sqCFF999999r8   r   r:   c                 N    g | ]!\  }} |                                d | "S )z : )ljust)rW   r  r   r  seps      r    rY   z'OptionTree.__repr__.<locals>.<listcomp>J  s;    *`*`*`caPQc+I1775>>+I+Ia+I+I*`*`*`r8   z
%s%s={
%s}z	%s%s={%s}zOptionTree(groups=z
))r2  r   r   r   r   r	  r-  r`   allmaxr_   )r@   r-  tabgsepesepgspecsr-   especsaccumulatorr  r   r   
format_kwsentriesr
  r  r  s                 @@@r    r   zOptionTree.__repr__*  s,    x("	Ts1uf[[]] 	m 	mE"$bKFe}#r))""C)=#>???tzz||,, : :1%/""CHHQKK#89999' , ,C&==S(f(f(f(fMe(f(f(f%f%f= ,MM1c(+++ m "(  
 99j99999!$Z!!3!3s1uu		*`*`*`*`*`U_*`*`*` a aaJ0A0A}}{WZ\acjVkklllLFKKMMLLdii6G6GLLLLr8   )NNNNNN)r0   )TN)NTN)r3   r4   r5   r6   r?   r@  r   rI  rN  rg  rq  r  r   rC   rD   s   @r    r)  r)  E  s         2 <@48= = = =27 7 7B) ) ) ) )
         2(J (J (J (J (JT5 5 5 5*   6P P P P2#M #M #M #M #M #M #Mr8   r)  c                       e Zd ZdZ ej        dddgd          Z ej        g d          Z ej	        d	          Z
 ej        d
	          Z ej        dd          Z ej        d	          Z ej        dd          Z ej        dd          Zg Zg Zedd            Zedd            Zedd            Zed d            Zed             Z	 	 d! fd	Zed             Zd Zd ZddZ  xZ!S )"
Compositora  
    A Compositor is a way of specifying an operation to be automatically
    applied to Overlays that match a specified pattern upon display.

    Any Operation that takes an Overlay as input may be used to define a
    compositor.

    For instance, a compositor may be defined to automatically display
    three overlaid monochrome matrices as an RGB image as long as the
    values names of those matrices match 'R', 'G' and 'B'.
    rU  displayzW
      The mode of the Compositor object which may be either 'data' or
      'display'.)r   r   r   z:
      Defines which backends to apply the Compositor for.r   z8
       The Operation to apply when collapsing overlays.r   a  
       The overlay pattern to be processed. An overlay pattern is a
       sequence of elements specified by dotted paths separated by * .

       For instance the following pattern specifies three overlaid
       matrices with values of 'RedChannel', 'GreenChannel' and
       'BlueChannel' respectively:

      'Image.RedChannel * Image.GreenChannel * Image.BlueChannel.

      This pattern specification could then be associated with the RGB
      operation that returns a single RGB matrix for display.TzI
       The group identifier for the output of this particular compositorr   z<
       Optional set of parameters to pass to the operation.FzE
       Whether to transfer the options from the input to the output.zF
       Whether to transfer plot options which match to the operation.Nc                     fd| j         D             }d |D             }|g k    rdS t          |          d         S )a  
        Returns the single strongest matching compositor operation
        given an overlay. If no matches are found, None is returned.

        The best match is defined as the compositor operation with the
        highest match value as returned by the match_level method.
        c                 t    g | ]4}|j         k    |j        r	|j        v |                              |f5S r7   )re  backendsmatch_level)rW   opr.   re  overlays     r    rY   z.Compositor.strongest_match.<locals>.<listcomp>  sQ     
 
 
.0w$w"+7M7M ^^G$$b)7M7M7Mr8   c                 :    g | ]\  }}||d         ||d         fS )Nr   r   r7   )rW   ry  r  s      r    rY   z.Compositor.strongest_match.<locals>.<listcomp>  s;     
 
 
)4%  1Xr58$   r8   Nr   )definitionsr   )clsr  re  r.   match_strengthrb   s    ```  r    strongest_matchzCompositor.strongest_match  sx    
 
 
 
 
 
47O
 
 

 
8F
 
 
 b==4gq!!r8   c                    ddl m ddlmm} d}t          |          s ||g          }d}d}t          t                    	 |                     |||          }|1|r-t          |          dk    r|
                                d         S |S |\  }	\  }
}t          ||          r(|
                                } |||
|                   }n1|                                }|                    ||
|                   }|                    d	 g          }rMt          fd
|D                       r1|r-t          |          dk    r|
                                d         S |S                     |||          }j        r|                    j                  }t          ||          r|g}n0t          t%          |                                |g                    }xx         fd|D             z  cc<   |                    |d|
         |z   ||d         z             }fd}t)          |                    d |g                    }||k    r|S |})zA
        Finds any applicable compositor and applies it.
        r   )Element)CompositeOverlayOverlayFTr7   Nr   c                     | S r<   r7   r`  s    r    rb  z-Compositor.collapse_element.<locals>.<lambda>  s    a r8   c              3   ,   K   | ]}|         v V  d S r<   r7   )rW   r   applicable_op	processeds     r    r   z.Compositor.collapse_element.<locals>.<genexpr>  s-      $T$TR9]+C%C$T$T$T$T$T$Tr8   )r-   c                 J    g | ]}|                     d  g          D ]}| S )c                     | S r<   r7   r`  s    r    rb  z8Compositor.collapse_element.<locals>.<listcomp>.<lambda>  s    [\ r8   traverse)rW   r   r   r  s      r    rY   z/Compositor.collapse_element.<locals>.<listcomp>  s<    (i(i(iajjQ\Q\_f^gFhFh(i(i(i(i(i(ir8   c                 &    t          |            S r<   )r{   )ra  r  s    r    rb  z-Compositor.collapse_element.<locals>.<lambda>  s    Jq2B$C$C C r8   c                      t          |           S r<   r   r`  s    r    rb  z-Compositor.collapse_element.<locals>.<lambda>  s    r!uu r8   )elementr  r  r  r  r{   r   r   r  r_   r^   r	  cloner  r  applyr-   relabelzipr   tuple)r  r  rangesre  r.   r  unpackprev_idsry  rD  r   r   r^   slicedr	  resultspec_fnnew_idsr  r  r  r  s                     @@@@r    collapse_elementzCompositor.collapse_element  s   
 	%$$$$$66666666'#344 	gwi((GF%%	!	''w??E} /c'lla//">>++A..05-Q}t'7++ ; )) d
!344  veDj'9::OOKK';;E $T$T$T$T$Te$T$T$T!T!T  /c'lla//">>++A.."((AAF" Cm.ABB'7++ < c&++--&::;;m$$$(i(i(i(iV(i(i(ii$$$mmF6E6N6$9&-$GHHG DCCCGG,,__wiHHIIG(""HC!	r8   c                     | j         g k    r|S |                    d          }|r-t          |d         |j                                                  n|j                                        }|D ]\  }}|                     |||          ||<    |S )zL
        Given a map of Overlays, apply all applicable compositors.
        F)shared_datar   )r  r  r  rU  r^   r	  r  )r  holomapr  re  r  rU  r   r  s           r    collapsezCompositor.collapse  s     ?b  N %008>Xs6!9gl1133444GLDVDVDXDX  	E 	ELC--gvtDDE#JJr8   c                     ddl m} d  j        D             }d  j        D             }|r|                     fd|g          }d |D             }|r2|                    d |          r|                     fd|          }|S )	zs
        Applies compositor operations to any HoloViews element or container
        using the map method.
        r   r  c                 B    g | ]}t          |j                  d k    |S r   r_   _pattern_specrj  s     r    rY   z"Compositor.map.<locals>.<listcomp>  s-    WWWQS=Q=QUV=V=Vq=V=V=Vr8   c                 B    g | ]}t          |j                  d k    |S r  r  rj  s     r    rY   z"Compositor.map.<locals>.<listcomp>  s-    VVVQS=Q=QTU=U=Uq=U=U=Ur8   c                 4                         |           S N)re  r.   r  r,   r.   r  re  s    r    rb  z Compositor.map.<locals>.<lambda>      c&:&:3TSZ&:&[&[ r8   c                     g | ]	}|j         
S r7   patternrj  s     r    rY   z"Compositor.map.<locals>.<listcomp>  s    CCC!AICCCr8   c                     | S r<   r7   r`  s    r    rb  z Compositor.map.<locals>.<lambda>  s    ! r8   c                 4                         |           S r  r  r  s    r    rb  z Compositor.map.<locals>.<lambda>  r  r8   )r  r  r  mapr  )r  r,   re  r.   r  element_compositorsoverlay_compositorselement_patternss   ` ``    r    r  zCompositor.map  s     	.-----WW#/WWWVV#/VVV 	.''[[[[[[+,. .CCC/BCCC 	,3<<=M#N#N 	,''[[[[[[*, ,C
r8   c                 0   d | j         D             }|j        |v r2| j                             |                    |j                             | j                             |           |j        | j        vr!| j                            |j                   d S d S )Nc                     g | ]	}|j         
S r7   r  )rW   r  s     r    rY   z'Compositor.register.<locals>.<listcomp>  s    AAA2BJAAAr8   )r  r  r   r  r   	operation
operations)r  
compositordefined_patternss      r    registerzCompositor.register  s    AAAAA!111O 0 6 6z7I J JKKKz***s~55N!!*"677777 65r8   c	           
         g g c| _         |                    d          D ]}
t          d |
                                                    d          D                       }| j                             |           t          |          dk    r                    |d                    t                    dk    r*t          fdD                       st          d          t                    dk    rd	         | _        nd
| _        || _	        t                                          |||||pg |	||           d S )N*c              3   >   K   | ]}|                                 V  d S r<   )stripr   s     r    r   z&Compositor.__init__.<locals>.<genexpr>  s*      LLbrxxzzLLLLLLr8   rN      r|  r   c              3   0   K   | ]}|d          k    V  dS r   Nr7   )rW   llabelss     r    r   z&Compositor.__init__.<locals>.<genexpr>  s+      &D&Dq&)|&D&D&D&D&D&Dr8   z4Mismatched labels not allowed in compositor patternsr   r:   )r-   r  r  re  r  r   transfer_optionstransfer_parameters)r  rd  r  r  r   r_   r  r:  rl  _output_typer>   r?   )r@   r  r  r-   re  r  r  output_typer  r   rK   
path_tupler  rB   s               @r    r?   zCompositor.__init__  sV   %'"FMM#&& 	- 	-DLLDJJLL4F4Fs4K4KLLLLLJ%%j111:!##jm,,,v;;??3&D&D&D&DV&D&D&D#D#D?QRRR[[ADJJDJ'u!(#,""*.b &*:-@ 	 	B 	B 	B 	B 	Br8   c                 (    | j         p| j        j        S )zg
        Returns the operation output_type unless explicitly overridden
        in the kwargs.
        )r  r  r  rq   s    r    r  zCompositor.output_type  s      >DN$>>r8   c                    d}t          | j        |          D ]\  }}|d         t          |          j        k    r dS |dz  }t	          |          dk    r?|j        t          |j        d          g}|d         |v r|dz  }n dS t	          |          dk    r0|j        t          |j        d          g}|d         |v r|dz  } dS |S )z
        Find the match strength for a list of overlay items that must
        be exactly the same length as the pattern specification.
        r   Nr   FrE  r  r|  )	r  r  r   r3   r_   r-   r	   rl  r
   )r@   overlay_itemslevelspecr   r-   s         r    _slice_match_levelzCompositor._slice_match_level  s    
 D.>> 	  	 HD"Aw$r((+++ttQJE4yyA~~xXrxFFFGEAw%!-1TT4yyA~~?28E#J#J#JKGu$$QJEE44  r8   c                 L   t          | j                  }|t          |          k    rdS d\  }}t          t          |          |z
  dz             D ]H}|                                |||z            }|                     |          }|9||k    r	|}|||z   f}I|dk    r||fndS )a0  
        Given an overlay, return the match level and applicable slice
        of the overall overlay. The level an integer if there is a
        match or None if there is no match.

        The level integer is the number of matching components. Higher
        values indicate a stronger match.
        Nr  r   r   )r_   r  r   r^   r  )r@   r  slice_widthbest_lvlmatch_sliceioverlay_slicelvls           r    r  zCompositor.match_level4  s     $,--W%%dd !*+s7||K/122 	1 	1A#NN,,Qq}_=M))-88C{HX~~ !K-0*2a--+&&TAr8   c                     ddl m} |t          j        }d  j                                        D             }t          ||          rt          |          dk    ru|                                d         } j	        rTt          
                    ||d          j        }|                     fd|                                D                          j        |fd|i|} j        r ||urt                              |||           |S )	zP
        Apply the compositor on the input with the given input ranges.
        r   r  Nc                 &    i | ]\  }}|d k    ||S )r  r7   r  s      r    r  z$Compositor.apply.<locals>.<dictcomp>R  s(    MMM41a!}:L:L!Q:L:L:Lr8   r   r$   c                 8    i | ]\  }}|j         j        v ||S r7   )r  r+   )rW   r   r   r@   s      r    r  z$Compositor.apply.<locals>.<dictcomp>W  s8     = = =1"#t~';";";  !!";";";r8   input_ranges)r  r  r   ra   r   r	  r{   r_   r^   r  r)   updater  r  )r@   rl   r  r.   r  r   	plot_optstransformeds   `       r    r  zCompositor.applyL  s5    	.-----?e&;GMM4;#4#4#6#6MMMe-.. 	>3u::??LLNN1%E' >!00%HHO	 = = = =	0A0A = = = > > > %dnUPPPPP  	@U+%=%=""5+w???r8   r<   )NrU  N)NrU  )rU  N)FFNN)"r3   r4   r5   r6   r+   ObjectSelectorre  r   r  	Parameterr  r   r  r-   Dictr   r   r  r  r  r  classmethodr  r  r  r  r  r?   r'  r  r  r  r  rC   rD   s   @r    r  r  S  sn       
 
  5)/(; B  D
 uz" += > > >H   %; < < <I el  A B B BG ELD /L M M ME UZ ? @ @ @F %u}U 9H I I I (%- <I J J J JK" " " ["( . . . [.`    [    [" 8 8 [8 JOGKB B B B B B8 ? ? X?  0B B B0       r8   r  c                      e Zd ZdZi Zi ZdgZ ee          Z	i Z
i ZdZi Zg Zdi iZdZdZdZg Zed             Zedd            Zed             Zedd	            Zed
             Zed             Zedd            Zedd            Ze	 	 dd            Zedd            Zed             Zedd            Z edd            Z!edd            Z"ed             Z#ed             Z$dS )r   a<  
    The Store is what links up HoloViews objects to their
    corresponding options and to the appropriate classes of the chosen
    backend (e.g. for rendering).

    In addition, Store supports pickle operations that automatically
    pickle and unpickle the corresponding options for a HoloViews
    object.
    htmlFr   Nc                 >    | j         D ]} ||           || _        dS )z:Use this method to set the backend to run the switch hooksN)_backend_switch_hooksra   )r  r.   hooks      r    set_current_backendzStore.set_current_backend  s3     - 	 	DDMMMM%r8   c                 b    || j         n|}|| j        |         S i | j        |<   || j        |<   d S r<   )ra   r   rR  )r  r.   r   s      r    r  zStore.options  sD    )0#%%g;<(()+Cg&$'CL!!!r8   c                 N    t          | j                                                  S )zs
        Returns a list of the backends that have been loaded, based on
        the available OptionTrees.
        )r   r   r   r  s    r    r   zStore.loaded_backends  s      cl''))***r8   c                 N    || j         n|}|| j        |         S || j        |<   d S r<   )ra   r   )r  r   r.   s      r    custom_optionszStore.custom_options  s9    )0#%%g;&w//+.C(((r8   c                 x    t                                           | _        t          j        |          }d| _        |S )zn
        Equivalent to pickle.load except that the HoloViews trees is
        restored appropriately.
        N)r   	id_offsetload_counter_offsetpickleload)r  filenamer   s      r    r  z
Store.load  s4     #/"8"8":":k(##"&
r8   c                 x    t                                           | _        t          j        |          }d| _        |S )zo
        Equivalent to pickle.loads except that the HoloViews trees is
        restored appropriately.
        N)r   r  r  r  loads)r  pickle_stringr   s      r    r  zStore.loads  s4     #/"8"8":":l=))"&
r8   r   c                 P    d| _         t          j        |||           d| _         dS )zq
        Equivalent to pickle.dump except that the HoloViews option
        tree is saved appropriately.
        TprotocolFN)save_option_stater  dump)r  r,   filer  s       r    r  z
Store.dump  s1     !%C1111 %r8   c                 N    d| _         t          j        ||          }d| _         |S )zr
        Equivalent to pickle.dumps except that the HoloViews option
        tree is saved appropriately.
        Tr  F)r  r  dumps)r  r,   r  r   s       r    r  zStore.dumps  s-     !%l3222 %
r8   Tc                    |g }t          |t          j                  }t          |t                    ot	          |t          j                  }	d}
|s|	rt          j        ||||||          }
|rj|rh|                    d           }g }|dd         D ]E}||vr?t          j        |||||          }|rdnd}|
d||z  z   z  }
|                    |           F|
S )	z
        Show information about a particular object or component class
        including the applicable style and plot options. Returns None if
        the object is not parameterized.
        N)ansir.   visualizationr  elementsc                      t          |           S r<   )r   r`  s    r    rb  zStore.info.<locals>.<lambda>  s    tAww r8   r   )r   r.   r!  r  z[1;30m%s[0mz%sz

)	r{   r+   Parameterizedr   
issubclassr   r   r  r   )r  r,   r   r.   r!  	recursiver  r"  parameterized_objectparameterized_classr   	hierarchylistedr[  
inner_infoblacks                   r    r   z
Store.info  s8    H)#u/BCC)#d33  H$.s53F$G$G 	 	H#6 	H#CdG2?,3hH H HD   
	%I 
	%%6%677IFqrr] % %F??!,!1!$@M:A"C "C "CJ 6:C11tEVuz'9::DMM!$$$r8   c                     |j         | j        |         v r/| j        |         |j                                      ||||          S |st                      S | j        |                             ||||          S )Nrs  )r   r   rq  r~   r   )r  r.   r,   r-   rk  s        r    r)   zStore.lookup_options  s     6S(111&w/7??UHg @ 7 7 7 	X99<(00eXw0WWWr8   c                    d |                     d           D             }t          |          dk    rt          d          t          |          dk    r>d                    d t	          |          D                       }t          d|z            | j        |         t          t          |                             S )	z
        Given an object, lookup the corresponding customized option
        tree if a single custom tree is applicable.
        c                     h | ]}||S r<   r7   r   s     r    	<setcomp>zStore.lookup.<locals>.<setcomp>  s    KKKbBNrNNNr8   c                     | j         S r<   r  r`  s    r    rb  zStore.lookup.<locals>.<lambda>  s    14 r8   r   z)Object does not own a custom options treer   ,c                 ,    g | ]}t          |          S r7   r   r   s     r    rY   z Store.lookup.<locals>.<listcomp>  s    ===2s2ww===r8   zGObject contains elements combined across multiple custom trees (ids %s))r  r_   r   r`   r   r   nextr   )r  r.   r,   idsidlists        r    lookupzStore.lookup  s     LKCLL88KKKs88q==GHHHXX]]XX=====>>F =?EF G G G"7+DcOO<<r8   r  c                 p   ||u rdS || j         n|}t          |          j        }|j        t          |          j        k    r|n|j        }d                    d |||j        fd|         D                       }g }	t          j        D ]}|                     |||          }
|
s|                     |||d          }|r|j	        ni fd|
j	        
                                D             }|r |	                    t          |fi |           |	r t                              |||	i|           dS dS )z
        Transfers options for all backends from one object to another.
        Drops any options defined in the supplied drop list.
        NrN   c                     g | ]}||S r7   r7   )rW   ss     r    rY   z*Store.transfer_options.<locals>.<listcomp>  s    OOOqQOOOOr8   F)rk  c                 0    i | ]\  }}|v |v||S r<   r7   )rW   r   r   existingnamess      r    r  z*Store.transfer_options.<locals>.<dictcomp>'  sB     P P PA!MQ%ZZQh=N=N 1=N=N=Nr8   )ra   r   r3   r-   r`   rl  r~   r   r)   r   r	  r   r   set_options)r  r,   new_objr.   r=  r  	type_namer-   r  r  optsnew_optsr*   r<  s       `        @r    r  zStore.transfer_options  s    '>>F)0#%%gMM*	 Y$s))*<<<		#)xxOOYsy$A&5&$IOOOPP+ 		; 		;E%%gsE::D ))'7EE)RRH*2:xHP P P P P):):)<)< P P PH ;wu9999::: 	H$$WtWowGGGGG	H 	Hr8   c                    || j         n|}|| j        |         vrt          d|d          t          |t                    rt          d |D                       st          d          t          j        d          5  |D ]L}|| j        |         |         j        vr0| j        |         |         }t          |j        |gz             |_        M	 ddd           n# 1 swxY w Y   t          dd|	          | j        |         |j        <   dS )
ag  
        Given a component such as an Element (e.g. Image, Curve) or a
        container (e.g. Layout) specify new style options to be
        accepted by the corresponding plotting class.

        Note: This is supplied for advanced users who know which
        additional style keywords are appropriate for the
        corresponding plotting class.
        Nz
Component z$ not registered to a plotting class.c              3   @   K   | ]}t          |t                    V  d S r<   r   r   s     r    r   z'Store.add_style_opts.<locals>.<genexpr>?  s-      7b7bPR
2s8K8K7b7b7b7b7b7br8   z4Please supply a list of style option keyword stringsCRITICALr#   T)r   rI   )ra   registryr   r{   r   r  r+   logging_levelr'   r   r~   r   name)r  	componentnew_optionsr.   optionr/   s         r    add_style_optszStore.add_style_opts.  s    *1#%%gCL111NYNNN   +t,, 	C7b7bVa7b7b7b4b4b 	F    ,, 	S 	S% S Sg!6y!A!LLL!$g!6y!AJ,2:3H&3Q,R,RJ)S	S 	S 	S 	S 	S 	S 	S 	S 	S 	S 	S 	S 	S 	S 	S
 18D;1
 1
 1
Win---s   ?ACC #C c           
         i || j         vr
i | j         |<   | j         |                             |           t          j        }|| j        vrt          g ||          | j        |<   || j        vr
i | j        |<   | j         |                                         D ]C\  }fdj        D             }t          fd|j        z   D                       }t          d          rt          j                  n                                }d |D             }	t          j        d          5  |_        ddd           n# 1 swxY w Y   t          |	|j                  }	t          ||j                  }t          |		          t          t          j        	          t          |	          t          d
d
ddg          d}
|j        }|
| j        |         |<   EdS )z
        Register the supplied dictionary of associations between
        elements and plotting classes to the specified backend.
        Nr-  r.   c                 F    g | ]}                     |g           D ]}|S r7   r~  )rW   r   optstyle_aliasess      r    rY   z"Store.register.<locals>.<listcomp>`  sV     D D DS(5(9(9#r(B(BD D!$ ! D D D Dr8   c                 &    h | ]}|j         v|S r7   )_disabled_opts)rW   rP  r$   s     r    r0  z!Store.register.<locals>.<setcomp>b  s3     !G !G !G'*$2E'E'E "%'E'E'Er8   r+   c                     g | ]}|d v|	S ))rH  r7   )rW   r   s     r    rY   z"Store.register.<locals>.<listcomp>g  s"    @@@qax.?.?.?.?.?r8   rE  r   r9  Fr  r  )r  r  rI   )r$   r   r#   r   )rF  r  r~   r   r   r)  r   r	  r'   r   hasattrr   r+   r   rG  r   r3   r&  )r  associationsr.   rQ  r-  
view_classexpanded_optsr'   r   r  
opt_groupsrH  r$   s      `        @r    r  zStore.registerM  s     M#,&&$&CL!W$$\222'#,&&$.r&'$R$R$RCL!#---+-C( #W 5 ; ; = = 	5 	5JD D D DDO D D DM !G !G !G !G1P !G !G !G H HJ *1w)?)?RT$*%%%T[[]]F@@F@@@I$Z00 - -",- - - - - - - - - - - - - - - ")Z5HIIII!*Z5HIIIJ "9===!73NOOO!:>>>!EE4?3LN N N	 J &D*4CL!$''3	5 	5s   /EE	
E	c                 &    || j         |         |<   dS )z
        Specify a display hook that will be applied to objects of type
        objtype. The group specifies the set to which the display hook
        belongs, allowing the Store to compute the precedence within
        each group.
        N)_display_hooks)r  r-   objtyper  s       r    set_display_hookzStore.set_display_hookz  s     .25!'***r8   c                 f   t          j        t          |                    }g }| j                                        D ]+\  }}|D ]#} | |v r|                    ||                      n$,i i }}|D ]?} ||          }	|	|	\  }
}|                    |
           |                    |           @||fS )z
        Using any display hooks that have been registered, render the
        object to a dictionary of MIME types and metadata information.
        )inspectgetmror   r[  r	  r   r  )r  r,   class_hierarchyhooksrD  
type_hooksrU  metadatar  retdmds               r    renderzStore.render  s     ".c33 /5577 	 	MAz&  *$$LLC111E % Rh 	  	 D$s))C{EArKKNNNOOBX~r8   rg   )r   )Tr   TFNN)T)NNr  r<   )%r3   r4   r5   r6   r%   rF  display_formatsr   r   r[  r   r   r   rR  option_settersr   r  r  ra   r  r  r  r  r   r  r  r  r  r  r   r)   r7  r  rL  r  r]  rh  r7   r8   r    r   r   `  su         I H hO ![&&N H I M N $R(O"O& & [& ( ( ( [( + + [+ / / / [/   [   [ & & & [&    [ FJ59   [> X X X [X = = [= H H H [H2 
 
 
 [
< *5 *5 *5 [*5X 2 2 [2   [  r8   r   c                      e Zd ZdZdZed             Zed             Zed             Zed             Z	ed             Z
edd            Zed	             Zed
             Zed             Zedd            Zedd            Zed             Zedd            Zedd            Zedd            Zeedd                        Zed             Zedd            Zedd            ZdS )r   a  
    A collection of utilities for advanced users for creating and
    setting customized option trees on the Store. Designed for use by
    either advanced users or the %opts line and cell magics which use
    this machinery.

    This class also holds general classmethods for working with
    OptionTree instances: as OptionTrees are designed for attribute
    access it is best to minimize the number of methods implemented on
    that class and implement the necessary utilities on StoreOptions
    instead.

    Lastly this class offers a means to record all OptionErrors
    generated by an option specification. This is used for validation
    purposes.
    Nc                     g | _         dS )z~
        Start collecting OptionErrors for all skipped options recorded
        with the record_skipped_option method
        N)_errors_recordedr  s    r    start_recording_skippedz$StoreOptions.start_recording_skipped  s      "r8   c                 ^    | j         t          d          | j         dd         }d| _         |S )zu
        Stop collecting OptionErrors recorded with the
        record_skipped_option method and return them
        Nz*Cannot stop recording before it is started)rm  r   )r  recordeds     r    stop_recording_skippedz#StoreOptions.stop_recording_skipped  s:     'HIII'*#r8   c                 L    | j         | j                             |           dS dS )zh
        Record the OptionError associated with a skipped option if
        currently recording
        N)rm  r   )r  r  s     r    r   z"StoreOptions.record_skipped_option  s2     + ''..... ,+r8   c                 B    d |                     d           D             S )Nc                     h | ]}|S r7   r7   r   s     r    r0  z.StoreOptions.get_object_ids.<locals>.<setcomp>  s*     F F Fr F F Fr8   c                 $    t          | dd           S Nr   )getattrr`  s    r    rb  z-StoreOptions.get_object_ids.<locals>.<lambda>  s    WQd-C-C r8   r  r  r,   s     r    get_object_idszStoreOptions.get_object_ids  s9    F Fll#C#CDDF F F 	Fr8   c                     i }|                                 D ]Q}d                    |          }i ||<   ||         j        D ]'}||         j        |         j        }|r|||         |<   (R|S )zX
        Given an OptionTree, convert it into the equivalent dictionary format.
        rN   )r   r`   r-  r   )r  treespecsr   spec_keygrpr   s          r    tree_to_dictzStoreOptions.tree_to_dict  s    
  	2 	2Axx{{H E(OAw~ 2 2a,3 2+1E(OC(2 r8   c                     g fd}|                     |t          |          dhz             t                              |          vrt	          dz            S )z
        Recursively propagate an id through an object for components
        matching the applied_keys. This method can only be called if
        there is a tree with a matching id in Store.custom_options
        c                 z    | j         k    s| j        j        dk    r| _                             |            d S d S )N
DynamicMap)r   rB   r3   r   )oappliedmatch_idnew_ids    r    	propagatez-StoreOptions.propagate_ids.<locals>.propagate  sG    txAK$8L$H$Hq!!!!! %I$Hr8   r  )r|  rs  zINew option id %d does not match any option trees in Store.custom_options.)r  r   r   r  AssertionError)r  r,   r  r  applied_keysr.   r  r  s     ``   @r    propagate_idszStoreOptions.propagate_ids  s     	" 	" 	" 	" 	" 	" 	" 	Yc,&7&7<.&HIII --g->>>>  "I#)"* + + + r8   c                 .    |                     d           S )zq
        Given an list of ids, capture a list of ids that can be
        restored using the restore_ids.
        c                     | j         S r<   r  )r  s    r    rb  z*StoreOptions.capture_ids.<locals>.<lambda>  s    ad r8   r  rx  s     r    capture_idszStoreOptions.capture_ids  s     ||NN+++r8   c                 V    t                    |                    fd           dS )z
        Given an list of ids as captured with capture_ids, restore the
        ids. Note the structure of an object must not change between
        the calls to capture_ids and restore_ids.
        c                 @    t          | dt                              S rv  )setattrr4  )r  r5  s    r    rb  z*StoreOptions.restore_ids.<locals>.<lambda>  s    wq$S		:: r8   N)r   r  )r  r,   r5  s     `r    restore_idszStoreOptions.restore_ids  s2     3ii::::;;;;;r8   c                 f   t          |                                          D ]t          |         t          t          f          rd |         D             }n$d |                                         D             }fd|                                D             }||t                    <   |S )zL
        Apply the given option specs to the supplied options tree.
        c                     i | ]
}|j         |S r7   rc  r   s     r    r  z5StoreOptions.apply_customizations.<locals>.<dictcomp>  s     = = =a = = =r8   c                 \    i | ])\  }}|t          |t                    rt          d i |n|*S r0  )r{   r   r~   r  s      r    r  z5StoreOptions.apply_customizations.<locals>.<dictcomp>  sK     !? !? !?%(Qq "#Z45H5H%OW\\q\\\a !? !? !?r8   c                 t    i | ]4\  }}||                                         d           d                   5S rN   r   )r  rd  )rW   r   r   r   s      r    r  z5StoreOptions.apply_customizations.<locals>.<dictcomp>  sL     ? ? ?!$1  1 1#))C..2C D D ? ? ?r8   )r   r   r{   r   r  r	  rn   )r  r  r  customizationr   s       @r    r4  z!StoreOptions.apply_customizations  s    
 $))++&& 
	. 
	.C$s)dE]33 ? = =49 = = =!? !?,0IOO,=,=!? !? !?? ? ? ?(5(;(;(=(=? ? ?M -GCHHr8   c                 Z   |t                                           n|}i }t          t                    }|D ]}|                                  t          dd          5  t          t                               |          j        	                                t                               |          j
        |          }|                     ||           ddd           n# 1 swxY w Y   |                                 D ]D}|j        |j        j        |j        f}	|j        ||	|fz   <   ||	                             |           E|	                                D ]Q\  \  }
}}}t          |          t          |          k    r(|
||t           j        f}t'          |
|||                   RdS )av  
        Given a specification, validated it against the options tree for
        the specified backends by raising OptionError for invalid
        options. If backends is None, validates against all the
        currently loaded backend.

        Only useful when invalid keywords generate exceptions instead of
        skipping, i.e. Options.skip_invalid is False.
        NTF)r   r   r	  r-  r.   )rJ   rI   )r   r   r   r   rn  r   r)  r  rU  r	  r-  r4  rq  rH   rI   r\   rJ   addra   rF   )r  r  r  r   
error_infobackend_errorsr.   r  r  	error_keyr[   r\   rJ   r   s                 r    validate_speczStoreOptions.validate_spec#  s    6>5E%//1118
$S))& 	7 	7G'')))TFFF 8 8$--005;;== ==118#  
 ((w7778 8 8 8 8 8 8 8 8 8 8 8 8 8 8 3355 7 7"2"3:"-/	 493I
9gZ/0y)--g66667 :H9M9M9O9O 	D 	D5*gvzH8}}O 4 444
E4IJ!'-73=c?D D D D 5	D 	Ds   A5CC#	&C#	c                     	 |                      ||           dS # t          $ r}|                                cY d}~S d}~ww xY w)z
        Returns an options validation error message if there are any
        invalid keywords. Otherwise returns None.
        )r  N)r  rF   rf   )r  r  r  r   s       r    validation_error_messagez%StoreOptions.validation_error_messageL  sf    	,dX66666 	, 	, 	,))++++++++	,s    
A>AAc                     i }g }d t           j        D             }|                                D ]2\  }}||vr|||<   dg}||         }||t          |dz   |z             <   3||fS )z
        Expands compositor definition keys into {type}.{group}
        keys. For instance a compositor operation returning a group
        string 'Image' of element type RGB expands to 'RGB.Image'.
        c                 2    i | ]}|j         |j        j        S r7   )r-   r  r3   r   s     r    r  z7StoreOptions.expand_compositor_keys.<locals>.<dictcomp>`  s.     
 
 
24BHbn-
 
 
r8   r  rN   )r  r  r	  rn   )r  r  expanded_specr  compositor_defsr   r   r@  s           r    expand_compositor_keysz#StoreOptions.expand_compositor_keysW  s     
 
8B8N
 
 
 

 	< 	<HC/))%(c"" !*{+C0	8;c)C-"34455l**r8   c                 d    i g }}                      |          }                                 }t          |          dk    rdgn|}d D             }pt          j        t                                        }	i }
|	D ]6}||v r0|	|         j        }fd|                                D             |
|<   7t                                        }|D ]}|c||v r_||         }t          |                                |j        |j
                  }||||z   dz   <   |                    |||z   dz   f           n2t          |	j                  }|||<   |                    ||f           |
                                D ]
\  }}|||<    fd	|                                D             |fS )
a  
        Returns the appropriate set of customized subtree clones for
        an object, suitable for merging with Store.custom_options (i.e
        with the ids appropriately offset). Note if an object has no
        integer ids a new OptionTree is built.

        The id_mapping return value is a list mapping the ids that
        need to be matched as set to their new values.
        r   Nc                 F    g | ]}|                     d           d         fS r  )rd  )rW   rP  s     r    rY   z4StoreOptions.create_custom_trees.<locals>.<listcomp>}  s*    BBB3399S>>!,.BBBr8   rs  c                 D    i | ]\  }}|t          |j                   S ))rI   r.   rH  )rW   r~  rP  r.   s      r    r  z4StoreOptions.create_custom_trees.<locals>.<dictcomp>  sI     * * *
 #c	 ),)= '  * * *r8   r  r   rN  c                 L    i | ] \  }}|r                     |          n|!S r7   )r4  )rW   r   r  r  r  s      r    r  z4StoreOptions.create_custom_trees.<locals>.<dictcomp>  sI     + + +Aa 7I3++GQ777 + + +r8   )ry  r  r_   r   ra   r  r-  r	  r  r)  r.   r   )r  r,   r  r.   clones
id_mappingobj_idsoffsetused_obj_typesavailable_optionsused_optionsobj_typeopts_groupsr  tree_idoriginalr  rA  s   ` ``              r    create_custom_treesz StoreOptions.create_custom_treesm  s@     
$$S))LLA--4&&7BB'BBB2U2!MM'M::) 		 		H>))/9@* * * *
 '2&7&7&9&9* * *X& --g->> 	' 	'G"w.'@'@)'2""..**#?$,  
 05w'!+,!!7Gf,<q,@"ABBBB"*;*B+24 4 4!&v!!7F"3444 #/"4"4"6"6 ' '$"&h'+ + + + +!<<>>+ + +,67 	7r8   c                    t                    |*t          |                                          k    r|d}}nC|At          fd|D                       r&t          dd                               d          |i nt          di |}d |                                D             }|D ]}i }|                                D ](\  }}||v r||         }	|                    ||	i           )||vri ||<   |D ]E}
|
||         v r(||         |
                             ||
                    4||
         ||         |
<   F|S )a  
        Given a full options dictionary and options groups specified
        as a keywords, return the full set of merged options:

        >>> options={'Curve':{'style':dict(color='b')}}
        >>> style={'Curve':{'linewidth':10 }}
        >>> merged = StoreOptions.merge_options(['style'], options, style=style)
        >>> sorted(merged['Curve']['style'].items())
        [('color', 'b'), ('linewidth', 10)]
        Nc              3       K   | ]}|v V  	d S r<   r7   )rW   r   r-  s     r    r   z-StoreOptions.merge_options.<locals>.<genexpr>  s'      )G)G!!v+)G)G)G)G)G)Gr8   zAll keys must be a subset of rS   rN   c                     h | ]	}|D ]}|
S r7   r7   )rW   rf  r   s      r    r0  z-StoreOptions.merge_options.<locals>.<setcomp>  s%    :::!::1A::::r8   r7   )	r   r   r  r   r`   r   r^   r	  r  )r  r-  r  r   all_keysr}  	additionsr   rf  r
  r   s    `         r    r3  zStoreOptions.merge_options  s    VC$7$76$A$A%tGFF!c)G)G)G)Gw)G)G)G&G&G!F$))F2C2CFFF   !""tg::v}}:::  	< 	<HI . .1q==H+C$$aW---w&&$&!  < <'(+++H%c*11)C.AAAA-6s^GH%c**	<
 r8   c                    |Q|                      |          }t          t                                                                                    }||fS |\  }}t          t                                                                                    }|                    |          D ]2}t                                          |= |                     ||           3dS )a  
        Method to capture and restore option state. When called
        without any state supplied, the current state is
        returned. Then if this state is supplied back in a later call
        using the same object, the original state is restored.
        N)r  r   r   r  r   
differencer  )r  r,   stater5  original_custom_keyscurrent_custom_keysr   s          r    r  zStoreOptions.state  s     =//#&&C#&u';';'='='B'B'D'D#E#E -..*/'S&"%e&:&:&<&<&A&A&C&C"D"D*556JKK * *((**3/S))))* *r8   c              +     K   ||rvdt           _        |                     |          }t                                           j                                        } | j        ||fi |}|                     ||           	 dV  |%dt           _        |                     ||           dS dS # |$dt           _        |                     ||           w w xY w)a  
        Context-manager for temporarily setting options on an object
        (if options is None, no options will be set) . Once the
        context manager exits, both the object and the Store will be
        left in exactly the same state they were in before the context
        manager was used.

        See holoviews.core.options.set_options function for more
        information on the options specification format.
        NT)r  )r   r   r  r  r-  r   r3  r>  )r  r,   r  r   optstater-  s         r    r  zStoreOptions.options  s       F%)E"yy~~H]]__+0022F'c'BB6BBGOOC)))	/EEE")-&		#X	..... #"w")-&		#X	.... #s   >B+ +(Cc                 t   g }t           j                                        D ]x}t          t                               |                                                    }t          |          dk    rt          |          dz   nd}|                    |           yt          |          rt          |          ndS )z
        Compute an appropriate offset for future id values given the set
        of ids currently defined across backends.
        rs  r   r   )r   r%   r   r   r  r_   r  r   )r  max_idsr.   	store_idsmax_ids        r    r  zStoreOptions.id_offset  s     ++-- 	# 	#G U11'1BBGGIIJJI),Y!););S^^A%%FNN6"""""7||2s7|||2r8   c                 T   |t           j        n|}t                               |                              |           i t           j        |<   t                                           D ]@}||k    r	t           j        |         }|D ]"\  }}|                    |d          }||||<   #AdS )a  
        Given the id_mapping from previous ids to new ids and the new
        custom tree dictionary, update the current backend with the
        supplied trees and update the keys in the remaining backends to
        stay linked with the current object.
        Nrs  )r   ra   r  r  rR  r   r   r   )	r  r  custom_treesr.   rX   backend_treesold_idr  r{  s	            r    update_backendszStoreOptions.update_backends  s     ,3?%''W--44\BBB')G$ &&(( 	1 	1AG||!1!4M$. 1 1 $((66#,0M&)1		1 	1r8   c                    t                               |          j                                        } | j        ||fi |}|                     |          \  }}|                     |||          \  }}	|                     |	||           g }
|	D ]Z\  }}|t          |                                          z   }| 	                    |||||          }|s|

                    |           [t          |
          D ]}t          |           |S )a  
        Pure Python function for customize HoloViews objects in terms of
        their style, plot and normalization options.

        The options specification is a dictionary containing the target
        for customization as a {type}.{group}.{label} keys. An example of
        such a key is 'Image' which would customize all Image components
        in the object. The key 'Image.Channel' would only customize Images
        in the object that have the group 'Channel'.

        The corresponding value is then a list of Option objects specified
        with an appropriate category ('plot', 'style' or 'norm'). For
        instance, using the keys described above, the specs could be:

        {'Image:[Options('style', cmap='jet')]}

        Or setting two types of option at once:

        {'Image.Channel':[Options('plot', size=50),
                          Options('style', cmap='Blues')]}


        Relationship to the %%opts magic
        ----------------------------------

        This function matches the functionality supplied by the %%opts
        cell magic in the IPython extension. In fact, you can use the same
        syntax as the IPython cell magic to achieve the same customization
        as shown above:

        from holoviews.util.parser import OptsSpec
        set_options(my_image, OptsSpec.parse("Image (cmap='jet')"))

        Then setting both plot and style options:

        set_options(my_image, OptsSpec.parse("Image [size=50] (cmap='Blues')"))
        rs  )r   r  r-  r   r3  r  r  r  r   r  r   r   r!   )r  r,   r  r.   r   r-  r  compositor_appliedr  r  not_usedr  r  r   r  s                  r    r>  zStoreOptions.set_options  s:   X w//6;;==###FG>>v>>#&#=#=g#F#F  #&#:#:3g#:#V#V jJgFFF ", 	( 	(Xv$T$))++%6%66C''XvsG (  G  (''' (mm 	+ 	+F"6****
r8   r<   rg   )r3   r4   r5   r6   rm  r  rn  rq  r   ry  r  r  r  r  r4  r  r  r  r  r3  r  r   r  r  r  r>  r7   r8   r    r   r     sf        * " " [" 	 	 [	 / / [/ F F [F   [    [( , , [, < < [<   [" %D %D %D [%DP , , , [, + + [+* 47 47 47 [47l " " " ["J * * * [*$ / / / ^ [/2 3 3 [3 1 1 1 [1, ? ? ? [? ? ?r8   r   r<   )+r6   r   r_  r  rm   collectionsr   
contextlibr   numpyr   r+   	accessorsr   pprintr   r{  r   utilr	   r
   r   r!   r)   RuntimeErrorr2   r   r(   rF   ri   rw   r   r$  r   r   r   r   r~   r)  ru  r  r   r   r7   r8   r    <module>r     s  ! !D        # # # # # # % % % % % %                        G G G G G G G G G G   B  *    L   " " " " "I " " "9
 9
 9
 9
 9
) 9
 9
 9
xJ J J J J9 J J J:@ @ @ @ @ @ @ @ 
@ 
@ 
@6; 6; 6; 6; 6;u" 6; 6; 6;tA1 A1 A1 A1 A1E A1 A1 A1J     ?: ?: ?: ?: ?:e ?: ?: ?:FL L L L L L L L`HM HM HM HM HM HM HM HMV 		J J J J J$ J J JZz z z z z z z zz	B B B B B B B B B Br8   