10
10
11
11
import matplotlib .pyplot as plt
12
12
import numpy as np
13
+ from copy import deepcopy
13
14
from scipy import integrate , linalg , optimize
14
15
15
16
try :
@@ -515,12 +516,16 @@ def set_discrete(
515
516
interpolation = "spline" ,
516
517
extrapolation = "constant" ,
517
518
one_by_one = True ,
519
+ mutate_self = True ,
518
520
):
519
- """This method transforms function defined Functions into list
520
- defined Functions. It evaluates the function at certain points
521
- (sampling range) and stores the results in a list, which is converted
522
- into a Function and then returned. The original Function object is
523
- replaced by the new one.
521
+ """This method discretizes a 1-D or 2-D Function by evaluating it at
522
+ certain points (sampling range) and storing the results in a list,
523
+ which is converted into a Function and then returned. By default, the
524
+ original Function object is replaced by the new one, which can be
525
+ changed by the attribute `mutate_self`.
526
+
527
+ This method is specially useful to change a dataset sampling or to
528
+ convert a Function defined by a callable into a list based Function.
524
529
525
530
Parameters
526
531
----------
@@ -544,18 +549,32 @@ def set_discrete(
544
549
one_by_one : boolean, optional
545
550
If True, evaluate Function in each sample point separately. If
546
551
False, evaluates Function in vectorized form. Default is True.
552
+ mutate_self : boolean, optional
553
+ If True, the original Function object source will be replaced by
554
+ the new one. If False, the original Function object source will
555
+ remain unchanged, and the new one is simply returned.
556
+ Default is True.
547
557
548
558
Returns
549
559
-------
550
560
self : Function
561
+
562
+ Notes
563
+ -----
564
+ 1. This method performs by default in place replacement of the original
565
+ Function object source. This can be changed by the attribute `mutate_self`.
566
+
567
+ 2. Currently, this method only supports 1-D and 2-D Functions.
551
568
"""
552
- if self .__dom_dim__ == 1 :
569
+ func = deepcopy (self ) if not mutate_self else self
570
+
571
+ if func .__dom_dim__ == 1 :
553
572
xs = np .linspace (lower , upper , samples )
554
- ys = self .get_value (xs .tolist ()) if one_by_one else self .get_value (xs )
555
- self .set_source (np .concatenate (([xs ], [ys ])).transpose ())
556
- self .set_interpolation (interpolation )
557
- self .set_extrapolation (extrapolation )
558
- elif self .__dom_dim__ == 2 :
573
+ ys = func .get_value (xs .tolist ()) if one_by_one else func .get_value (xs )
574
+ func .set_source (np .concatenate (([xs ], [ys ])).transpose ())
575
+ func .set_interpolation (interpolation )
576
+ func .set_extrapolation (extrapolation )
577
+ elif func .__dom_dim__ == 2 :
559
578
lower = 2 * [lower ] if isinstance (lower , (int , float )) else lower
560
579
upper = 2 * [upper ] if isinstance (upper , (int , float )) else upper
561
580
sam = 2 * [samples ] if isinstance (samples , (int , float )) else samples
@@ -564,22 +583,29 @@ def set_discrete(
564
583
ys = np .linspace (lower [1 ], upper [1 ], sam [1 ])
565
584
xs , ys = np .array (np .meshgrid (xs , ys )).reshape (2 , xs .size * ys .size )
566
585
# Evaluate function at all mesh nodes and convert it to matrix
567
- zs = np .array (self .get_value (xs , ys ))
568
- self .__interpolation__ = "shepard"
569
- self .__extrapolation__ = "natural"
570
- self .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
571
- return self
586
+ zs = np .array (func .get_value (xs , ys ))
587
+ func .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
588
+ func .__interpolation__ = "shepard"
589
+ func .__extrapolation__ = "natural"
590
+ else :
591
+ raise ValueError (
592
+ "Discretization is only supported for 1-D and 2-D Functions."
593
+ )
594
+ return func
572
595
573
596
def set_discrete_based_on_model (
574
- self , model_function , one_by_one = True , keep_self = True
597
+ self , model_function , one_by_one = True , keep_self = True , mutate_self = True
575
598
):
576
- """This method transforms the domain of Function instance into a list of
577
- discrete points based on the domain of a model Function instance. It
578
- does so by retrieving the domain, domain name, interpolation method and
579
- extrapolation method of the model Function instance. It then evaluates
580
- the original Function instance in all points of the retrieved domain to
581
- generate the list of discrete points that will be used for interpolation
582
- when this Function is called.
599
+ """This method transforms the domain of a 1-D or 2-D Function instance
600
+ into a list of discrete points based on the domain of a model Function
601
+ instance. It does so by retrieving the domain, domain name,
602
+ interpolation method and extrapolation method of the model Function
603
+ instance. It then evaluates the original Function instance in all
604
+ points of the retrieved domain to generate the list of discrete points
605
+ that will be used for interpolation when this Function is called.
606
+
607
+ By default, the original Function object is replaced by the new one,
608
+ which can be changed by the attribute `mutate_self`.
583
609
584
610
Parameters
585
611
----------
@@ -589,15 +615,17 @@ def set_discrete_based_on_model(
589
615
Must be a Function whose source attribute is a list (i.e. a list
590
616
based Function instance). Must have the same domain dimension as the
591
617
Function to be discretized.
592
-
593
618
one_by_one : boolean, optional
594
619
If True, evaluate Function in each sample point separately. If
595
620
False, evaluates Function in vectorized form. Default is True.
596
-
597
- keepSelf : boolean, optional
621
+ keep_self : boolean, optional
598
622
If True, the original Function interpolation and extrapolation
599
623
methods will be kept. If False, those are substituted by the ones
600
624
from the model Function. Default is True.
625
+ mutate_self : boolean, optional
626
+ If True, the original Function object source will be replaced by
627
+ the new one. If False, the original Function object source will
628
+ remain unchanged, and the new one is simply returned.
601
629
602
630
Returns
603
631
-------
@@ -645,40 +673,48 @@ def set_discrete_based_on_model(
645
673
646
674
Notes
647
675
-----
648
- 1. This method performs in place replacement of the original Function
649
- object source.
676
+ 1. This method performs by default in place replacement of the original
677
+ Function object source. This can be changed by the attribute `mutate_self` .
650
678
651
679
2. This method is similar to set_discrete, but it uses the domain of a
652
680
model Function to define the domain of the new Function instance.
681
+
682
+ 3. Currently, this method only supports 1-D and 2-D Functions.
653
683
"""
654
684
if not isinstance (model_function .source , np .ndarray ):
655
685
raise TypeError ("model_function must be a list based Function." )
656
686
if model_function .__dom_dim__ != self .__dom_dim__ :
657
687
raise ValueError ("model_function must have the same domain dimension." )
658
688
659
- if self .__dom_dim__ == 1 :
689
+ func = deepcopy (self ) if not mutate_self else self
690
+
691
+ if func .__dom_dim__ == 1 :
660
692
xs = model_function .source [:, 0 ]
661
- ys = self .get_value (xs .tolist ()) if one_by_one else self .get_value (xs )
662
- self .set_source (np .concatenate (([xs ], [ys ])).transpose ())
663
- elif self .__dom_dim__ == 2 :
693
+ ys = func .get_value (xs .tolist ()) if one_by_one else func .get_value (xs )
694
+ func .set_source (np .concatenate (([xs ], [ys ])).transpose ())
695
+ elif func .__dom_dim__ == 2 :
664
696
# Create nodes to evaluate function
665
697
xs = model_function .source [:, 0 ]
666
698
ys = model_function .source [:, 1 ]
667
699
# Evaluate function at all mesh nodes and convert it to matrix
668
- zs = np .array (self .get_value (xs , ys ))
669
- self .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
700
+ zs = np .array (func .get_value (xs , ys ))
701
+ func .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
702
+ else :
703
+ raise ValueError (
704
+ "Discretization is only supported for 1-D and 2-D Functions."
705
+ )
670
706
671
707
interp = (
672
- self .__interpolation__ if keep_self else model_function .__interpolation__
708
+ func .__interpolation__ if keep_self else model_function .__interpolation__
673
709
)
674
710
extrap = (
675
- self .__extrapolation__ if keep_self else model_function .__extrapolation__
711
+ func .__extrapolation__ if keep_self else model_function .__extrapolation__
676
712
)
677
713
678
- self .set_interpolation (interp )
679
- self .set_extrapolation (extrap )
714
+ func .set_interpolation (interp )
715
+ func .set_extrapolation (extrap )
680
716
681
- return self
717
+ return func
682
718
683
719
def reset (
684
720
self ,
0 commit comments