Coverage for aixcalibuha/sensitivity_analysis/morris.py: 100%

25 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-01-27 10:48 +0000

1""" 

2Adds the MorrisAnalyzer to the available 

3classes of sensitivity analysis. 

4""" 

5import numpy as np 

6from SALib.sample import morris 

7from SALib.analyze import morris as analyze_morris 

8from aixcalibuha.sensitivity_analysis import SenAnalyzer 

9from aixcalibuha import CalibrationClass 

10 

11 

12class MorrisAnalyzer(SenAnalyzer): 

13 """ 

14 Moris method from SALib https://salib.readthedocs.io/en/latest/api.html#method-of-morris 

15 An elementary effects (One-At-A-Time) method which computes the sensitivity 

16 measures 'mu', 'mu_star' and 'sigma' with a confidence interval for mu_star. 

17 

18 Additional arguments: 

19 

20 :keyword int num_levels: 

21 Default num_samples, used for the morris-method 

22 :keyword optimal_trajectories: 

23 Used for the morris-method 

24 :keyword bool local_optimization: 

25 Default True, used for the morris-method 

26 """ 

27 def __init__(self, sim_api, **kwargs): 

28 super().__init__( 

29 sim_api=sim_api, 

30 **kwargs) 

31 # Set additional kwargs 

32 self.num_levels = kwargs.pop("num_levels", self.num_samples) 

33 self.optimal_trajectories = kwargs.pop("optimal_trajectories", None) 

34 self.local_optimization = kwargs.pop("local_optimization", True) 

35 

36 @property 

37 def analysis_variables(self): 

38 """The analysis variables of the sobol method""" 

39 return ['mu_star', 'mu', 'sigma', 'mu_star_conf'] 

40 

41 def analysis_function(self, x, y): 

42 """ 

43 Use the SALib.analyze.morris method to analyze the simulation results. 

44 

45 :param np.array x: 

46 the `X` parameter of the morris method (The NumPy matrix containing the model inputs) 

47 :param np.array y: 

48 The NumPy array containing the model outputs 

49 :return: 

50 returns the result of the SALib.analyze.sobol method (from the documentation: 

51 a dictionary with cols `mu`, `mu_star`, `sigma`, and `mu_star_conf`, where each 

52 entry is a list of size D (the number of parameters) containing the indices in the 

53 same order as the parameter file.) 

54 """ 

55 return analyze_morris.analyze(self.problem, x, y, 

56 num_levels=self.num_levels) 

57 

58 def create_sampler_demand(self): 

59 """ 

60 Function to create the sampler parameters for the morris method 

61 """ 

62 return {'num_levels': self.num_levels, 

63 'optimal_trajectories': self.optimal_trajectories, 

64 'local_optimization': self.local_optimization} 

65 

66 def generate_samples(self): 

67 """ 

68 Run the sampler specified for morris and return the results. 

69 

70 :return: 

71 The list of samples generated as a NumPy array with one row per sample 

72 and each row containing one value for each variable name in `problem['names']`. 

73 :rtype: np.ndarray 

74 """ 

75 return morris.sample(self.problem, 

76 N=self.num_samples, 

77 **self.create_sampler_demand()) 

78 

79 def _get_res_dict(self, result: dict, cal_class: CalibrationClass, analysis_variable: str): 

80 """ 

81 Convert the result object to a dict with the key 

82 being the variable name and the value being the result 

83 associated to self.analysis_variable. 

84 """ 

85 if result is None: 

86 names = cal_class.tuner_paras.get_names() 

87 return dict(zip(names, np.zeros(len(names)))) 

88 return dict(zip(result['names'], result[analysis_variable]))