Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Absorption with cubepy #133

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9bfc005
Merge branch 'pylint_and_flake8' of https://github.com/cosimoNigro/agnpy
pawel21 Nov 26, 2021
3bb4a33
Merge branch 'master' of https://github.com/cosimoNigro/agnpy
pawel21 Feb 3, 2022
a23cab0
calcurate absorption using cubepy
pawel21 Aug 31, 2022
0ca6f70
add set up error to integrate
pawel21 Sep 9, 2022
4b9f0e3
iterate freq to compute tau_blr
pawel21 Sep 20, 2022
be9979a
Merge branch 'master' of https://github.com/cosimoNigro/agnpy into ab…
pawel21 Nov 10, 2022
eff6965
Merge branch 'master' of https://github.com/cosimoNigro/agnpy into ab…
pawel21 Dec 6, 2022
bcd1888
add notebook with absorption in BLR with cubepy
pawel21 Jan 10, 2023
ffdecbe
Merge branch 'master' of https://github.com/cosimoNigro/agnpy into ab…
pawel21 Apr 6, 2023
403a0bb
remove l_size
pawel21 Apr 6, 2023
c0b6cfa
start develop funtion to calcurate absorption over all line for BLR
pawel21 Apr 6, 2023
8e21ba8
added fun to calculate absorption in all BLR lines
pawel21 May 16, 2023
57d67bc
nodified notebook to new function
pawel21 May 16, 2023
7039b98
add test for absorption in BLR with cubepy
pawel21 Apr 26, 2024
dd28724
remove not used parameters
pawel21 Apr 26, 2024
92eb17b
Add more clear explanations for docs string about calc tau in BLR
pawel21 Jun 3, 2024
e75d6d8
Add function to compute inegrand for cubepy
pawel21 Jun 3, 2024
d5b4778
Merge branch 'master' of https://github.com/cosimoNigro/agnpy into ab…
pawel21 Jun 3, 2024
a81e789
Add environment dependencies for cubepy
pawel21 Jun 3, 2024
eeed0a9
Fix environment dependencies
pawel21 Jun 3, 2024
3aabb7c
Check target name during calc tau
pawel21 Jun 3, 2024
e6b73df
Fix problem with cubepy instalion
pawel21 Jun 7, 2024
269eec2
add cubepy requires to setup.py
pawel21 Jun 7, 2024
70b6ef8
work on exmpale notebook
pawel21 Jul 19, 2024
246a7d3
remove notebook from docs
pawel21 Oct 2, 2024
ede4818
make code more concise and renamed function
pawel21 Oct 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 169 additions & 1 deletion agnpy/absorption/absorption.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
x_re_shell_mu_s,
)
from ..utils.conversion import nu_to_epsilon_prime, to_R_g_units
from ..targets import PointSourceBehindJet, SSDisk, SphericalShellBLR, RingDustTorus
from ..targets import PointSourceBehindJet, SSDisk, SphericalShellBLR, RingDustTorus, lines_dictionary
from ..emission_regions import Blob
from ..synchrotron import nu_synch_peak, Synchrotron

import cubepy as cp


__all__ = ["sigma", "Absorption", "ebl_files_dict", "EBL"]

Expand Down Expand Up @@ -443,6 +445,111 @@ def evaluate_tau_blr_mu_s(
)
return (prefactor * integral).to_value("")

