From 2085cacd8b32eae444e6b78bef2139cb1cbcf641 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Wed, 4 May 2016 23:00:24 +0800 Subject: calc_pei.py: try to estimate PEI error (FIXME/TODO) --- calc_pei.py | 104 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 26 deletions(-) (limited to 'calc_pei.py') diff --git a/calc_pei.py b/calc_pei.py index c8a79c1..bf49478 100755 --- a/calc_pei.py +++ b/calc_pei.py @@ -3,10 +3,10 @@ # # Aaron LI # Created: 2016-04-29 -# Updated: 2016-05-02 +# Updated: 2016-05-04 # -# TODO: -# * to calculate the PEI error +# FIXME/TODO: +# * come up a approach to estimate the PEI error # """ @@ -36,10 +36,10 @@ from matplotlib.figure import Figure from matplotlib.path import Path import matplotlib.patches as patches -from make_r500_regions import get_r500 +from info import get_r500 -__version__ = "0.3.1" -__date__ = "2016-05-02" +__version__ = "0.4.0" +__date__ = "2016-05-04" plt.style.use("ggplot") @@ -50,17 +50,15 @@ def calc_pei(data, r500, interp_np=101): of the lower-left part with respect to the total rectangle. Arguments: - * data: 3-column power spectrum data (frequency, power, power_err) + * data: (frequency, power) power spectrum data * r500: R500 value in unit of the inverse of the above "frequency" * interp_np: number of data points interpolated to calculate PEI """ - freqs = data[:, 0] - psd1d = data[:, 1] + freqs, psd1d = data # frequency values corresponding to 0.35R500 and 0.035R500 pei_fmin = 1.0 / (0.350 * r500) pei_fmax = 1.0 / (0.035 * r500) # switch to the logarithmic scale - # XXX: how to deal with the errors mask = (freqs > 0.0) x = np.log10(freqs[mask]) y = np.log10(psd1d[mask]) @@ -78,15 +76,55 @@ def calc_pei(data, r500, interp_np=101): area_below = scipy.integrate.trapz((y_interp-pei_ymin), x_interp) pei_value = area_below / area_total results = { - "area_total": area_total, - "area_below": area_below, - "pei_value": pei_value, - "pei_err": None, + "area_total": area_total, + "area_below": area_below, + "pei_value": pei_value, } data_interp_log10 = np.column_stack((x_interp, y_interp)) return (results, data_interp_log10) +def estimate_pei_error(data, r500, mctimes, verbose=False): + """ + Estimate the PEI error by Monte Carlo method. + + FIXME: + CANNOT randomize the PSD data and just invoke the `calc_pei()` to + calculate the PEI value, which may be vastly different to the original + *central* value, due to the possible significant change to the PEI + rectangle and PSD data points (large PSD errors). + """ + eps = 1.0e-30 + freqs = data[:, 0] + psd1d = data[:, 1] + psd1d_err = data[:, 2] + psd1d_err[psd1d_err < eps] = eps + r500, r500_err = r500 + if verbose: + print("Estimating PEI error by Monte Carlo (%d times) ..." % mctimes, + end="", flush=True) + pei_results = [] + for i in range(mctimes): + if verbose and i % 100 == 0: + print("%d..." % i, end="", flush=True) + psd1d_rand = np.random.normal(psd1d, psd1d_err) + r500_rand = np.random.normal(r500, r500_err) + pei = calc_pei(data=(freqs, psd1d_rand), r500=r500_rand) + pei_results.append(pei["pei_value"]) + pei_mean = np.mean(pei_results) + pei_err = np.std(pei_results) + pei_q25, pei_median, pei_q75 = np.percentile(pei_results, + q=(25, 50, 75)) + results = { + "pei_mean": pei_mean, + "pei_median": pei_median, + "pei_q25": pei_q25, + "pei_q75": pei_q75, + "pei_err": pei_err, + } + return results + + def plot_pei(data, data_interp_log10, info={}, ax=None, fig=None): """ Make a plot to visualize the PEI rectangular. @@ -158,6 +196,7 @@ def main(): default_infile = "psd.txt" default_outfile = "pei.json" default_infojson = "../*_INFO.json" + # default_mctimes = 1000 parser = argparse.ArgumentParser( description="Calculate the power excess index (PEI)", @@ -165,6 +204,13 @@ def main(): parser.add_argument("-V", "--version", action="version", version="%(prog)s " + "%s (%s)" % (__version__, __date__)) + # parser.add_argument("-v", "--verbose", dest="verbose", + # required=False, action="store_true", + # help="show verbose information") + # parser.add_argument("-m", "--mctimes", dest="mctimes", required=False, + # type=int, default=default_mctimes, + # help="number of MC times to estimate PEI error " + + # "(default: %d)" % default_mctimes) parser.add_argument("-j", "--json", dest="json", required=False, help="the *_INFO.json file " + "(default: find %s)" % default_infojson) @@ -193,23 +239,29 @@ def main(): name = info["Source Name"] obsid = int(info["Obs. ID"]) r500 = get_r500(info) - r500_kpc = r500["r500_kpc"] r500_pix = r500["r500_pix"] - kpc_per_pix = r500["kpc_per_pix"] + r500_err_pix = (abs(r500["r500EL_pix"]) + abs(r500["r500EU_pix"])) / 2 psd_data = np.loadtxt(args.infile) - pei, data_interp_log10 = calc_pei(psd_data, r500=r500_pix) + freqs = psd_data[:, 0] + psd1d = psd_data[:, 1] + pei, data_interp_log10 = calc_pei(data=(freqs, psd1d), r500=r500_pix) + # pei_err = estimate_pei_error(psd_data, r500=(r500_pix, r500_err_pix), + # mctimes=args.mctimes, verbose=args.verbose) pei_data = OrderedDict([ - ("name", name), - ("obsid", obsid), - ("r500_kpc", r500_kpc), - ("r500_pix", r500_pix), - ("kpc_per_pix", kpc_per_pix), - ("area_total", pei["area_total"]), - ("area_below", pei["area_below"]), - ("pei", pei["pei_value"]), - ("pei_err", pei["pei_err"]), + ("name", name), + ("obsid", obsid), + ("r500_pix", r500_pix), + ("r500_err_pix", r500_err_pix), + ("area_total", pei["area_total"]), + ("area_below", pei["area_below"]), + ("pei", pei["pei_value"]), + # ("pei_mean", pei_err["pei_mean"]), + # ("pei_median", pei_err["pei_median"]), + # ("pei_q25", pei_err["pei_q25"]), + # ("pei_q75", pei_err["pei_q75"]), + # ("pei_err", pei_err), ]) pei_data_json = json.dumps(pei_data, indent=2) print(pei_data_json) -- cgit v1.2.2