Introducing XGA Products

This tutorial will briefly touch on XGA’s product classes, which are a key part of the internal makeup of the module. They act as an interface between XGA’s functions and the data in different types of X-ray data (images, exposure maps, spectra etc.), and contain many useful and convenient methods for analysis and the extraction of information.

Specific abilities of different product types will not be demonstrated in this tutorial, there are too many to go into here, a brief overview will be given to showcase the purpose and important abilities of all the product classes built into XGA.

[36]:
from astropy.units import Quantity

from xga.sources import GalaxyCluster
from xga.generate.esass import srctool_spectrum

What are products?

Most XGA products are what we use to wrap various types of data produced by telescope-specific software, as well as providing various product specific functionality. Generally, the user is unlikely to ever define a product instance themselves, internal methods in a source object and the telescope-specific wrapper functions will define, check, and store the products.

Those products that are generated by XGA’s SAS interface have an added ability to parse the stderr output of the SAS routines used to generate them, then flag any recognised errors (by comparing to an archive of known SAS errors).

There are some XGA products that are not wrappers for generated data products, but are purely for storing and providing access to XGA generated data. These are not based on the same superclass as the other products, but are stored in the same way.

Products instantiated by XGA are immediately ‘associated’ with a source object, though beyond storing the name of the source in the product’s internal structure, they have no knowledge or awareness of the XGA source and its properties. This was by design, to make sure that any functionality built into a product would work regardless of the type of XGA source, and even if it was defined independently of any source at all.

