diff options
author | Aaron LI <aly@aaronly.me> | 2017-11-12 20:17:03 +0800 |
---|---|---|
committer | Aaron LI <aly@aaronly.me> | 2017-11-12 20:17:03 +0800 |
commit | 14ae753c7a7afeb81d89247e0f64411414c6959a (patch) | |
tree | dd4d16899bfa2fb3c49a616a834274cd0d488988 /astro/spectrum | |
parent | eef93f4e51afbc20ce6cf1180d67c870e762e42f (diff) | |
download | atoolbox-14ae753c7a7afeb81d89247e0f64411414c6959a.tar.bz2 |
crosstalk_deprojection.py: v0.6.0, report spectral data changes; many fixes
Diffstat (limited to 'astro/spectrum')
-rwxr-xr-x | astro/spectrum/crosstalk_deprojection.py | 361 |
1 files changed, 195 insertions, 166 deletions
diff --git a/astro/spectrum/crosstalk_deprojection.py b/astro/spectrum/crosstalk_deprojection.py index a7aa30a..8dd2a03 100755 --- a/astro/spectrum/crosstalk_deprojection.py +++ b/astro/spectrum/crosstalk_deprojection.py @@ -5,10 +5,12 @@ # # Change log: # 2017-11-12: -# * Various cleanups +# * Report spectrum data changes +# * Add 'regid' to identify spectrum/arf/rmf regions # * Add 'info_emin' and 'info_emax' configuration options -# * Remove command line arguments # * Add global configurations variable 'CONFIGS' +# * Remove command line arguments +# * Various cleanups # 2016-06-07: # * Explain the errors/uncertainties calculation approach # 2016-04-20: @@ -154,7 +156,7 @@ from astropy.io import fits from configobj import ConfigObj -__version__ = "0.5.6" +__version__ = "0.6.0" __date__ = "2017-11-12" WARNING = """ @@ -184,7 +186,7 @@ def group_data(data, grouping): else: # other channels of a group data_grp[i-1] += data_grp[i] - data_grp[i] = 0 + data_grp[i] = 0 assert np.isclose(sum(data_grp), sum(data)) return data_grp @@ -220,30 +222,31 @@ class ARF: # {{{ [2] Definition of RMF and ARF file formats https://heasarc.gsfc.nasa.gov/docs/heasarc/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.html """ - filename = None - # only consider the "SPECTRUM" extension - header = None - energ_lo = None - energ_hi = None - specresp = None # function of the interpolated ARF f_interp = None # energies of the spectral channels energy_channel = None # spectral channel grouping specification - grouping = None - groupped = False + grouping = None + groupped = False # groupped ARF channels with respect to the grouping - specresp_grp = None + specresp_grp = None - def __init__(self, filename): + def __init__(self, filename, regid=None): self.filename = filename + self.regid = regid with fits.open(filename) as fitsobj: ext_specresp = fitsobj["SPECRESP"] self.header = ext_specresp.header - self.energ_lo = ext_specresp.data["ENERG_LO"] - self.energ_hi = ext_specresp.data["ENERG_HI"] - self.specresp = ext_specresp.data["SPECRESP"] + self.energ_lo = ext_specresp.data["ENERG_LO"] # [keV] + self.energ_hi = ext_specresp.data["ENERG_HI"] # [keV] + self.specresp = ext_specresp.data["SPECRESP"] # [cm^2] + + def __str__(self): + if self.regid: + return self.regid + else: + return self.filename def get_data(self, groupped=False, group_squeeze=False, copy=True): if groupped: @@ -257,26 +260,26 @@ class ARF: # {{{ else: return specresp - def get_energy(self, mean="geometric"): + @property + def energy(self): """ Return the mean energy values of the ARF. + The geometric mean is adopted, i.e., e = sqrt(e_min*e_max) + Unit: [keV] + """ + return np.sqrt(self.energ_lo * self.energ_hi) - Arguments: - * mean: type of the mean energy: - + "geometric": geometric mean, i.e., e = sqrt(e_min*e_max) - + "arithmetic": arithmetic mean, i.e., e = 0.5*(e_min+e_max) - """ - if mean == "geometric": - energy = np.sqrt(self.energ_lo * self.energ_hi) - elif mean == "arithmetic": - energy = 0.5 * (self.energ_lo + self.energ_hi) + @property + def energy_groupped(self): + if self.groupped: + energy = self.energy + return energy[self.grouping == 1] else: - raise ValueError("Invalid mean type: %s" % mean) - return energy + return None def interpolate(self, x=None, verbose=False): """ - Cubic interpolate the ARF curve using `scipy.interpolate' + Interpolate the ARF curve using `scipy.interpolate' If the requested point is outside of the data range, the fill value of *zero* is returned. @@ -289,13 +292,12 @@ class ARF: # {{{ otherwise, the interpolated data are returned. """ if not hasattr(self, "f_interp") or self.f_interp is None: - energy = self.get_energy() arf = self.get_data(copy=False) if verbose: - print("INFO: interpolating ARF '%s' (may take a while) ..." % + print("INFO: Interpolating ARF '%s' (may take a while) ..." % self.filename, file=sys.stderr) f_interp = scipy.interpolate.interp1d( - energy, arf, kind="cubic", bounds_error=False, + self.energy, arf, kind="quadratic", bounds_error=False, fill_value=0.0, assume_sorted=True) self.f_interp = f_interp @@ -318,7 +320,7 @@ class ARF: # {{{ if self.groupped: return if verbose: - print("INFO: Grouping spectrum '%s' ..." % self.filename, + print("INFO: Grouping ARF '%s' ..." % self.filename, file=sys.stderr) self.energy_channel = energy_channel self.grouping = grouping @@ -363,33 +365,19 @@ class RMF: # {{{ [2] Definition of RMF and ARF file formats https://heasarc.gsfc.nasa.gov/docs/heasarc/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.html """ - filename = None - ## extension "MATRIX" - hdr_matrix = None - energ_lo = None - energ_hi = None - n_grp = None - f_chan = None - n_chan = None - # raw squeezed RMF matrix data - matrix = None - ## extension "EBOUNDS" - hdr_ebounds = None - channel = None - e_min = None - e_max = None - ## converted 2D RMF matrix/image from the squeezed binary table - # size: len(energ_lo) x len(channel) - rmfimg = None - - def __init__(self, filename): + # converted 2D RMF matrix/image from the squeezed binary table + # size: len(energ_lo) x len(channel) + rmfimg = None + + def __init__(self, filename, regid=None): self.filename = filename + self.regid = regid with fits.open(filename) as fitsobj: # "MATRIX" extension ext_matrix = fitsobj["MATRIX"] self.hdr_matrix = ext_matrix.header - self.energ_lo = ext_matrix.data["ENERG_LO"] - self.energ_hi = ext_matrix.data["ENERG_HI"] + self.energ_lo = ext_matrix.data["ENERG_LO"] # [keV] + self.energ_hi = ext_matrix.data["ENERG_HI"] # [keV] self.n_grp = ext_matrix.data["N_GRP"] self.f_chan = ext_matrix.data["F_CHAN"] self.n_chan = ext_matrix.data["N_CHAN"] @@ -398,25 +386,23 @@ class RMF: # {{{ ext_ebounds = fitsobj["EBOUNDS"] self.hdr_ebounds = ext_ebounds.header self.channel = ext_ebounds.data["CHANNEL"] - self.e_min = ext_ebounds.data["E_MIN"] - self.e_max = ext_ebounds.data["E_MAX"] + self.e_min = ext_ebounds.data["E_MIN"] # [keV] + self.e_max = ext_ebounds.data["E_MAX"] # [keV] + + def __str__(self): + if self.regid: + return self.regid + else: + return self.filename - def get_energy(self, mean="geometric"): + @property + def energy(self): """ Return the mean energy values of the RMF "EBOUNDS". - - Arguments: - * mean: type of the mean energy: - + "geometric": geometric mean, i.e., e = sqrt(e_min*e_max) - + "arithmetic": arithmetic mean, i.e., e = 0.5*(e_min+e_max) - """ - if mean == "geometric": - energy = np.sqrt(self.e_min * self.e_max) - elif mean == "arithmetic": - energy = 0.5 * (self.e_min + self.e_max) - else: - raise ValueError("Invalid mean type: %s" % mean) - return energy + The geometric mean is adopted, i.e., e = sqrt(e_min*e_max) + Unit: [keV] + """ + return np.sqrt(self.e_min * self.e_max) def get_rmfimg(self): """ @@ -436,7 +422,7 @@ class RMF: # {{{ # if self.rmfimg is None: # Make the 2D RMF matrix/image - n_energy = len(self.energ_lo) + n_energy = len(self.energ_lo) n_channel = len(self.channel) rmf_dtype = self.matrix[0].dtype rmfimg = np.zeros(shape=(n_energy, n_channel), dtype=rmf_dtype) @@ -454,7 +440,10 @@ class RMF: # {{{ header = self.hdr_matrix.copy(strip=True) header.extend(self.hdr_ebounds.copy(strip=True)) outfits = fits.PrimaryHDU(data=rmfimg, header=header) - outfits.writeto(outfile, checksum=True, clobber=clobber) + try: + outfits.writeto(outfile, checksum=True, overwrite=clobber) + except TypeError: + outfits.writeto(outfile, checksum=True, clobber=clobber) # class RMF }}} @@ -729,7 +718,10 @@ class Spectrum: # {{{ header=self.header) # Replace the original spectrum data fitsobj["SPECTRUM"] = ext_spec - fitsobj.writeto(outfile, clobber=clobber, checksum=True) + try: + fitsobj.writeto(outfile, overwrite=clobber, checksum=True) + except TypeError: + fitsobj.writeto(outfile, clobber=clobber, checksum=True) # class Spectrum }}} @@ -796,7 +788,8 @@ class SpectrumSet(Spectrum): # {{{ outfile = self.outfile super().write(outfile=outfile, clobber=clobber) - def get_energy(self, mean="geometric"): + @property + def energy(self): """ Get the energy values of each channel if RMF present. @@ -810,7 +803,15 @@ class SpectrumSet(Spectrum): # {{{ if self.rmf is None: return None else: - return self.rmf.get_energy(mean=mean) + return self.rmf.energy + + @property + def energy_groupped(self): + energy = self.energy + if self.groupped and energy is not None: + return energy[self.grouping == 1] + else: + return None def get_arf(self, groupped=True, copy=True): """ @@ -827,7 +828,7 @@ class SpectrumSet(Spectrum): # {{{ else: return self.arf.get_data(groupped=groupped, copy=copy) - def read_xflt(self): + def read_xflt(self, verbose=False): """ Read the XFLT000# keywords from the header, check the validity (e.g., "XFLT0001" should equals "XFLT0002", "XFLT0003" should equals 0). @@ -857,8 +858,10 @@ class SpectrumSet(Spectrum): # {{{ # if NO additional XFLT000# keys exist, assume "annulus" region if self.angle < eps: self.angle = 360.0 + if verbose: + print("[%s] region angle: %.2f [deg]" % (str(self), self.angle)) - def scale(self): + def scale(self, verbose=False): """ Scale the spectral data (and spectral group errors if present) of the source spectrum (and background spectra if present) according @@ -870,14 +873,17 @@ class SpectrumSet(Spectrum): # {{{ The spectral data and errors (i.e., `self.spec_data', and `self.spec_err') is MODIFIED! """ - self.spec_data *= (360.0 / self.angle) + factor = 360.0 / self.angle + if verbose: + print("[%s] region scale factor: %.2f" % (str(self), factor)) + self.spec_data *= factor if self.spec_err is not None: - self.spec_err *= (360.0 / self.angle) + self.spec_err *= factor # also scale the background spectrum if present if self.bkg: - self.bkg.spec_data *= (360.0 / self.angle) + self.bkg.spec_data *= factor if self.bkg.spec_err is not None: - self.bkg.spec_err *= (360.0 / self.angle) + self.bkg.spec_err *= factor def apply_grouping(self, grouping=None, quality=None, verbose=False): """ @@ -894,7 +900,7 @@ class SpectrumSet(Spectrum): # {{{ """ super().apply_grouping(grouping=grouping, quality=quality) # also group the ARF accordingly - self.arf.apply_grouping(energy_channel=self.get_energy(), + self.arf.apply_grouping(energy_channel=self.energy, grouping=self.grouping, verbose=verbose) # group the background spectrum if present if self.bkg: @@ -944,12 +950,16 @@ class SpectrumSet(Spectrum): # {{{ (self.filename, ratio, self.bkg.filename)) if verbose: print(operation, file=sys.stderr) - datasum1 = np.sum(self.spec_data) + energy = self.energy + eidx = ((energy >= CONFIGS["info_emin"]) & + (energy <= CONFIGS["info_emax"])) + datasum1 = np.sum(self.spec_data[eidx]) spec_data_subbkg = self.spec_data - ratio * self.bkg.get_data() - datasum2 = np.sum(spec_data_subbkg) + datasum2 = np.sum(spec_data_subbkg[eidx]) datacp = 100 * (datasum2-datasum1) / datasum1 - print("[%s] bkg subtraction: %g -> %g (%.2f%%)" % - (str(self), datasum1, datasum2, datacp)) + if verbose: + print("[%s] bkg subtraction: %g -> %g (%.2f%%)" % + (str(self), datasum1, datasum2, datacp)) if inplace: self.spec_data = spec_data_subbkg self.spec_bkg_subtracted = True @@ -987,7 +997,7 @@ class SpectrumSet(Spectrum): # {{{ spectrumset.filename) if verbose: print(operation, file=sys.stderr) - energy = self.get_energy() + energy = self.energy if groupped: spectrumset.arf.apply_grouping(energy_channel=energy, grouping=self.grouping, @@ -1007,9 +1017,19 @@ class SpectrumSet(Spectrum): # {{{ arf_ratio = arfresp_cross / arfresp_spec # fix nan/inf values due to division by zero arf_ratio[~np.isfinite(arf_ratio)] = 0.0 - spec_data = (self.get_data(group_squeeze=group_squeeze) - - spectrumset.get_data(group_squeeze=group_squeeze)*arf_ratio) - self.set_data(spec_data, group_squeeze=group_squeeze) + spec_data1 = self.get_data(group_squeeze=group_squeeze) + spec_data2 = spectrumset.get_data(group_squeeze=group_squeeze) + spec_data_new = spec_data1 - spec_data2 * arf_ratio + self.set_data(spec_data_new, group_squeeze=group_squeeze) + energy_groupped = self.energy_groupped + eidx = ((energy_groupped >= CONFIGS["info_emin"]) & + (energy_groupped <= CONFIGS["info_emax"])) + datasum1 = np.sum(spec_data1[eidx]) + datasum2 = np.sum(spec_data_new[eidx]) + datacp = 100 * (datasum2-datasum1) / datasum1 + if verbose: + print("[%s] crosstalk/subtract -> [%s]: %g -> %g (%.2f%%)" % + (str(self), str(spectrumset), datasum1, datasum2, datacp)) # record history if add_history: self.header.add_history(operation) @@ -1028,7 +1048,7 @@ class SpectrumSet(Spectrum): # {{{ self.filename) if verbose: print(operation, file=sys.stderr) - energy = self.get_energy() + energy = self.energy if groupped: cross_arf.apply_grouping(energy_channel=energy, grouping=self.grouping, @@ -1044,9 +1064,18 @@ class SpectrumSet(Spectrum): # {{{ arf_ratio = arfresp_cross / arfresp_this # fix nan/inf values due to division by zero arf_ratio[~np.isfinite(arf_ratio)] = 0.0 - spec_data = (self.get_data(group_squeeze=group_squeeze) + - self.get_data(group_squeeze=group_squeeze) * arf_ratio) - self.set_data(spec_data, group_squeeze=group_squeeze) + spec_data = self.get_data(group_squeeze=group_squeeze) + spec_data_new = spec_data * (1 + arf_ratio) + self.set_data(spec_data_new, group_squeeze=group_squeeze) + energy_groupped = self.energy_groupped + eidx = ((energy_groupped >= CONFIGS["info_emin"]) & + (energy_groupped <= CONFIGS["info_emax"])) + datasum1 = np.sum(spec_data[eidx]) + datasum2 = np.sum(spec_data_new[eidx]) + datacp = 100 * (datasum2-datasum1) / datasum1 + if verbose: + print("[%s] crosstalk/compensate <- [%s]: %g -> %g (%.2f%%)" % + (str(self), str(cross_arf), datasum1, datasum2, datacp)) # record history if add_history: self.header.add_history(operation) @@ -1132,7 +1161,7 @@ class Crosstalk: # {{{ # `SpectrumSet' and `ARF' objects corresponding to the spectra from # which the photons were scattered into this spectrum. cross_in_specset = None - cross_in_arf = None + cross_in_arf = None # `ARF' objects corresponding to the regions to which the photons of # this spectrum were scattered into. cross_out_arf = None @@ -1142,32 +1171,33 @@ class Crosstalk: # {{{ # whether the spectrum is groupped groupped = False - def __init__(self, config, arf_dict={}, rmf_dict={}, + def __init__(self, config, regid=None, arf_dict={}, rmf_dict={}, grouping=None, quality=None): """ Arguments: * config: a section of the whole config file (`ConfigObj' object) """ + self.regid = regid self.cross_in_specset = [] - self.cross_in_arf = [] - self.cross_out_arf = [] + self.cross_in_arf = [] + self.cross_out_arf = [] # this spectrum to be corrected self.spectrumset = SpectrumSet( - filename=config["spec"], + filename=config["spec"], regid=regid, outfile=config["outfile"], - arf=arf_dict.get(config["arf"], config["arf"]), - rmf=rmf_dict.get(config.get("rmf"), config.get("rmf")), + arf=arf_dict[config["arf"]], + rmf=rmf_dict.get(config.get("rmf"), None), bkg=config.get("bkg")) # spectra and cross arf from which photons were scattered in - for reg_in in config["cross_in"].values(): + for k, v in config["cross_in"].items(): specset = SpectrumSet( - filename=reg_in["spec"], - arf=arf_dict.get(reg_in["arf"], reg_in["arf"]), - rmf=rmf_dict.get(reg_in.get("rmf"), reg_in.get("rmf")), - bkg=reg_in.get("bkg")) + filename=v["spec"], regid=k, + arf=arf_dict[config["arf"]], + rmf=rmf_dict.get(config.get("rmf"), None), + bkg=v.get("bkg")) self.cross_in_specset.append(specset) - self.cross_in_arf.append(arf_dict.get(reg_in["cross_arf"], - ARF(reg_in["cross_arf"]))) + self.cross_in_arf.append( + arf_dict.get(v["cross_arf"], ARF(v["cross_arf"], regid=k))) # regions into which the photons of this spectrum were scattered into if "cross_out" in config.sections: cross_arf = config["cross_out"].as_list("cross_arf") @@ -1304,7 +1334,7 @@ class Deprojection: # {{{ for spec in spectra: if not isinstance(spec, SpectrumSet): raise ValueError("Not a 'SpectrumSet' object") - spec.read_xflt() + spec.read_xflt(verbose=verbose) self.spectra.append(spec) self.spectra = spectra self.grouping = grouping @@ -1338,12 +1368,12 @@ class Deprojection: # {{{ for spec in self.spectra: spec.estimate_errors(gehrels=gehrels) - def scale(self): + def scale(self, verbose=False): """ Scale the spectral data according to the region angular size. """ for spec in self.spectra: - spec.scale() + spec.scale(verbose=verbose) def do_deprojection(self, group_squeeze=True, add_history=False, verbose=False): @@ -1425,14 +1455,14 @@ class Deprojection: # {{{ spec.fix_header_keywords( reset_kw=["RESPFILE", "ANCRFILE", "BACKFILE"]) - def write(self, filenames=[], clobber=False): + def write(self, outfiles=None, clobber=False): """ Write the deprojected spectra to output file. """ - if filenames == []: - filenames = [spec.outfile for spec in self.spectra] - for spec, outfile in zip(self.spectra, filenames): - spec.write(filename=outfile, clobber=clobber) + if outfiles is None: + outfiles = [spec.outfile for spec in self.spectra] + for spec, outfile in zip(self.spectra, outfiles): + spec.write(outfile=outfile, clobber=clobber) @staticmethod def projected_volume(r1, r2, R1, R2): @@ -1488,27 +1518,26 @@ def calc_median_errors(results): # main routine {{{ def main(config, subtract_bkg, fix_negative, mc_times, - verbose=False, clobber=False): + verbose=False, clobber=False, **kwargs): # collect ARFs and RMFs into dictionaries (avoid interpolation every time) arf_files = set() rmf_files = set() for region in config.sections: config_reg = config[region] - arf_files.add(config_reg.get("arf")) - rmf_files.add(config_reg.get("rmf")) - for reg_in in config_reg["cross_in"].values(): - arf_files.add(reg_in.get("arf")) - arf_files.add(reg_in.get("cross_arf")) + arf_files.add((config_reg["arf"], region)) + rmf_files.add((config_reg["rmf"], region)) + for k, v in config_reg["cross_in"].items(): + arf_files.add((v["arf"], k)) + arf_files.add((v["cross_arf"], k)) if "cross_out" in config_reg.sections: for arf in config_reg["cross_out"].as_list("cross_arf"): - arf_files.add(arf) - arf_files = arf_files - set([None]) - arf_dict = {arf: ARF(arf) for arf in arf_files} - rmf_files = rmf_files - set([None]) - rmf_dict = {rmf: RMF(rmf) for rmf in rmf_files} - if verbose: - print("INFO: arf_files:", arf_files, file=sys.stderr) - print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_files.add((arf, None)) + print("INFO: arf_files:", arf_files, file=sys.stderr) + print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_dict = {arf: ARF(arf, regid=reg) + for arf, reg in arf_files if arf is not None} + rmf_dict = {rmf: RMF(rmf, regid=reg) + for rmf, reg in rmf_files if rmf is not None} # get the GROUPING and QUALITY data grouping_fits = fits.open(config["grouping"]) @@ -1526,7 +1555,7 @@ def main(config, subtract_bkg, fix_negative, mc_times, for region in config.sections: if verbose: print("INFO: processing '%s' ..." % region, file=sys.stderr) - crosstalk = Crosstalk(config.get(region), + crosstalk = Crosstalk(config.get(region), regid=region, arf_dict=arf_dict, rmf_dict=rmf_dict, grouping=grouping, quality=quality) crosstalk.apply_grouping(verbose=verbose) @@ -1549,7 +1578,7 @@ def main(config, subtract_bkg, fix_negative, mc_times, if verbose: print("INFO: scaling spectra according the region angular size...", file=sys.stderr) - deprojection.scale() + deprojection.scale(verbose=verbose) if verbose: print("INFO: doing deprojection ...", file=sys.stderr) deprojection.do_deprojection(add_history=True, verbose=verbose) @@ -1561,7 +1590,7 @@ def main(config, subtract_bkg, fix_negative, mc_times, print("INFO: Monte Carlo to estimate spectral errors (%d times) ..." % mc_times, file=sys.stderr) for i in range(mc_times): - if i % 100 == 0: + if i % 50 == 0: print("%d..." % i, end="", flush=True, file=sys.stderr) # correct crosstalk effects cc_spectra_copy = [] @@ -1577,7 +1606,7 @@ def main(config, subtract_bkg, fix_negative, mc_times, deprojection_copy = Deprojection(spectra=cc_spectra_copy, grouping=grouping, quality=quality, verbose=False) - deprojection_copy.scale() + deprojection_copy.scale(verbose=False) deprojection_copy.do_deprojection(add_history=False, verbose=False) deproj_results.append(deprojection_copy.get_spec_data( group_squeeze=group_squeeze, copy=True)) @@ -1598,7 +1627,8 @@ def main(config, subtract_bkg, fix_negative, mc_times, # main_deprojection routine {{{ -def main_deprojection(config, mc_times, verbose=False, clobber=False): +def main_deprojection(config, mc_times, verbose=False, clobber=False, + **kwargs): """ Only perform the spectral deprojection. """ @@ -1607,15 +1637,14 @@ def main_deprojection(config, mc_times, verbose=False, clobber=False): rmf_files = set() for region in config.sections: config_reg = config[region] - arf_files.add(config_reg.get("arf")) - rmf_files.add(config_reg.get("rmf")) - arf_files = arf_files - set([None]) - arf_dict = {arf: ARF(arf) for arf in arf_files} - rmf_files = rmf_files - set([None]) - rmf_dict = {rmf: RMF(rmf) for rmf in rmf_files} - if verbose: - print("INFO: arf_files:", arf_files, file=sys.stderr) - print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_files.add((config_reg["arf"], region)) + rmf_files.add((config_reg["rmf"], region)) + print("INFO: arf_files:", arf_files, file=sys.stderr) + print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_dict = {arf: ARF(arf, regid=reg) + for arf, reg in arf_files if arf is not None} + rmf_dict = {rmf: RMF(rmf, regid=reg) + for rmf, reg in rmf_files if rmf is not None} # get the GROUPING and QUALITY data grouping_fits = fits.open(config["grouping"]) @@ -1631,7 +1660,8 @@ def main_deprojection(config, mc_times, verbose=False, clobber=False): for region in config.sections: config_reg = config[region] specset = SpectrumSet( - filename=config_reg["spec"], outfile=config_reg["outfile"], + filename=config_reg["spec"], regid=region, + outfile=config_reg["outfile"], arf=arf_dict.get(config_reg["arf"], config_reg["arf"]), rmf=rmf_dict.get(config_reg["rmf"], config_reg["rmf"]), bkg=config_reg["bkg"]) @@ -1644,7 +1674,7 @@ def main_deprojection(config, mc_times, verbose=False, clobber=False): if verbose: print("INFO: scaling spectra according the region angular size ...", file=sys.stderr) - deprojection.scale() + deprojection.scale(verbose=verbose) # keep a (almost) clean copy of the input projected spectra proj_spectra_cleancopy = [spec.copy() for spec in proj_spectra] @@ -1663,7 +1693,7 @@ def main_deprojection(config, mc_times, verbose=False, clobber=False): print("INFO: Monte Carlo to estimate spectral errors (%d times) ..." % mc_times, file=sys.stderr) for i in range(mc_times): - if i % 100 == 0: + if i % 50 == 0: print("%d..." % i, end="", flush=True, file=sys.stderr) # copy and randomize the input projected spectra proj_spectra_copy = [spec.copy().randomize() @@ -1694,7 +1724,7 @@ def main_deprojection(config, mc_times, verbose=False, clobber=False): # main_crosstalk routine {{{ def main_crosstalk(config, subtract_bkg, fix_negative, mc_times, - verbose=False, clobber=False): + verbose=False, clobber=False, **kwargs): """ Only perform the crosstalk correction. """ @@ -1703,21 +1733,20 @@ def main_crosstalk(config, subtract_bkg, fix_negative, mc_times, rmf_files = set() for region in config.sections: config_reg = config[region] - arf_files.add(config_reg.get("arf")) - rmf_files.add(config_reg.get("rmf")) - for reg_in in config_reg["cross_in"].values(): - arf_files.add(reg_in.get("arf")) - arf_files.add(reg_in.get("cross_arf")) + arf_files.add((config_reg["arf"], region)) + rmf_files.add((config_reg["rmf"], region)) + for k, v in config_reg["cross_in"].items(): + arf_files.add((v["arf"], k)) + arf_files.add((v["cross_arf"], k)) if "cross_out" in config_reg.sections: for arf in config_reg["cross_out"].as_list("cross_arf"): - arf_files.add(arf) - arf_files = arf_files - set([None]) - arf_dict = {arf: ARF(arf) for arf in arf_files} - rmf_files = rmf_files - set([None]) - rmf_dict = {rmf: RMF(rmf) for rmf in rmf_files} - if verbose: - print("INFO: arf_files:", arf_files, file=sys.stderr) - print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_files.add((arf, None)) + print("INFO: arf_files:", arf_files, file=sys.stderr) + print("INFO: rmf_files:", rmf_files, file=sys.stderr) + arf_dict = {arf: ARF(arf, regid=reg) + for arf, reg in arf_files if arf is not None} + rmf_dict = {rmf: RMF(rmf, regid=reg) + for rmf, reg in rmf_files if rmf is not None} # get the GROUPING and QUALITY data if "grouping" in config.keys(): @@ -1739,7 +1768,7 @@ def main_crosstalk(config, subtract_bkg, fix_negative, mc_times, for region in config.sections: if verbose: print("INFO: processing '%s' ..." % region, file=sys.stderr) - crosstalk = Crosstalk(config.get(region), + crosstalk = Crosstalk(config.get(region), regid=region, arf_dict=arf_dict, rmf_dict=rmf_dict, grouping=grouping, quality=quality) if grouping is not None: @@ -1765,7 +1794,7 @@ def main_crosstalk(config, subtract_bkg, fix_negative, mc_times, print("INFO: Monte Carlo to estimate spectral errors (%d times) ..." % mc_times, file=sys.stderr) for i in range(mc_times): - if i % 100 == 0: + if i % 50 == 0: print("%d..." % i, end="", flush=True, file=sys.stderr) # correct crosstalk effects cc_spectra_copy = [] @@ -1847,7 +1876,7 @@ if __name__ == "__main__": info_emax = 7.0 CONFIGS.update(info_emin=info_emin, info_emax=info_emax) - for k, v in CONFIGS: + for k, v in CONFIGS.items(): print("* %s: %s" % (k, v)) if mode.lower() == "both": |