Skip to content

Commit f8813be

Browse files
should be erosita with custom_bkg
1 parent 5296735 commit f8813be

File tree

1 file changed

+75
-14
lines changed

1 file changed

+75
-14
lines changed

xga/generate/esass/spec.py

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import numpy as np
1212
from astropy.units import Quantity
13+
from regions import CircleSkyRegion, EllispeSkyRegion
1314

1415
from .misc import evtool_combine_evts
1516
from .phot import evtool_image
@@ -22,11 +23,39 @@
2223
from ...samples.base import BaseSample
2324
from ...sources import BaseSource, ExtendedSource, GalaxyCluster
2425

26+
def parse_custom_bkg_esass(region: Union[CircleSkyRegion, EllispeSkyRegion], within_radii: bool = False):
27+
"""
28+
Parse a region object from the `regions` module and return the arguments needed
29+
to call `get_annular_sas_region`.
30+
31+
:param region: A region from the `regions` module
32+
:param str func: Which XGA function will this region be parsed to
33+
:return: Tuple containing (inner_radius, outer_radius, central_coord, rot_angle)
34+
"""
35+
if isinstance(region, CircleSkyRegion):
36+
outer_radius = region.radius if not within_radii else region.radius*1.5
37+
central_coord = Quantity([region.center.ra.deg, region.center.dec.deg], 'deg')
38+
rot_angle = Quantity(0, 'deg') # No rotation for circular regions
39+
inner_radius = Quantity(0, 'deg')
40+
41+
elif isinstance(region, EllipseSkyRegion):
42+
outer_radius = Quantity([region.height / 2, region.width / 2]) if not within_radii \
43+
else Quantity((region.height/2)*1.5)
44+
central_coord = Quantity([region.center.ra.deg, region.center.dec.deg], 'deg')
45+
rot_angle = Quantity(region.angle.to('deg').value, 'deg')
46+
inner_radius = Quantity([0, 0], 'deg')
47+
48+
else:
49+
raise TypeError(f"Unsupported region type: {type(region)}")
50+
51+
return inner_radius, outer_radius, central_coord, rot_angle
52+
2553