What types of product are there?

  • BaseProduct - The superclass for many of the standard XGA product classes, there isn’t really any reason for a BaseProduct to be declared.

    • EventList - A very simple product class which differs only slightly from the BaseProduct class, its only used to store path and header information for the XMM event lists that the configuration file points XGA at.

    • Image - An extremely useful product with many extra features, it is used to wrap fits images. The data and header information are read into memory (when required), and can be accessed with properties and attributes of an Image instance. A view method (to look at the image and overlay extra information), and a coordinate transformation method are examples of the built-in functionality.

      • ExpMap - A subclass of the XGA Image class, this is a very simple extension to Image that adds a method to easily retrieve an exposure time at a given angular or pixel coordinate.

      • RateMap - The class that most photometric analyses are based around, also a subclass of Image. Instantiating this class requires the user pass matching Image and ExpMap instances (same ObsID, instrument etc.) A count rate map is then calculated from this information. This has several added methods, including the ability to retrieve a count rate at a given coordinate, and different peak finding methods.

      • PSF - (XMM data only) This wraps two-dimensional PSF images generated by a routine such as psfgen, and can be used to PSF correct images and ratemaps. Few methods have been added, and it is unlikely a user will ever need to interact directly with this. The added functionality here is the ability to resample the PSF at a scale provided by a passed in Image object.

    • Spectrum - A complicated sub-class of BaseProduct, it wraps and stores a spectrum, including storing paths to all of the other files necessary to analyse it (e.g. RMF, ARF, background spectrum). When a source that has had spectra associated with it is passed to an XGA XSPEC function, the fit results are added to the spectrum objects. This has methods to retrieve fit results, as well as view the fitted Spectrum.

  • BaseAggregateProduct - Another base product class, this one is designed to store a group of related XGA products.

    • PSFGrid - (XMM data only) An XGA object used during the PSF correction of images and ratemaps, it stores a grid of PSF objects generated at different spatial positions on the XMM detectors. It provides access to those PSFs on request from the PSF correction function, and context as to which PSF was generated at which position.

    • AnnularSpectra - This holds sets of XGA Spectrum products generated in concentric annuli, and includes various methods for accessing the individual spectra, retrieving fit information (if a fit has been run), and viewing the spectra (both for individual annuli, and the whole set). This class is crucial for the measurement of galaxy cluster temperature profiles, and by extension the measurement of hydrostatic mass profiles.

  • BaseProfile1D - Here we move to the special products that don’t wrap existing X-ray data products, these are entirely generated by XGA. This class is designed to store, fit, and generate plots of different 1D profiles. The user should never declare an instance of this class, only the specific subclass that they need for their analysis.

    • SurfaceBrightness1D - Mostly meant for Galaxy Clusters, this class will store a 1D surface brightness profile, and enable the fitting of valid models such as a beta profile, or double beta profile.

    • GasDensity1D - This is meant to store a gas density profile as calculated by XGA, and includes methods to calculate a total gas mass within a given radius, as well as to generate a gas mass profile.

    • GasMass1D - A class for gas mass 1D profiles, which currently has no extra functionality over BaseProfile1D.

    • ProjectedGasTemperature1D - A class for the projected temperature profiles which are measured by fitting plasma emission models to annular spectra. They are ‘projected’ because they are a combination of temperatures of the 3D shells which are intersected along the line of sight by the annulus.

    • APECNormalisation1D - A class for storing profiles of the normalisation of the APEC plasma emission model, which is extracted from the same fitting process (run on an AnnularSpectra) that produces the projected temperature profiles. This profile can be used to measure the 3D density profile, and (when converted to an emission measure profile and combined with knowledge of the projected temperature profile) allows us to infer the 3D temperature profile.

    • EmissionMeasure1D - Calculated from an APECNormalisation1D, and knowledge of the cosmology and the redshift of the source. The emission measure profile can be used to help infer the 3D temperature profile of a cluster, when combined with the projected temperature profile and assumptions about the source geometry.

    • ProjectedGasMetallicity1D - Another profile that can be measured from the fitting of AnnularSpectra, though only if metallicity is allowed to vary as a free parameter. Again it is ‘projected’ because the metallicities are a combination of the metallicities of the 3D shells intersected along the line of sight by the annuli.

    • GasTemperature3D - A three-dimensional radial map of the plasma temperature of the intra-cluster medium of a galaxy cluster. This can be used, in combination with knowledge of the 3D gas density, to measure a mass profile for a galaxy cluster.

    • HydrostaticMass - Defined with a gas density profile and a 3D temperature profile, this type of profile describes the change of the total mass contained within a radius, and has methods to measure a mass at whatever radius the user wants to.

    • BaryonFraction - Can be generated by a HydrostaticMass profile, this shows the change in total baryon fraction within a radius, with radius. Again the value at a specific point can be calculated using a method implemented in this class.

  • BaseAggregateProfile1D - This is unlikely ever to actually have any specific subclasses, as awareness of the type of profile is not really necessary for its only job, which is to display multiple profiles on one axis. These can be generated just by adding multiple profile products together with the standard Python + operator

  • ScalingRelation - The scaling relation products are unique in XGA, in that they are the only products that cannot be stored within a source, as they concern multiple sources (or no sources at all if declared from the literature), it would not make sense. These are produced by the scaling relation generation functions built into XGA, and in that case would contain both data and a fitted model. There are also several scaling relations from literature defined in XGA, these only contain the fitted model. A view method capable of producing publication quality plots is provided, along with many other convenient methods.

  • AggregateScalingRelation - Just as the BaseAggregateProfile1D class was created purely to view multiple profiles on the same axes, this class is designed to enable scaling relations to be easily combined and viewed together. This class is instantiated by adding multiple ScalingRelation objects together.

Generating Products

This tutorial will not touch on how to generate the product objects, this will be left to more subject specific tutorials such as “Photometry with XGA” and “Spectroscopy with XGA”.

Any data products generated by XGA are stored in the directory pointed to by the xga_save_path entry in the configuration file (which can be either an absolute or relative path). By default a source will load in any product previously generated for it, to save the computational expense of re-generating products that already exist, this behaviour can be turned off if the user sets the load_products keyword argument to False when defining a source object.

Methods for retrieving products

Here it will be demonstrated how XGA stores product objects within a source, and how you can retrieve them if you wish to interact with the products directly.

Firslty a demonstration GalaxyCluster source object is defined - Abell 907 (please note that the overdensity radii and the redshift used here are approximate and should not be used for a scientific analysis)