@staticmethod
def compute_integrand_for_blr(cubepy_params_array, R_line, mu_s, epsilon_1, epsilon_line):
"""
Computes the integrand for the gamma-gamma absorption model with
a spherical shell Broad Line Region (BLR).

Parameters
----------
cubepy_params_array : array-like
Array containing integration parameters [mu, phi, log_l].
R_line : :class:`~astropy.units.Quantity`
Radius of the BLR spherical shell.
mu_s : float
Cosine of the angle between the blob motion and the jet axis.
epsilon_1 : float
Dimensionless energy parameter for the incoming photon.
epsilon_line : float
Dimensionless energy of the emitted line.

Returns
-------
float
The value of the integrand for the given parameters.
Copy link
Collaborator

@jsitarek jsitarek Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be useful to specify in which units the integrand is specified (I think it should be cm)

"""
(mu, phi, log_l) = cubepy_params_array
l = np.exp(log_l)
mu_star = mu_star_shell(mu, R_line.to_value('cm'), l)
_cos_psi = cos_psi(mu_s, mu_star, phi)
x = x_re_shell(mu, R_line.to_value('cm'), l)
s = epsilon_1 * epsilon_line * (1 - _cos_psi) / 2
integrand = (1 - _cos_psi) * l / x ** 2 * sigma(s).to_value("cm**2")
return integrand
@staticmethod
def evaluate_tau_blr_cubepy(
nu,
eps_abs,
z,
mu_s,
L_disk,
xi_line,
epsilon_line,
R_line,
r
):
"""Evaluates the gamma-gamma absorption produced by a spherical shell
BLR for a general set of model parameters using cubepy

Parameters
----------
nu : :class:`~astropy.units.Quantity`
array of frequencies, in Hz, to compute the tau
**note** these are observed frequencies (observer frame)
z : float
redshift of the source
mu_s : float
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function is following evaluate_tau_blr that is only valid for mu_s=1 (otherwise integration over path of the photon and over the distance from the black hole is not equivalent), so it should not have it as a parameter (@cosimoNigro can you also have a look at this?)

cosine of the angle between the blob motion and the jet axis
L_disk : :class:`~astropy.units.Quantity`
Luminosity of the disk whose radiation is being reprocessed by the BLR
xi_line : float
fraction of the disk radiation reprocessed by the BLR
epsilon_line : string
dimensionless energy of the emitted line
R_line : :class:`~astropy.units.Quantity`
radius of the BLR spherical shell
r : :class:`~astropy.units.Quantity`
distance between the Broad Line Region and the blob
mu, phi : :class:`~numpy.ndarray`
arrays of cosine of zenith and azimuth angles to integrate over

Returns
-------
:class:float
array of the tau values corresponding to each frequency
"""
# conversions
epsilon_1 = nu_to_epsilon_prime(nu, z)
# set boundary for integration
low = np.array(
[
[min(mu_to_integrate)],
[min(phi_to_integrate)],
[np.log(r.to_value('cm'))]
]
)
high = np.array(
[
[max(mu_to_integrate)],
[max(phi_to_integrate)],
[np.log(1e5*r.to_value('cm'))]
jsitarek marked this conversation as resolved.
Show resolved Hide resolved
]
)
prefactor = (L_disk * xi_line) / (
(4 * np.pi) ** 2 * epsilon_line * m_e * c ** 3
)

prefactor = prefactor.to("cm-1")
eps = eps_abs / prefactor.to_value("cm-1")
value, error = cp.integrate(Absorption.compute_integrand_for_blr,
low,
high,
abstol=eps,
args=(R_line, mu_s, epsilon_1, epsilon_line))
integral = value[0]*u.cm
return (prefactor * integral[0]).to_value("")

def tau_blr(self, nu):
"""Evaluates the gamma-gamma absorption produced by a spherical shell
BLR for a general set of model parameters
Expand Down Expand Up @@ -479,6 +586,67 @@ def tau_blr_mu_s(self, nu):
phi=self.phi,
)

def tau_blr_cubepy(self, nu, eps_abs=1e-6):
"""Evaluates the gamma-gamma absorption produced by a spherical shell
BLR for a general set of model parameters with cubepy integration
method
"""

tau_blr_list = []
for freq in nu:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem of using integrators as cubepy, that rely on functions, instead of trapz is that you do not get directly the output as an array but you are forced to loop over each frequency value. Anyhow, I think this is good for the moment.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, but since you do not have arrays you have much smaller memory usage, and the integration module automatically selects the points to evaluate the function in an optimal way, so a simple loop over frequencies is a small price to pay :-)

tau_blr_list.append(
self.evaluate_tau_blr_cubepy(
freq,
eps_abs,
self.z,
self.mu_s,
self.target.L_disk,
self.target.xi_line,
self.target.epsilon_line,
self.target.R_line,
self.r
)
)
return tau_blr_list

def tau_blr_all_lines_cubepy(self, nu, eps_abs=1e-6):
"""
Calculate the absorption in all available BLR (Broad Line Region) shells.
This function scales the radius and luminosity to the Hbeta line
and applies the computation to all the available BLR lines (shells) using
their respective ratios.

Parameters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about adding a dictionary 'lines' to the parameters (and setting it by default to lines_dictionary)
this would allow to run the function with limited number of lines (selecting only the most important ones for speed) or with modified dictionary (if we have more accurate measurements for a particular source). It would also facilitate tests because you could then implement a quick test on a dictionary of 2 lines

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, but what do you think about doing it in the "second" iteration (after merging this code with all lines into the main branch)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you prefer ok, but note that this is really minor change to the code, just adding a new parameter to the function, with a default value and then in the line 637 using this parameter instead of lines_dictionary.
And it would simplify implementation of my comment about tests

