Coverage for pesummary/core/file/_lazy/base.py: 0.0%

90 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-11-05 13:38 +0000

1# Licensed under an MIT style license -- see LICENSE.md 

2 

3import numpy as np 

4from ....utils.parameters import Parameters 

5 

6__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"] 

7 

8 

9class _LazyRead(object): 

10 """Base class for a lazy read object 

11 

12 Parameters 

13 ---------- 

14 drop_non_numeric: bool, optional 

15 if True, remove all non_numeric values from the posterior samples 

16 table 

17 remove_nan_likelihood_samples: bool, optional 

18 if True. remove all rows in the posterior samples table that have 'nan' 

19 likelihood 

20 

21 Attributes 

22 ---------- 

23 parameters: pesummary.utils.parameters.Parameters 

24 list of parameters in the posterior samples table 

25 samples: np.ndarray 

26 2D array of samples in the posterior samples table 

27 samples_dict: pesummary.utils.samples_dict.SamplesDict 

28 dictionary displaying the posterior samples table. 

29 """ 

30 def __init__( 

31 self, *args, drop_non_numeric=True, remove_nan_likelihood_samples=True, 

32 **kwargs 

33 ): 

34 super().__init__(*args, **kwargs) 

35 self.mcmc_samples = False 

36 self.drop_non_numeric = drop_non_numeric 

37 self.remove_nan_likelihood_samples = remove_nan_likelihood_samples 

38 

39 @property 

40 def parameters(self): 

41 if not hasattr(self, "_parameters"): 

42 _ = self.samples 

43 self._parameters = [str(i) for i in self._parameters] 

44 return Parameters(self._parameters) 

45 

46 @property 

47 def samples(self): 

48 if hasattr(self, "_samples"): 

49 return self._samples 

50 self.grab_samples_from_file() 

51 if not self._is_array: 

52 self._convert_samples_to_array() 

53 if self.drop_non_numeric: 

54 self.remove_non_numeric_values_from_samples() 

55 if self.remove_nan_likelihood_samples: 

56 self.remove_nan_likelihood_values_from_samples() 

57 return self._samples 

58 

59 @property 

60 def _is_array(self): 

61 if not np.issubdtype(type(self._samples[0]), np.number): 

62 return True 

63 return False 

64 

65 def _convert_samples_to_array(self): 

66 self._samples_dict = { 

67 key: [item] for key, item in self.samples_dict.items() 

68 } 

69 

70 def remove_non_numeric_values_from_samples(self): 

71 numeric_cols = [] 

72 for i in range(self._samples.shape[1]): 

73 try: 

74 original_dtype = self._samples[:, i].dtype 

75 # this will fail if non-numeric dtype 

76 self._samples[:, i].astype(np.complex128) 

77 numeric_cols.append(i) 

78 self._samples[:, i].astype(original_dtype) 

79 except (ValueError, TypeError): 

80 from pesummary.utils.utils import logger 

81 logger.warning( 

82 f"Removing '{self._parameters[i]}' from the posterior " 

83 f"table as it contains non-numeric values. To prevent " 

84 f"this, pass 'drop_non_numeric=False' when loading the " 

85 f"file." 

86 ) 

87 continue 

88 if not len(numeric_cols): 

89 self._parameters = [] 

90 self._samples = [] 

91 else: 

92 self._parameters = self._parameters[numeric_cols] 

93 self._samples = self._samples[:, numeric_cols] 

94 

95 def remove_nan_likelihood_values_from_samples(self): 

96 if "log_likelihood" not in self._parameters: 

97 return 

98 ind = self.parameters.index("log_likelihood") 

99 likelihoods = self._samples[:,ind] 

100 inds = np.isnan(likelihoods) 

101 if not sum(inds): 

102 return 

103 msg = ( 

104 f"Posterior table contains {sum(inds)} samples with 'nan' log " 

105 f"likelihood. " 

106 ) 

107 msg += "Removing samples from posterior table." 

108 logger.warn(msg) 

109 self._samples = self._samples[~inds,:] 

110 

111 @property 

112 def samples_dict(self): 

113 # if samples_dict has already been initialized, use this 

114 if hasattr(self, "_samples_dict"): 

115 return self._samples_dict 

116 return self._generate_samples_dict() 

117 

118 def _generate_samples_dict(self): 

119 from pesummary.utils.samples_dict import ( 

120 SamplesDict, MCMCSamplesDict 

121 ) 

122 if self.mcmc_samples: 

123 return MCMCSamplesDict( 

124 self.parameters, [np.array(i).T for i in self.samples] 

125 ) 

126 return SamplesDict(self.parameters, np.array(self.samples).T) 

127 

128 def __repr__(self): 

129 return self.summary() 

130 

131 def _parameter_summary(self, parameters, parameters_to_show=4): 

132 """Return a summary of the parameter stored 

133 

134 Parameters 

135 ---------- 

136 parameters: list 

137 list of parameters to create a summary for 

138 parameters_to_show: int, optional 

139 number of parameters to show. Default 4. 

140 """ 

141 params = parameters 

142 if len(parameters) > parameters_to_show: 

143 params = parameters[:2] + ["..."] + parameters[-2:] 

144 return ", ".join(params) 

145 

146 def summary( 

147 self, parameters_to_show=4, show_parameters=True, show_nsamples=True 

148 ): 

149 """Return a summary of the contents of the file 

150 

151 Parameters 

152 ---------- 

153 parameters_to_show: int, optional 

154 number of parameters to show. Default 4 

155 show_parameters: Bool, optional 

156 if True print a list of the parameters stored 

157 show_nsamples: Bool, optional 

158 if True print how many samples are stored in the file 

159 """ 

160 string = "" 

161 if self.filename is not None: 

162 string += "file: {}\n".format(self.filename) 

163 string += "cls: {}.{}\n".format( 

164 self.__class__.__module__, self.__class__.__name__ 

165 ) 

166 if show_nsamples: 

167 string += "nsamples: {}\n".format(len(self.samples)) 

168 if show_parameters: 

169 string += "parameters: {}".format( 

170 self._parameter_summary( 

171 self.parameters, parameters_to_show=parameters_to_show 

172 ) 

173 ) 

174 return string