|
19 | 19 | from pint.toa import TOAs |
20 | 20 | from scipy.linalg import cho_solve, cholesky, solve_triangular |
21 | 21 | from scipy.optimize import minimize |
22 | | -from astropy import units as u |
23 | 22 |
|
24 | 23 | import pyvela |
25 | 24 |
|
@@ -174,25 +173,57 @@ def __init__( |
174 | 173 | if check: |
175 | 174 | self._check() |
176 | 175 |
|
| 176 | + def _check_cube(self, sample: np.ndarray, desc: str): |
| 177 | + try: |
| 178 | + lnl = self.lnlike(sample) |
| 179 | + if not np.isfinite(lnl): |
| 180 | + warnings.warn( |
| 181 | + f"Non-finite log-likelihood for {desc}. Check the prior definition/default values." |
| 182 | + ) |
| 183 | + except: |
| 184 | + warnings.warn( |
| 185 | + f"Error occurred while computing log-likelihood for {desc}. Check the prior definition/default values." |
| 186 | + ) |
| 187 | + |
177 | 188 | def _check(self): |
178 | | - """Check if the computations work with the default values.""" |
179 | | - cube = np.random.rand(self.ndim) |
180 | | - sample = self.prior_transform(cube) |
181 | | - print("sample: ", sample) |
182 | | - lnpr = self.lnprior(sample) |
183 | | - lnl = self.lnlike(sample) |
184 | | - lnp = self.lnpost(sample) |
185 | | - lnpv = self.lnpost_vectorized(np.array([sample])) |
186 | | - assert all(np.isfinite([lnpr, lnl, lnp])), ( |
187 | | - "The log-prior, log-likelihood, or log-posterior is non-finite at the default parameter values. " |
188 | | - "Please make sure that (1) default values are within the prior range, and (b) the default values " |
189 | | - "provide a phase-connected solution. If nothing is wrong, this may be a bug. Please report this." |
190 | | - ) |
191 | | - assert np.isclose(lnp, lnpv), ( |
192 | | - "The non-vectorized and vectorized versions of the log-posterior gives different results. " |
193 | | - "This is most likely a bug. Please report this." |
| 189 | + """Check if the computations work with the prior values.""" |
| 190 | + |
| 191 | + self._check_cube(self.default_params, "default parameter values") |
| 192 | + |
| 193 | + lnpr = self.lnprior(self.default_params) |
| 194 | + if not np.isfinite(lnpr): |
| 195 | + warnings.warn( |
| 196 | + "The log-prior is non-finite at the default parameter values. " |
| 197 | + "This is probably a mistake in the prior definition. Please check this." |
| 198 | + ) |
| 199 | + for ii, pname in enumerate(self.param_names): |
| 200 | + params_tuple = vl.read_params(self.model, self.default_params) |
| 201 | + param_prior = self.model.priors[ii] |
| 202 | + if not np.isfinite(vl.lnprior(param_prior, params_tuple)): |
| 203 | + warnings.warn( |
| 204 | + f"Log-prior is non-finite at the default value of {pname}." |
| 205 | + ) |
| 206 | + |
| 207 | + lnp = self.lnpost(self.default_params) |
| 208 | + lnpv = self.lnpost_vectorized(np.array([self.default_params])) |
| 209 | + if not np.isclose(lnp, lnpv): |
| 210 | + warnings.warn( |
| 211 | + "The non-vectorized and vectorized versions of the log-posterior give " |
| 212 | + "different results at the default parameter values. This is most likely " |
| 213 | + "a bug. Please report this." |
| 214 | + ) |
| 215 | + |
| 216 | + self._check_cube( |
| 217 | + self.prior_transform(np.repeat(0.5, self.ndim)), "prior median" |
194 | 218 | ) |
195 | 219 |
|
| 220 | + for ii, pname in enumerate(self.param_names): |
| 221 | + for q in [0.01, 0.99]: |
| 222 | + cube = np.repeat(0.5, self.ndim) |
| 223 | + cube[ii] = q |
| 224 | + sample = self.prior_transform(cube) |
| 225 | + self._check_cube(sample, f"{int(q*100)}th percentile of {pname}") |
| 226 | + |
196 | 227 | def lnlike(self, params: Iterable[float]) -> float: |
197 | 228 | """Compute the log-likelihood function""" |
198 | 229 | return vl.calc_lnlike(self.pulsar, params) |
|
0 commit comments