| Conditions | 5 |
| Total Lines | 77 |
| Code Lines | 32 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | import os |
||
| 53 | def get_source_map(self, response_bin_id, tag=None, integrate=False, psf_integration_method='fast'): |
||
| 54 | |||
| 55 | # Get current point source position |
||
| 56 | # NOTE: this might change if the point source position is free during the fit, |
||
| 57 | # that's why it is here |
||
| 58 | |||
| 59 | ra_src, dec_src = self._source.position.ra.value, self._source.position.dec.value |
||
| 60 | |||
| 61 | if (ra_src, dec_src) != self._last_processed_position: |
||
| 62 | |||
| 63 | # Position changed (or first iteration), let's update the dec bins |
||
| 64 | self._update_dec_bins(dec_src) |
||
| 65 | |||
| 66 | self._last_processed_position = (ra_src, dec_src) |
||
| 67 | |||
| 68 | # Get the current response bin |
||
| 69 | response_energy_bin = self._response_energy_bins[response_bin_id] |
||
| 70 | psf_interpolator = self._psf_interpolators[response_bin_id] |
||
| 71 | |||
| 72 | # Get the PSF image |
||
| 73 | # This is cached inside the PSF class, so that if the position doesn't change this line |
||
| 74 | # is very fast |
||
| 75 | this_map = psf_interpolator.point_source_image(ra_src, dec_src, psf_integration_method) |
||
| 76 | |||
| 77 | # Check that the point source image is entirely contained in the ROI, if not print a warning |
||
| 78 | map_sum = this_map.sum() |
||
| 79 | |||
| 80 | if not np.isclose(map_sum, 1.0, rtol=1e-2): |
||
| 81 | |||
| 82 | custom_warnings.warn("PSF for source %s is not entirely contained " |
||
| 83 | "in ROI for response bin %s. Fraction is %.2f instead of 1.0. " |
||
| 84 | "Consider enlarging your model ROI." % (self._name, |
||
| 85 | response_bin_id, |
||
| 86 | map_sum)) |
||
| 87 | |||
| 88 | # Compute the fluxes from the spectral function at the same energies as the simulated function |
||
| 89 | energy_centers_keV = response_energy_bin.sim_energy_bin_centers * 1e9 # astromodels expects energies in keV |
||
| 90 | |||
| 91 | # This call needs to be here because the parameters of the model might change, |
||
| 92 | # for example during a fit |
||
| 93 | |||
| 94 | source_diff_spectrum = self._source(energy_centers_keV, tag=tag) |
||
| 95 | |||
| 96 | # This provide a way to force the use of integration, for testing |
||
| 97 | if os.environ.get("HAL_INTEGRATE_POINT_SOURCE", '').lower() == 'yes': # pragma: no cover |
||
| 98 | |||
| 99 | integrate = True |
||
| 100 | |||
| 101 | if integrate: # pragma: no cover |
||
| 102 | |||
| 103 | # Slower approach, where we integrate the spectra of both the simulation and the source |
||
| 104 | # It is off by default because it is slower and it doesn't provide any improvement in accuracy |
||
| 105 | # according to my simulations (GV) |
||
| 106 | |||
| 107 | interp_spectrum = LogLogInterpolator(response_energy_bin.sim_energy_bin_centers, |
||
| 108 | source_diff_spectrum * 1e9, |
||
| 109 | k=2) |
||
| 110 | |||
| 111 | interp_sim_spectrum = LogLogInterpolator(response_energy_bin.sim_energy_bin_centers, |
||
| 112 | response_energy_bin.sim_differential_photon_fluxes, |
||
| 113 | k=2) |
||
| 114 | |||
| 115 | src_spectrum = [interp_spectrum.integral(a, b) for (a, b) in zip(response_energy_bin.sim_energy_bin_low, |
||
| 116 | response_energy_bin.sim_energy_bin_hi)] |
||
| 117 | |||
| 118 | sim_spectrum = [interp_sim_spectrum.integral(a, b) for (a, b) in zip(response_energy_bin.sim_energy_bin_low, |
||
| 119 | response_energy_bin.sim_energy_bin_hi)] |
||
| 120 | |||
| 121 | scale = np.array(src_spectrum) / np.array(sim_spectrum) |
||
| 122 | |||
| 123 | else: |
||
| 124 | |||
| 125 | # Transform from keV^-1 cm^-2 s^-1 to TeV^-1 cm^-2 s^-1 and re-weight the detected counts |
||
| 126 | scale = source_diff_spectrum / response_energy_bin.sim_differential_photon_fluxes * 1e9 |
||
| 127 | |||
| 128 | # Now return the map multiplied by the scale factor |
||
| 129 | return np.sum(scale * response_energy_bin.sim_signal_events_per_bin) * this_map |
||
| 130 |
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.