@@ -2538,262 +2538,6 @@ def __exit__(self, exc_type, exc_value, traceback):
2538
2538
pass
2539
2539
2540
2540
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
-
2797
2541
def _topmost_artist (
2798
2542
artists ,
2799
2543
_cached_max = functools .partial (max , key = operator .attrgetter ("zorder" ))):
0 commit comments