----------
nu: numpy array
Frequency array with unit
eps_abs: float, optional
Absolute precision for the calculation, default is 1e-6
"""
SUM_RATIO_LINES_BLR = 30.652
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcoding this is not safe, you should sum up the lines from the dictionary that you will use

XI_TARGET_LINE = self.target.xi_line
tau_z_all = np.zeros(nu.shape)

blr_shells = dict()
Copy link
Collaborator

@jsitarek jsitarek Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you define those dictionaries? I guess it is a remnant of a script where you were also plotting the effect of individual lines, but this is either way not possible this function.

here you are using the dictionaries only to sum up over all the lines, so you could instead created SphericalShellBLR and Absorption as temporary variables directly in the for loop

absorption_shells = dict()

# TODO write test
if self.target.line != "Hbeta":
raise KeyError("Please use Hbeta as reference")

for line_key in lines_dictionary.keys():
jsitarek marked this conversation as resolved.
Show resolved Hide resolved
xi_line_current = lines_dictionary[line_key]['L_Hbeta_ratio']
xi_line = (xi_line_current * XI_TARGET_LINE) / SUM_RATIO_LINES_BLR
R_line_current = self.target.R_line * lines_dictionary[line_key]['R_Hbeta_ratio']

blr_shells[line_key] = SphericalShellBLR(self.target.L_disk, xi_line, line_key, R_line_current)
absorption_shells[line_key] = Absorption(blr_shells[line_key], r=self.r, z=self.z)

tau_z_current = absorption_shells[line_key].tau_blr_cubepy(nu, eps_abs=eps_abs)
tau_z_all += tau_z_current

return tau_z_all

@staticmethod
def evaluate_tau_dt(
nu,
Expand Down
27 changes: 26 additions & 1 deletion agnpy/absorption/tests/test_absorption.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from agnpy.spectra import PowerLaw, BrokenPowerLaw
from agnpy.emission_regions import Blob
from agnpy.synchrotron import Synchrotron
from agnpy.targets import PointSourceBehindJet, SSDisk, SphericalShellBLR, RingDustTorus
from agnpy.targets import PointSourceBehindJet, SSDisk, SphericalShellBLR, RingDustTorus, lines_dictionary
from agnpy.absorption import Absorption, EBL
from agnpy.utils.math import axes_reshaper
from agnpy.utils.validation_utils import (
Expand Down Expand Up @@ -228,6 +228,31 @@ def test_abs_dt_vs_point_source(self):
# requires a 10% deviation from the two SED points
assert check_deviation(nu, tau_dt, tau_ps_dt, 0.1)

def test_abs_blr_cubepy(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test as it is written now does not test much: only if you do not have a crash because of not matching API, or some internal inconsistency in the code.
Instead you could run a test of comparing tau_blr_cubepy output with tau_blr

"""Checks for any errors that may occur during the execution of the function that
calculates absorption in BLR with cubepy."""
SUM_RATIO_LINES_BLR = 30.652
E = np.logspace(-1, 1, 20) * u.TeV
nu = E.to("Hz", equivalencies=u.spectral())
L_disk = 6e45 * u.Unit("erg s-1")
R_line = 2.45 * 1e17 * u.cm
r_blob_bh = 1e18 * u.cm
z = 1
XI_LINE = 0.1
blr_dict = dict()
ec_blr_dict = dict()
tau_z_all = np.zeros(nu.shape)
for line in list(lines_dictionary.keys()):
xi_line_this = lines_dictionary[line]['L_Hbeta_ratio']
xi_line = (xi_line_this * XI_LINE) / SUM_RATIO_LINES_BLR
R_line_this = R_line * lines_dictionary[line]['R_Hbeta_ratio']
blr_dict[line] = SphericalShellBLR(L_disk, xi_line, line, R_line_this)
ec_blr_dict[line] = Absorption(blr_dict[line], r=r_blob_bh, z=z)
tau_z_this = ec_blr_dict[line].tau_blr_cubepy(nu, eps_abs=1e-3)
tau_z_all += tau_z_this
assert True



def sigma_pp(b):
"""pair production cross section"""
Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ dependencies:
- pip:
- agnpy
- gammapy
- cubepy<=1.0.2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
],
install_requires=["astropy>=5.0, <6.0", "numpy>=1.21", "scipy>=1.5,!=1.10", "matplotlib>=3.4"],
install_requires=["astropy>=5.0, <6.0", "numpy>=1.21", "scipy>=1.5,!=1.10", "matplotlib>=3.4", "cubepy<=1.0.2"],
python_requires=">=3.8",
)