def get_actual_temperature(fitter, Tmeas, Tmeas_err, cache=None, ret_cache=None, summarize=True): """ Get the actual temperature from the measured temperature :param fitter: a Bayesian_TLS instance which has already been fit :param Tmeas: the measured temperature. Either a float or a numpy array with independent temperatures :param Tmeas_err: uncertainty on the measured temperature. Same shape as Tmeas. :return: posterior samples for the actual temperature """ # First, build up a cache of the MCMC predicted measured temperatures for lots of actual temperatures if cache is None: logging.info('Generating cache...') Ta_arr = np.arange(2000, 10000, 1.0) Tmeas_pred = fitter.predict(Ta_arr, N=10000) cache = pd.DataFrame(Tmeas_pred, columns=Ta_arr) ret_cache = True if ret_cache is None else False del Tmeas_pred # Get the probability of each value in the cache Tmeas = np.atleast_1d(Tmeas).astype(np.float) Tmeas_err = np.atleast_1d(Tmeas_err).astype(np.float) def get_prob(Tm_pred, Tm, Tm_err): return np.exp(-((Tm_pred - Tm) / Tm_err)**2) probs = np.array([get_prob(cache.values, Tm, Tme) for Tm, Tme in zip(Tmeas, Tmeas_err)]) # Get the posterior probability distribution tmp = np.mean(probs, axis=1) tmp /= np.sum(tmp, axis=1)[:, np.newaxis] P = np.prod(tmp, axis=0) # Find the maximum and FWHM of the probabilities #best_T = cache.columns.values[np.argmax(P)] #roots = fwhm(cache.columns.values, P, k=0, ret_roots=True) #h, l = max(roots), min(roots) l, best_T, h = integral(cache.columns.values, P, [0.16, 0.5, 0.84], k=0) print('$T = {}^{{+{}}}_{{-{}}}$'.format(best_T, h-best_T, best_T-l)) # Return the requested things. if ret_cache: if summarize: return best_T, h - best_T, best_T - l, cache return cache.columns.values, P, cache if summarize: return best_T, h - best_T, best_T - l return cache.columns.values, P
def _correct(self, df, cache=True): """ This function is called by convert_measured_to_actual and is NOT meant to be called directly! It takes a pandas dataframe that all have the same star """ # Group by instrument and addmode, and get the PDF for the actual temperature for each df = df.dropna(subset=['Tmeas']) if len(df) == 0: df['Corrected_Temperature'] = np.nan df['T_uperr'] = np.nan df['T_lowerr'] = np.nan return df[['Star', 'Corrected_Temperature', 'T_uperr', 'T_lowerr']].copy() groups = df.groupby(('Instrument', 'addmode')) Probabilities = [] for (inst, addmode), group in groups: # Make a fitter instance d = {'instrument': inst, 'directory': self._caldir[inst], 'addmode': addmode} key = (inst, addmode) fitter = self._fitters[inst]() # get/set the cache if key in self._chainCache: chain, probs = self._chainCache[key] Tpredictions = self._predictionCache[key] fitter.spoof_sampler(chain, probs) else: chain = np.loadtxt(self._flatchain_format.format(**d)) probs = np.loadtxt(self._flatlnprob_format.format(**d)) fitter.spoof_sampler(chain, probs) Ta_arr = np.arange(2000, 12000, 2.0) Tmeas_pred = fitter.predict(Ta_arr, N=10000) Tpredictions = pd.DataFrame(Tmeas_pred, columns=Ta_arr) if cache: self._chainCache[key] = (chain, probs) self._predictionCache[key] = Tpredictions # Get the PDF (probability distribution function) Tmeas = group['Tmeas'].values Tmeas_err = group['Tmeas_err'].values for Tm, Tm_err in zip(Tmeas, Tmeas_err): temperature, probability = CCF_Systematics.get_actual_temperature(fitter, Tm, Tm_err, cache=Tpredictions, summarize=False) Probabilities.append(probability / probability.sum()) # Multiply all the PDFs Prob = np.array(Probabilities).prod(axis=0) # Summarize the PDF (similar interface to np.percentile) l, m, h = integral(temperature, Prob, [0.16, 0.5, 0.84], k=0) # Save in a Pandas DataFrame and return return pd.DataFrame(data={'Star': df['Star'].values[0], 'Corrected_Temperature': m, 'T_uperr': h - m, 'T_lowerr': m - l}, index=[0])