2654
def _spec_cmds(sources: Union[BaseSource, BaseSample], outer_radius: Union[str, Quantity],
2755
inner_radius: Union[str, Quantity] = Quantity(0, 'arcsec'), group_spec: bool = True, min_counts: int = 5,
2856
min_sn: float = None, num_cores: int = NUM_CORES, disable_progress: bool = False,
29-
combine_tm: bool = True, combine_obs: bool = True, force_gen: bool = False):
57+
combine_tm: bool = True, combine_obs: bool = True, force_gen: bool = False,
58+
custom_bkg: Union[str, List[str]] = None):
3059
"""
3160
An internal function to generate all the commands necessary to produce a srctool spectrum, but is not
3261
decorated by the esass_call function, so the commands aren't immediately run. This means it can be used for
@@ -63,6 +92,7 @@ def _spec_cmds(sources: Union[BaseSource, BaseSample], outer_radius: Union[str,
6392
:param bool combine_obs: Setting this to False will generate an image for each associated observation,
6493
instead of for one combined observation.
6594
:param bool force_gen: This boolean flag will force the regeneration of spectra, even if they already exist.
95+
:param str custom_bkg: A string to be input into the backreg argument of srctool.
6696
"""
6797
def _append_spec_info(evt_list):
6898
"""
@@ -164,11 +194,40 @@ def _append_spec_info(evt_list):
164194
reg = get_annular_esass_region(source, inner_radii[s_ind], outer_radii[s_ind], obs_id,
165195
interloper_regions=interloper_regions,
166196
central_coord=source.default_coord, rand_ident=rand_ident)
167-
b_reg = get_annular_esass_region(source, outer_radii[s_ind] * source.background_radius_factors[0],
168-
outer_radii[s_ind] * source.background_radius_factors[1], obs_id,
169-
interloper_regions=back_inter_reg,
170-
central_coord=source.default_coord, bkg_reg=True,
171-
rand_ident=rand_ident)
197+
198+
# This finds any regions which
199+
if custom_bkg is None:
200+
back_inter_reg = source.regions_within_radii(outer_radii[s_ind] * source.background_radius_factors[0],
201+
outer_radii[s_ind] * source.background_radius_factors[1],
202+
"erosita", source.default_coord)
203+
b_reg = get_annular_esass_region(source, outer_radii[s_ind] * source.background_radius_factors[0],
204+
outer_radii[s_ind] * source.background_radius_factors[1], obs_id,
205+
interloper_regions=back_inter_reg,
206+
central_coord=source.default_coord, bkg_reg=True,
207+
rand_ident=rand_ident)
208+
else:
209+
if isinstance(custom_bkg[s_ind], dict):
210+
try:
211+
use_custom_bkg = custom_bkg[s_ind][obs_id]
212+
except KeyError:
213+
raise KeyError("If using a dictionary for the custom_bkg argument, there"
214+
" must be an entry for every obs_id assigned to the source,"
215+
" or the obs_id must be 'combined' if setting the combine_obs"
216+
" argument to True.")
217+
else:
218+
use_custom_bkg = custom_bkg[s_ind]
219+
220+
_ , bkg_outr, bkg_coord, _ = parse_custom_bkg_esass(use_custom_bkg, True)
221+
back_inter_reg = source.regions_within_radii(Quantity(0, 'deg'), bkg_outr,
222+
'erosita', bkg_coord)
223+
bkg_innr, bkg_outr, bkg_coord, bkg_rot_angle = parse_custom_bkg_esass(use_custom_bkg)
224+
breg = get_annular_esass_region(source, bkg_innr, bkg_outr, obs_id,
225+
interloper_regions=back_inter_reg,
226+
central_coord=bkg_coord, bkg_reg=True,
227+
rand_ident=rand_ident,
228+
rot_angle=bkg_rot_angle)
229+
230+
172231
inn_rad_degrees = inner_radii[s_ind]
173232
out_rad_degrees = outer_radii[s_ind]
174233

@@ -444,6 +503,13 @@ def _append_spec_info(evt_list):
444503
ex_src = False
445504
et = 'POINT'
446505

506+
if isinstance(custom_bkg, dict):
507+
custom_bkg = [custom_bkg]
508+
509+
if isinstance(custom_bkg, list):
510+
if len(custom_bkg) != len(sources):
511+
raise ValueError("If inputting a list of dictionaries into the 'custom_bkg' argument, the length "
512+
"of the list must be the same as the length of the sample.")
447513
# TODO implement the det map EXTTPYE, at the moment this spectrum will treat the target as a point source
448514
# Defining the various eSASS commands that need to be populated
449515
# There will be a different command for extended and point sources
@@ -528,14 +594,9 @@ def _append_spec_info(evt_list):
528594
if outer_radius != 'region':
529595
# Finding interloper regions within the radii we have specified has been put here because it all works in
530596
# degrees and as such only needs to be run once for all the different observations.
531-
# TODO ASSUMPTION8 telescope agnostic version of the regions_within_radii will have telescope argument
532597
interloper_regions = source.regions_within_radii(inner_radii[s_ind], outer_radii[s_ind], "erosita",
533598
source.default_coord)
534-
# This finds any regions which
535-
# TODO ASSUMPTION8 telescope agnostic version of the regions_within_radii will have telescope argument
536-
back_inter_reg = source.regions_within_radii(outer_radii[s_ind] * source.background_radius_factors[0],
537-
outer_radii[s_ind] * source.background_radius_factors[1],
538-
"erosita", source.default_coord)
599+
539600
src_inn_rad_str = inner_radii[s_ind].value
540601
src_out_rad_str = outer_radii[s_ind].value
541602
# The key under which these spectra will be stored
@@ -555,7 +616,7 @@ def _append_spec_info(evt_list):
555616
# This function then uses the evtlist to generate spec commands, final paths,
556617
# and extra info, it will then append them to the cmds, final_paths, and extrainfo lists
557618
# that are defined above
558-
_append_spec_info(evt_list)
619+
_append_spec_info(evt_list, s_ind)
559620

560621

561622
else:
@@ -565,7 +626,7 @@ def _append_spec_info(evt_list):
565626
# This function then uses the evtlist to generate spec commands, final paths,
566627
# and extra info, it will then append them to the cmds, final_paths, and extrainfo lists
567628
# that are defined above
568-
_append_spec_info(evt_list)
629+
_append_spec_info(evt_list, s_ind)
569630

570631

571632
sources_cmds.append(np.array(cmds))

0 commit comments

Comments
 (0)