@@ -2538,262 +2538,6 @@ def __exit__(self, exc_type, exc_value, traceback):
25382538 pass
25392539
25402540
2541- class _FuncInfo (object ):
2542- """
2543- Class used to store a function.
2544-
2545- """
2546-
2547- def __init__ (self , function , inverse , bounded_0_1 = True , check_params = None ):
2548- """
2549- Parameters
2550- ----------
2551-
2552- function : callable
2553- A callable implementing the function receiving the variable as
2554- first argument and any additional parameters in a list as second
2555- argument.
2556- inverse : callable
2557- A callable implementing the inverse function receiving the variable
2558- as first argument and any additional parameters in a list as
2559- second argument. It must satisfy 'inverse(function(x, p), p) == x'.
2560- bounded_0_1: bool or callable
2561- A boolean indicating whether the function is bounded in the [0,1]
2562- interval, or a callable taking a list of values for the additional
2563- parameters, and returning a boolean indicating whether the function
2564- is bounded in the [0,1] interval for that combination of
2565- parameters. Default True.
2566- check_params: callable or None
2567- A callable taking a list of values for the additional parameters
2568- and returning a boolean indicating whether that combination of
2569- parameters is valid. It is only required if the function has
2570- additional parameters and some of them are restricted.
2571- Default None.
2572-
2573- """
2574-
2575- self .function = function
2576- self .inverse = inverse
2577-
2578- if callable (bounded_0_1 ):
2579- self ._bounded_0_1 = bounded_0_1
2580- else :
2581- self ._bounded_0_1 = lambda x : bounded_0_1
2582-
2583- if check_params is None :
2584- self ._check_params = lambda x : True
2585- elif callable (check_params ):
2586- self ._check_params = check_params
2587- else :
2588- raise ValueError ("Invalid 'check_params' argument." )
2589-
2590- def is_bounded_0_1 (self , params = None ):
2591- """
2592- Returns a boolean indicating if the function is bounded in the [0,1]
2593- interval for a particular set of additional parameters.
2594-
2595- Parameters
2596- ----------
2597-
2598- params : list
2599- The list of additional parameters. Default None.
2600-
2601- Returns
2602- -------
2603-
2604- out : bool
2605- True if the function is bounded in the [0,1] interval for
2606- parameters 'params'. Otherwise False.
2607-
2608- """
2609-
2610- return self ._bounded_0_1 (params )
2611-
2612- def check_params (self , params = None ):
2613- """
2614- Returns a boolean indicating if the set of additional parameters is
2615- valid.
2616-
2617- Parameters
2618- ----------
2619-
2620- params : list
2621- The list of additional parameters. Default None.
2622-
2623- Returns
2624- -------
2625-
2626- out : bool
2627- True if 'params' is a valid set of additional parameters for the
2628- function. Otherwise False.
2629-
2630- """
2631-
2632- return self ._check_params (params )
2633-
2634-
2635- class _StringFuncParser (object ):
2636- """
2637- A class used to convert predefined strings into
2638- _FuncInfo objects, or to directly obtain _FuncInfo
2639- properties.
2640-
2641- """
2642-
2643- _funcs = {}
2644- _funcs ['linear' ] = _FuncInfo (lambda x : x ,
2645- lambda x : x ,
2646- True )
2647- _funcs ['quadratic' ] = _FuncInfo (np .square ,
2648- np .sqrt ,
2649- True )
2650- _funcs ['cubic' ] = _FuncInfo (lambda x : x ** 3 ,
2651- lambda x : x ** (1. / 3 ),
2652- True )
2653- _funcs ['sqrt' ] = _FuncInfo (np .sqrt ,
2654- np .square ,
2655- True )
2656- _funcs ['cbrt' ] = _FuncInfo (lambda x : x ** (1. / 3 ),
2657- lambda x : x ** 3 ,
2658- True )
2659- _funcs ['log10' ] = _FuncInfo (np .log10 ,
2660- lambda x : (10 ** (x )),
2661- False )
2662- _funcs ['log' ] = _FuncInfo (np .log ,
2663- np .exp ,
2664- False )
2665- _funcs ['log2' ] = _FuncInfo (np .log2 ,
2666- lambda x : (2 ** x ),
2667- False )
2668- _funcs ['x**{p}' ] = _FuncInfo (lambda x , p : x ** p [0 ],
2669- lambda x , p : x ** (1. / p [0 ]),
2670- True )
2671- _funcs ['root{p}(x)' ] = _FuncInfo (lambda x , p : x ** (1. / p [0 ]),
2672- lambda x , p : x ** p ,
2673- True )
2674- _funcs ['log{p}(x)' ] = _FuncInfo (lambda x , p : (np .log (x ) /
2675- np .log (p [0 ])),
2676- lambda x , p : p [0 ]** (x ),
2677- False ,
2678- lambda p : p [0 ] > 0 )
2679- _funcs ['log10(x+{p})' ] = _FuncInfo (lambda x , p : np .log10 (x + p [0 ]),
2680- lambda x , p : 10 ** x - p [0 ],
2681- lambda p : p [0 ] > 0 )
2682- _funcs ['log(x+{p})' ] = _FuncInfo (lambda x , p : np .log (x + p [0 ]),
2683- lambda x , p : np .exp (x ) - p [0 ],
2684- lambda p : p [0 ] > 0 )
2685- _funcs ['log{p}(x+{p})' ] = _FuncInfo (lambda x , p : (np .log (x + p [1 ]) /
2686- np .log (p [0 ])),
2687- lambda x , p : p [0 ]** (x ) - p [1 ],
2688- lambda p : p [1 ] > 0 ,
2689- lambda p : p [0 ] > 0 )
2690-
2691- def __init__ (self , str_func ):
2692- """
2693- Parameters
2694- ----------
2695- str_func : string
2696- String to be parsed.
2697-
2698- """
2699-
2700- if not isinstance (str_func , six .string_types ):
2701- raise ValueError ("'%s' must be a string." % str_func )
2702- self ._str_func = six .text_type (str_func )
2703- self ._key , self ._params = self ._get_key_params ()
2704- self ._func = self ._parse_func ()
2705-
2706- def _parse_func (self ):
2707- """
2708- Parses the parameters to build a new _FuncInfo object,
2709- replacing the relevant parameters if necessary in the lambda
2710- functions.
2711-
2712- """
2713-
2714- func = self ._funcs [self ._key ]
2715-
2716- if not self ._params :
2717- func = _FuncInfo (func .function , func .inverse ,
2718- func .is_bounded_0_1 ())
2719- else :
2720- m = func .function
2721- function = (lambda x , m = m : m (x , self ._params ))
2722-
2723- m = func .inverse
2724- inverse = (lambda x , m = m : m (x , self ._params ))
2725-
2726- is_bounded_0_1 = func .is_bounded_0_1 (self ._params )
2727-
2728- func = _FuncInfo (function , inverse ,
2729- is_bounded_0_1 )
2730- return func
2731-
2732- @property
2733- def func_info (self ):
2734- """
2735- Returns the _FuncInfo object.
2736-
2737- """
2738- return self ._func
2739-
2740- @property
2741- def function (self ):
2742- """
2743- Returns the callable for the direct function.
2744-
2745- """
2746- return self ._func .function
2747-
2748- @property
2749- def inverse (self ):
2750- """
2751- Returns the callable for the inverse function.
2752-
2753- """
2754- return self ._func .inverse
2755-
2756- @property
2757- def is_bounded_0_1 (self ):
2758- """
2759- Returns a boolean indicating if the function is bounded
2760- in the [0-1 interval].
2761-
2762- """
2763- return self ._func .is_bounded_0_1 ()
2764-
2765- def _get_key_params (self ):
2766- str_func = self ._str_func
2767- # Checking if it comes with parameters
2768- regex = r'\{(.*?)\}'
2769- params = re .findall (regex , str_func )
2770-
2771- for i , param in enumerate (params ):
2772- try :
2773- params [i ] = float (param )
2774- except ValueError :
2775- raise ValueError ("Parameter %i is '%s', which is "
2776- "not a number." %
2777- (i , param ))
2778-
2779- str_func = re .sub (regex , '{p}' , str_func )
2780-
2781- try :
2782- func = self ._funcs [str_func ]
2783- except (ValueError , KeyError ):
2784- raise ValueError ("'%s' is an invalid string. The only strings "
2785- "recognized as functions are %s." %
2786- (str_func , list (self ._funcs )))
2787-
2788- # Checking that the parameters are valid
2789- if not func .check_params (params ):
2790- raise ValueError ("%s are invalid values for the parameters "
2791- "in %s." %
2792- (params , str_func ))
2793-
2794- return str_func , params
2795-
2796-
27972541def _topmost_artist (
27982542 artists ,
27992543 _cached_max = functools .partial (max , key = operator .attrgetter ("zorder" ))):
0 commit comments