diff options
author | Aaron LI <aaronly.me@outlook.com> | 2016-04-29 16:14:43 +0800 |
---|---|---|
committer | Aaron LI <aaronly.me@outlook.com> | 2016-04-29 16:14:43 +0800 |
commit | 738fdcbb7b5108da820685b469f946599a526e7b (patch) | |
tree | d49c37af4b3082626cfd738e6447a094a69f5470 /calc_pei.py | |
parent | 744aa16e2f408f4660b2c8a143da0aa40bdf03e8 (diff) | |
download | cexcess-738fdcbb7b5108da820685b469f946599a526e7b.tar.bz2 |
calc_pei.py: new; calculate the power excess index (PEI)
Diffstat (limited to 'calc_pei.py')
-rwxr-xr-x | calc_pei.py | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/calc_pei.py b/calc_pei.py new file mode 100755 index 0000000..19e71bb --- /dev/null +++ b/calc_pei.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Aaron LI +# Created: 2016-04-29 +# Updated: 2016-04-29 +# +# TODO: +# * to calculate the PEI error +# * to save a plot with the rectangular and interpolation marked +# + +""" +Calculate the power excess index (PEI), which is defined the area ratio of +the lower-left part with respect to the total rectangulr, which is further +defined by the radial power spectrum and the scale of 0.035R500 and 0.35R500, +in the logarithmic space. + +Reference: +Zhang, C., et al. 2016, ApJ +""" + +__version__ = "0.1.0" +__date__ = "2016-04-29" + + +import sys +import glob +import argparse +import json +from collections import OrderedDict + +import numpy as np +import scipy as sp +import scipy.interpolate +import scipy.integrate + +from make_r500_regions import get_r500 + + +def calc_pei(data, r500, interp_np=101): + """ + Calculate the power excess index (PEI), which is defined the area ratio + of the lower-left part with respect to the total rectangulr. + + Arguments: + * data: 3-column power spectrum data (frequency, power, power_err) + * 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] + psd1d_err = data[:, 2] + # frequency values corresponding to 0.35R500 and 0.035R500 + f1 = 1.0 / (0.350 * r500) + f2 = 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]) + x1 = np.log10(f1) + x2 = np.log10(f2) + # interpolate the power spectrum + f_interp = sp.interpolate.interp1d(x, y, kind="cubic", assume_sorted=True) + y1 = f_interp(x1) + y2 = f_interp(x2) + if interp_np % 2 == 0: + # Simpson's rule requires an even number of intervals + interp_np += 1 + x_interp = np.linspace(x1, x2, num=interp_np) + y_interp = f_interp(x_interp) + # calculate the PEI + area_total = abs(x1 - x2) * abs(y1 - y2) + area_below = sp.integrate.simps((y_interp-y2), x_interp) + pei_value = area_below / area_total + results = { + "area_total": area_total, + "area_below": area_below, + "pei_value": pei_value, + "pei_err": None, + } + return results + + +def main(): + # default arguments + default_infile = "psd.txt" + default_outfile = "pei.json" + default_infojson = "../*_INFO.json" + + parser = argparse.ArgumentParser( + description="Calculate the power excess index (PEI)", + epilog="Version: %s (%s)" % (__version__, __date__)) + parser.add_argument("-V", "--version", action="version", + version="%(prog)s " + "%s (%s)" % (__version__, __date__)) + parser.add_argument("-j", "--json", dest="json", required=False, + help="the *_INFO.json file (default: find %s)" % default_infojson) + parser.add_argument("-i", "--infile", dest="infile", + required=False, default=default_infile, + help="input data of the radial power spectrum " + \ + "(default: %s)" % default_infile) + parser.add_argument("-o", "--outfile", dest="outfile", + required=False, default=default_outfile, + help="output json file to save the results " + \ + "(default: %s)" % default_outfile) + args = parser.parse_args() + + info_json = glob.glob(default_infojson)[0] + if args.json: + info_json = args.json + + json_str = open(info_json).read().rstrip().rstrip(",") + info = json.loads(json_str) + 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"] + + psd_data = np.loadtxt(args.infile) + pei = calc_pei(psd_data, r500=r500_pix) + + 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"]), + ]) + pei_data_json = json.dumps(pei_data, indent=2) + print(pei_data_json) + open(args.outfile, "w").write(pei_data_json+"\n") + + +if __name__ == "__main__": + main() + +# vim: set ts=4 sw=4 tw=0 fenc=utf-8 ft=python: # |