[5]:
src = GalaxyCluster(149.59209, -11.05972, 0.16, r500=Quantity(1200, 'kpc'), r200=Quantity(1700, 'kpc'),
                    name="A907", search_distance={'erosita': Quantity(3, 'deg'),
                                                  'xmm': Quantity(30, 'arcmin')})
#src.info()
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/ipykernel/ipkernel.py:283: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.
  and should_run_async(code)
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/mnt/lustre/projects/astro/general/jp735/XGA_dev/XGA/xga/sources/general.py:229: UserWarning: Generating the combined images required for this is not supported for eROSITA - we will use the highest exposure ObsID instead - associated with source A907
  self._all_peaks(peak_find_method, 'extended')
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/its/home/jp735/.conda/envs/xga_dev/lib/python3.8/site-packages/regions/core/compound.py:93: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  data = self.operator(*np.array(padded_data, dtype=np.int))
/mnt/lustre/projects/astro/general/jp735/XGA_dev/XGA/xga/sources/general.py:231: UserWarning: Multiple telescopes are associated with source A907 - we do not yet support combining peak information, so the XMM peak is being returned.
  self._default_coord = self.peak

Retrieving specific product types

This tutorial will detail some of the product retrieval methods. The are of the general form get_<product type>(). Different Product type objects have different identifying information, hence their retrieval methods can contain unique keyword arguments. Here these will be detailed to a degree, but it is advised to seek the API documentation for the complete view. In particular retrieving profile products can vary depending on the source type they were generated from (eg. only GalaxyCluster sources have hydrostatic_mass_profile products associated with them).

All images products can be retrieved using the get_images() method. This will contain single camera images for XMM, combined images from all eROSITA telescope modules, for all energy ranges.
Please note that to retrieve PSF corrected images you must pass psf_corr=True.
[17]:
specific_ims = src.get_images()
specific_ims
[17]:
[<xga.products.phot.Image at 0x7f22af3342e0>,
 <xga.products.phot.Image at 0x7f22af334970>,
 <xga.products.phot.Image at 0x7f22af334310>,
 <xga.products.phot.Image at 0x7f22af2f3880>,
 <xga.products.phot.Image at 0x7f22af2f3bb0>,
 <xga.products.phot.Image at 0x7f22af2f4130>,
 <xga.products.phot.Image at 0x7f22af2f4b20>,
 <xga.products.phot.Image at 0x7f22af2f4ca0>,
 <xga.products.phot.Image at 0x7f22af2f4e50>,
 <xga.products.phot.Image at 0x7f22af5145b0>,
 <xga.products.phot.Image at 0x7f22af399fa0>,
 <xga.products.phot.Image at 0x7f22af138460>,
 <xga.products.phot.Image at 0x7f22af1389d0>,
 <xga.products.phot.Image at 0x7f22af138af0>,
 <xga.products.phot.Image at 0x7f22af138fd0>,
 <xga.products.phot.Image at 0x7f22af138f70>,
 <xga.products.phot.Image at 0x7f22aefae730>,
 <xga.products.phot.Image at 0x7f22aefae850>,
 <xga.products.phot.Image at 0x7f22aefaedf0>,
 <xga.products.phot.Image at 0x7f22ae9b7070>,
 <xga.products.phot.Image at 0x7f22aea7eb50>,
 <xga.products.phot.Image at 0x7f22aefae3a0>,
 <xga.products.phot.Image at 0x7f22aea7e550>,
 <xga.products.phot.Image at 0x7f22aea5e9a0>,
 <xga.products.phot.Image at 0x7f22aef14550>,
 <xga.products.phot.Image at 0x7f22aea63b20>,
 <xga.products.phot.Image at 0x7f22ae9b7e20>]

Cycling through the list of image products and looking at their energy bounds, ObsIDs, instruments, and telescopes, we can see that indeed the images for all ObsID-Instrument combinations, in all energy bands, for each telescope have been retrieved:

