|
1 | 1 | # This code is a part of X-ray: Generate and Analyse (XGA), a module designed for the XMM Cluster Survey (XCS).
|
2 |
| -# Last modified by David J Turner (turne540@msu.edu) 16/07/2025, 10:48. Copyright (c) The Contributors |
| 2 | +# Last modified by David J Turner (turne540@msu.edu) 16/07/2025, 12:25. Copyright (c) The Contributors |
3 | 3 |
|
4 | 4 | import gc
|
5 | 5 | import os
|
|
35 | 35 | from ..sourcetools.misc import coord_to_name
|
36 | 36 | from ..utils import ALLOWED_PRODUCTS, dict_search, xmm_det, xmm_sky, OUTPUT, SRC_REGION_COLOURS, \
|
37 | 37 | DEFAULT_COSMO, ALLOWED_INST, COMBINED_INSTS, obs_id_test, PRETTY_TELESCOPE_NAMES, OBS_ID_REGEX, \
|
38 |
| - check_telescope_choices |
| 38 | + check_telescope_choices, RAD_MATCH_PRECISION |
39 | 39 |
|
40 | 40 | # This disables an annoying astropy warning that pops up all the time with XMM images
|
41 | 41 | # Don't know if I should do this really
|
@@ -3293,52 +3293,50 @@ def _get_spec_prod(self, outer_radius: Union[str, Quantity], obs_id: str = None,
|
3293 | 3293 | else:
|
3294 | 3294 | raise TypeError("You may only pass a quantity or a string as outer_radius")
|
3295 | 3295 |
|
3296 |
| - if over_sample is not None: |
3297 |
| - over_sample = int(over_sample) |
3298 |
| - if min_counts is not None: |
3299 |
| - min_counts = int(min_counts) |
3300 |
| - if min_sn is not None: |
3301 |
| - min_sn = float(min_sn) |
3302 |
| - |
3303 |
| - # Sets up the extra part of the storage key name depending on if grouping is enabled |
3304 |
| - if group_spec and min_counts is not None: |
3305 |
| - extra_name = "_mincnt{}".format(min_counts) |
3306 |
| - elif group_spec and min_sn is not None: |
3307 |
| - extra_name = "_minsn{}".format(min_sn) |
3308 |
| - else: |
3309 |
| - extra_name = '' |
3310 |
| - |
3311 |
| - # And if it was oversampled during generation then we need to include that as well |
3312 |
| - if over_sample is not None: |
3313 |
| - extra_name += "_ovsamp{ov}".format(ov=over_sample) |
3314 |
| - |
3315 |
| - if outer_radius != 'region': |
3316 |
| - # The key under which these spectra will be stored |
3317 |
| - spec_storage_name = "ra{ra}_dec{dec}_ri{ri}_ro{ro}_grp{gr}" |
3318 |
| - spec_storage_name = spec_storage_name.format(ra=self.default_coord[0].value, |
3319 |
| - dec=self.default_coord[1].value, |
3320 |
| - ri=inn_rad_num.value, ro=out_rad_num.value, |
3321 |
| - gr=group_spec) |
3322 |
| - else: |
3323 |
| - spec_storage_name = "region_grp{gr}".format(gr=group_spec) |
3324 |
| - |
3325 |
| - # Adds on the extra information about grouping to the storage key |
3326 |
| - spec_storage_name += extra_name |
| 3296 | + # Checking spectrum generation inputs, and making sure they are in the right types |
| 3297 | + over_sample = int(over_sample) if over_sample is not None else None |
| 3298 | + min_counts = int(min_counts) if min_counts is not None else None |
| 3299 | + min_sn = float(min_sn) if min_sn is not None else None |
3327 | 3300 |
|
3328 | 3301 | if obs_id == 'combined':
|
3329 |
| - matched_prods = self.get_products('combined_spectrum', obs_id=obs_id, inst=inst, |
3330 |
| - extra_key=spec_storage_name, telescope=telescope) |
| 3302 | + matched_prods = self.get_products('combined_spectrum', obs_id=obs_id, inst=inst, telescope=telescope) |
3331 | 3303 | else:
|
3332 |
| - matched_prods = self.get_products('spectrum', obs_id=obs_id, inst=inst, extra_key=spec_storage_name, |
3333 |
| - telescope=telescope) |
| 3304 | + matched_prods = self.get_products('spectrum', obs_id=obs_id, inst=inst, telescope=telescope) |
| 3305 | + |
| 3306 | + matched_prods : List[Spectrum] |
| 3307 | + |
| 3308 | + # Checking for matching radii first - this will likely whittle down the spectra best of all. We have had |
| 3309 | + # matching problems sometimes because of float precision (the last digit flips and is no longer an exact |
| 3310 | + # match to the other radius) |
| 3311 | + matched_prods = [m_prod for m_prod in matched_prods |
| 3312 | + if np.isclose(inn_rad_num, m_prod.inner_rad, rtol=0, atol=RAD_MATCH_PRECISION) |
| 3313 | + and np.isclose(out_rad_num, m_prod.outer_rad, rtol=0, atol=RAD_MATCH_PRECISION)] |
| 3314 | + |
| 3315 | + # Separating the matching steps can also give us the opportunity to say exactly where matching failed |
| 3316 | + # in the future. Now we check for matches to the spectrum generation settings - in a for loop this time |
| 3317 | + # because we have to distinguish between searching for grouped and ungrouped spectra |
| 3318 | + final_matched_prods = [] |
| 3319 | + for m_prod in matched_prods: |
| 3320 | + # If the current spectrum doesn't match user specified grouping (or not) boolean, we move on |
| 3321 | + if not group_spec == m_prod.grouped: |
| 3322 | + continue |
| 3323 | + # Getting here means that the grouped status of the current spectrum matches the user |
| 3324 | + # specification, and then if they aren't grouped we don't need to do the other comparisons |
| 3325 | + elif not group_spec: |
| 3326 | + final_matched_prods.append(m_prod) |
| 3327 | + continue |
3334 | 3328 |
|
3335 |
| - if len(matched_prods) == 1: |
3336 |
| - matched_prods = matched_prods[0] |
3337 |
| - elif len(matched_prods) == 0: |
3338 |
| - raise NoProductAvailableError("Cannot find any spectra matching your input.") |
| 3329 | + # If we're here then we have to compare this spectrum's grouping settings to those passed by |
| 3330 | + # the user |
| 3331 | + if min_counts == m_prod.min_counts and min_sn == m_prod.min_sn and over_sample == m_prod.over_sample: |
| 3332 | + final_matched_prods.append(m_prod) |
3339 | 3333 |
|
3340 |
| - return matched_prods |
| 3334 | + if len(final_matched_prods) == 1: |
| 3335 | + final_matched_prods = final_matched_prods[0] |
| 3336 | + elif len(final_matched_prods) == 0: |
| 3337 | + raise NoProductAvailableError("Cannot find any spectra matching your input.") |
3341 | 3338 |
|
| 3339 | + return final_matched_prods |
3342 | 3340 |
|
3343 | 3341 | def get_spectra(self, outer_radius: Union[str, Quantity], obs_id: str = None, inst: str = None,
|
3344 | 3342 | inner_radius: Union[str, Quantity] = Quantity(0, 'arcsec'), group_spec: bool = True,
|
|
0 commit comments