def test_trapz_loglog(): energy = Quantity([1, 10], "TeV") pwl = PowerLawSpectralModel(index=2.3) ref = pwl.integral(energy_min=energy[0], energy_max=energy[1]) val = trapz_loglog(pwl(energy), energy) assert_quantity_allclose(val, ref)
def evaluate_integrate(self, fov_lon, fov_lat, energy_reco, method="linear"): """Evaluate at given FOV position and energy, by integrating over the energy range. Parameters ---------- fov_lon, fov_lat : `~astropy.coordinates.Angle` FOV coordinates expecting in AltAz frame. energy_reco: `~astropy.units.Quantity` Reconstructed energy edges. method : {'linear', 'nearest'}, optional Interpolation method Returns ------- array : `~astropy.units.Quantity` Returns 2D array with axes offset """ data = self.evaluate(fov_lon, fov_lat, energy_reco, method=method) return trapz_loglog(data, energy_reco, axis=0)
def integrate_log_log(self, axis_name, **kwargs): """Integrate along a given axis. This method uses log-log trapezoidal integration. Parameters ---------- axis_name : str Along which axis to integrate. **kwargs : dict Coordinates at which to evaluate the IRF Returns ------- array : `~astropy.units.Quantity` Returns 2D array with axes offset """ axis = self.axes.index(axis_name) data = self.evaluate(**kwargs, method="linear") values = kwargs[axis_name] return trapz_loglog(data, values, axis=axis)
def plot_spectrum(self, ax=None, **kwargs): """Plot angle integrated background rate versus energy. Parameters ---------- ax : `~matplotlib.axes.Axes`, optional Axis kwargs : dict Forwarded tp plt.plot() Returns ------- ax : `~matplotlib.axes.Axes` Axis """ import matplotlib.pyplot as plt ax = plt.gca() if ax is None else ax offset = self.data.axes["offset"].edges energy = self.data.axes["energy"].center bkg = [] for ee in energy: data = self.data.evaluate(offset=offset, energy=ee) val = np.nansum(trapz_loglog(data, offset, axis=0)) bkg.append(val.value) ax.plot(energy, bkg, label="integrated spectrum", **kwargs) unit = self.data.data.unit * offset.unit * offset.unit ax.set_xscale("log") ax.set_yscale("log") ax.set_xlabel(f"Energy [{energy.unit}]") ax.set_ylabel(f"Background rate ({unit})") ax.set_xlim(min(energy.value), max(energy.value)) ax.legend(loc="best") return ax
def integrate_spectrum(func, emin, emax, ndecade=100, intervals=False): """Integrate 1d function using the log-log trapezoidal rule. If scalar values for xmin and xmax are passed an oversampled grid is generated using the ``ndecade`` keyword argument. If xmin and xmax arrays are passed, no oversampling is performed and the integral is computed in the provided grid. Parameters ---------- func : callable Function to integrate. emin : `~astropy.units.Quantity` Integration range minimum emax : `~astropy.units.Quantity` Integration range minimum ndecade : int, optional Number of grid points per decade used for the integration. Default : 100. intervals : bool, optional Return integrals in the grid not the sum, default: False """ if emin.isscalar and emax.isscalar: energies = MapAxis.from_energy_bounds(emin=emin, emax=emax, nbin=ndecade, per_decade=True).edges else: energies = edges_from_lo_hi(emin, emax) values = func(energies) integral = trapz_loglog(values, energies) if intervals: return integral return integral.sum()