[18]:
for im in specific_ims:
    print(im.energy_bounds, im.obs_id, im.instrument, im.telescope)
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0404910601 pn xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0404910601 pn xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0404910601 mos1 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0404910601 mos1 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0404910601 mos2 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0404910601 mos2 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201901401 pn xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201901401 pn xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201901401 mos1 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201901401 mos1 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201901401 mos2 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201901401 mos2 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201903501 pn xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201903501 pn xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201903501 mos1 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201903501 mos1 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 0201903501 mos2 xmm
(<Quantity 2. keV>, <Quantity 10. keV>) 0201903501 mos2 xmm
(<Quantity 0.5 keV>, <Quantity 2. keV>) 148102 combined erosita
(<Quantity 0.2 keV>, <Quantity 10. keV>) 148102 combined erosita
(<Quantity 0.5 keV>, <Quantity 10. keV>) 148102 combined erosita
(<Quantity 0.5 keV>, <Quantity 2. keV>) 151102 combined erosita
(<Quantity 0.2 keV>, <Quantity 10. keV>) 151102 combined erosita
(<Quantity 0.5 keV>, <Quantity 10. keV>) 151102 combined erosita
(<Quantity 0.5 keV>, <Quantity 2. keV>) 150099 combined erosita
(<Quantity 0.2 keV>, <Quantity 10. keV>) 150099 combined erosita
(<Quantity 0.5 keV>, <Quantity 10. keV>) 150099 combined erosita

The get methods are similar for Spectrum products, you may also filter for telescope, instrument, and obs_id. However there is an additional requirement that the area from which the spectrum was generated must be parsed.

[61]:
# Firstly let's generate some spectra to retrieve
srctool_spectrum(src, 'r500')
[61]:
<xga.sources.extended.GalaxyCluster at 0x7f22b5f409a0>

It is mandatory to parse the area that you used to generate the spectra in the get_spectra() method.

[62]:
# Here we need to include the area the spectrum was generated from
src.get_spectra('r500')
[62]:
[<xga.products.spec.Spectrum at 0x7f22af490be0>,
 <xga.products.spec.Spectrum at 0x7f22ac196ee0>,
 <xga.products.spec.Spectrum at 0x7f22af51af70>]

Filtering the Products

Product retrieval methods have to ability to be specific. Through the optional keyword arguments, energy ranges, instruments, telescopes, and ObsIDs can be filtered for. Such as in the example below where a 0.5-2.0keV exposure map for the PN camera of observation 0404910601 is retrieved. When only one product is retrieved, it is returned as a single Product object, rather than a list.

Here we use the get_expmaps() method, since we are retrieving an exposure map.

[48]:
specific_exs = src.get_expmaps(obs_id='0404910601', inst='pn',
                               lo_en=Quantity(0.5, 'keV'), hi_en=Quantity(2.0, 'keV'))
specific_exs
[48]:
<xga.products.phot.ExpMap at 0x7f22af334dc0>

All get methods have a telescope argument if you wish to only look at products from a certain telescope.

We use Ratemaps to demonstrate, which are retrieved using the get_ratemaps() method. Note that these will automatically be generated if the necessary images and exposure maps have already been generated.

[59]:
rtmaps = src.get_ratemaps(telescope='erosita')
rtmaps
[59]:
[<xga.products.phot.RateMap at 0x7f22aefaedc0>,
 <xga.products.phot.RateMap at 0x7f22ae9bea60>,
 <xga.products.phot.RateMap at 0x7f22ae9be2e0>,
 <xga.products.phot.RateMap at 0x7f22aef141c0>,
 <xga.products.phot.RateMap at 0x7f22aea68820>,
 <xga.products.phot.RateMap at 0x7f22ae9cc220>,
 <xga.products.phot.RateMap at 0x7f22aef14340>,
 <xga.products.phot.RateMap at 0x7f22aea8c0d0>,
 <xga.products.phot.RateMap at 0x7f22ae9639a0>]

