1.Using metalog distribution and tool from metalogsworkbook, I can fit for \mathrm{CDF}^{-1}(t;\,t_\mathrm{SFR}). Now the prior sampling is much faster and the first problem is solved.
def logpdf(t,t_sfr):
return np.piecewise(t,
[(t<=12.)&(t>10**0.23),
(t<=10**0.23)&(t>10**(-0.1)),
(t<=10**(-0.1))&(t>=0.)],
[lambda t: 4.5860*np.log10(t)**3 - 9.0617*np.log10(t)**2 + 1.8664*np.log10(t) - 1.0666,
lambda t: -35.7414*np.log10(t)**3 + 2.2133*np.log10(t)**2 + 3.8230*np.log10(t) -1.6314,
lambda t: np.log(0.178*t),
lambda t: -np.inf]
) - (12-t)/t_sfr - np.piecewise(t_sfr,
[(t_sfr>=4)&(t_sfr<=12)],
[lambda t_sfr: np.log(-3.75557 + 1/(0.221348 + 0.0538988*np.exp(-0.117341*t_sfr))-0.191343*np.exp(-1.00455*t_sfr) *np.sin(6.15789 - t_sfr)),
lambda t_sfr: np.inf])
#--------------------------------------------------------------------------------------------
coefficients_of_ai = pd.read_csv('fit_for_p(t_and_tsfr)/coeffofai.csv',header=None).to_numpy()
ai = []
for i in range(8):
ai.append(np.poly1d(coefficients_of_ai[i]))
def inv_cdf(u, t_sfr):
A = (u-0.5)
B = np.log(u/(1-u))
M = ai[0](t_sfr) + ai[1](t_sfr)*B + ai[2](t_sfr)*A*B + ai[3](t_sfr)*A + ai[4](t_sfr)*A**2 + ai[5](t_sfr)*A**2*B + ai[6](t_sfr)*A**3 + ai[7](t_sfr)*A**3*B
return (12.*np.exp(M))/(1+np.exp(M))
def random(t_sfr: float, rng= None, size= None,) -> np.ndarray | float:
return inv_cdf(rng.uniform(size=size),t_sfr)
#---------------------------------------------------------------
with pm.Model() as m:
t_sfr = 8.
t = pm.CustomDist(
't',
t_sfr,
logp=logpdf,
random=random,)
idata = pm.sample_prior_predictive(100000)
2. It turns out that I didn’t normalize the pdf properly: the normalization depends on t_\mathrm{sfr} and I just ignored it.
Thanks again for your help!