We reccomend consulting the multi mission tutorial to see extra get methods for XMM specfic products, as well as notes on filtering for instruments with eROSITA products.

There are many more get_<product type>() methods that retrieve annular spectra, lightcurves, and XGA profiles. Whilst these are not detailed here, you may consult the API documentation to see their functionality.

A general method for retrieving products

The get_products() method is a general way to retrieve products of any type. To use this method you need to specify the type of object to retrieve (e.g. ‘image’). Optionally the user may specific the telescope, ObsID, and instrument (if these options are not specified then the method will retrieve any product that matches the other criteria you provide).

You can also pass an extra_key, which would be something like a specific bound energy key; knowing the key that corresponds to the type of product you wish to retrieve isn’t as intuitive as using the get_<product type>() methods - so it is recommended to use those instead for specfic filtering.

Retrieving images through get_product() is done like this:

[63]:
# We retrieve images here to demonstrate
src.get_products('image')
[63]:
[<xga.products.phot.Image at 0x7f22af3342e0>,
 <xga.products.phot.Image at 0x7f22af334970>,
 <xga.products.phot.Image at 0x7f22af334310>,
 <xga.products.phot.Image at 0x7f22af2f3880>,
 <xga.products.phot.Image at 0x7f22af2f3bb0>,
 <xga.products.phot.Image at 0x7f22af2f4130>,
 <xga.products.phot.Image at 0x7f22af2f4b20>,
 <xga.products.phot.Image at 0x7f22af2f4ca0>,
 <xga.products.phot.Image at 0x7f22af2f4e50>,
 <xga.products.phot.Image at 0x7f22af5145b0>,
 <xga.products.phot.Image at 0x7f22af399fa0>,
 <xga.products.phot.Image at 0x7f22af138460>,
 <xga.products.phot.Image at 0x7f22af1389d0>,
 <xga.products.phot.Image at 0x7f22af138af0>,
 <xga.products.phot.Image at 0x7f22af138fd0>,
 <xga.products.phot.Image at 0x7f22af138f70>,
 <xga.products.phot.Image at 0x7f22aefae730>,
 <xga.products.phot.Image at 0x7f22aefae850>,
 <xga.products.phot.Image at 0x7f22aefaedf0>,
 <xga.products.phot.Image at 0x7f22ae9b7070>,
 <xga.products.phot.Image at 0x7f22aea7eb50>,
 <xga.products.phot.Image at 0x7f22aefae3a0>,
 <xga.products.phot.Image at 0x7f22aea7e550>,
 <xga.products.phot.Image at 0x7f22aea5e9a0>,
 <xga.products.phot.Image at 0x7f22aef14550>,
 <xga.products.phot.Image at 0x7f22aea63b20>,
 <xga.products.phot.Image at 0x7f22ae9b7e20>]

The final keyword argument taken by get_products is ‘just_obj’, which tells the method if you would just like a list of product objects, or if you’d like a list of lists which contain summary information about the products. The ease of retrieving this summary is a case for using get_product() over a get_<product type>() method:

[64]:
src.get_products('image', just_obj=False)
[64]:
[['xmm',
  '0404910601',
  'pn',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af3342e0>],
 ['xmm',
  '0404910601',
  'pn',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af334970>],
 ['xmm',
  '0404910601',
  'mos1',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af334310>],
 ['xmm',
  '0404910601',
  'mos1',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af2f3880>],
 ['xmm',
  '0404910601',
  'mos2',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af2f3bb0>],
 ['xmm',
  '0404910601',
  'mos2',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af2f4130>],
 ['xmm',
  '0201901401',
  'pn',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af2f4b20>],
 ['xmm',
  '0201901401',
  'pn',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af2f4ca0>],
 ['xmm',
  '0201901401',
  'mos1',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af2f4e50>],
 ['xmm',
  '0201901401',
  'mos1',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af5145b0>],
 ['xmm',
  '0201901401',
  'mos2',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af399fa0>],
 ['xmm',
  '0201901401',
  'mos2',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af138460>],
 ['xmm',
  '0201903501',
  'pn',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af1389d0>],
 ['xmm',
  '0201903501',
  'pn',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af138af0>],
 ['xmm',
  '0201903501',
  'mos1',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22af138fd0>],
 ['xmm',
  '0201903501',
  'mos1',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22af138f70>],
 ['xmm',
  '0201903501',
  'mos2',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22aefae730>],
 ['xmm',
  '0201903501',
  'mos2',
  'bound_2.0-10.0',
  <xga.products.phot.Image at 0x7f22aefae850>],
 ['erosita',
  '148102',
  'combined',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22aefaedf0>],
 ['erosita',
  '148102',
  'combined',
  'bound_0.2-10.0',
  <xga.products.phot.Image at 0x7f22ae9b7070>],
 ['erosita',
  '148102',
  'combined',
  'bound_0.5-10.0',
  <xga.products.phot.Image at 0x7f22aea7eb50>],
 ['erosita',
  '151102',
  'combined',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22aefae3a0>],
 ['erosita',
  '151102',
  'combined',
  'bound_0.2-10.0',
  <xga.products.phot.Image at 0x7f22aea7e550>],
 ['erosita',
  '151102',
  'combined',
  'bound_0.5-10.0',
  <xga.products.phot.Image at 0x7f22aea5e9a0>],
 ['erosita',
  '150099',
  'combined',
  'bound_0.5-2.0',
  <xga.products.phot.Image at 0x7f22aef14550>],
 ['erosita',
  '150099',
  'combined',
  'bound_0.2-10.0',
  <xga.products.phot.Image at 0x7f22aea63b20>],
 ['erosita',
  '150099',
  'combined',
  'bound_0.5-10.0',
  <xga.products.phot.Image at 0x7f22ae9b7e20>]]

If you did wish to use get_product() to retrieve products of a specific energy range, this is controlled through the extra_key argument.

[65]:
src.get_products('image', extra_key='bound_0.5-2.0')
[65]:
[<xga.products.phot.Image at 0x7f22af3342e0>,
 <xga.products.phot.Image at 0x7f22af334310>,
 <xga.products.phot.Image at 0x7f22af2f3bb0>,
 <xga.products.phot.Image at 0x7f22af2f4b20>,
 <xga.products.phot.Image at 0x7f22af2f4e50>,
 <xga.products.phot.Image at 0x7f22af399fa0>,
 <xga.products.phot.Image at 0x7f22af1389d0>,
 <xga.products.phot.Image at 0x7f22af138fd0>,
 <xga.products.phot.Image at 0x7f22aefae730>,
 <xga.products.phot.Image at 0x7f22aefaedf0>,
 <xga.products.phot.Image at 0x7f22aefae3a0>,
 <xga.products.phot.Image at 0x7f22aef14550>]

NoProductAvailableError

This exception is triggered if you try and use one of the specific get methods to retrieve a product that does not exist.

Here, for instance, we attempt to retrieve a merged RateMap in the 0.5-4.2keV energy range:

[56]:
src.get_combined_ratemaps(Quantity(0.5, 'keV'), Quantity(4.2, 'keV'))
---------------------------------------------------------------------------
NoProductAvailableError                   Traceback (most recent call last)
Cell In[56], line 1
----> 1 src.get_combined_ratemaps(Quantity(0.5, 'keV'), Quantity(4.2, 'keV'))

File /mnt/lustre/projects/astro/general/jp735/XGA_dev/XGA/xga/sources/base.py:2957, in BaseSource.get_combined_ratemaps(self, lo_en, hi_en, psf_corr, psf_model, psf_bins, psf_algo, psf_iter, telescope)
   2955     matched_prods = matched_prods[0]
   2956 elif len(matched_prods) == 0:
-> 2957     raise NoProductAvailableError("Cannot find any combined ratemaps matching your input.")
   2959 return matched_prods

NoProductAvailableError: Cannot find any combined ratemaps matching your input.