Skip to content

Commit bd6c6a6

Browse files
committed
Add new photolysis rates; reformat photo_timescale exception; light code reformatting.
1 parent dac9a95 commit bd6c6a6

5 files changed

Lines changed: 218 additions & 202 deletions

File tree

CHANGES.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,35 @@ Update supported versions [#419]:
1010
New Features
1111
------------
1212

13+
sbpy.activity.gas
14+
^^^^^^^^^^^^^^^^^
15+
16+
- Added active and quiet sun photolysis rates for H2O and CO2 from Huebner &
17+
Mukherjee 2015 to `sbpy.activity.gas.photo_timescale`. [#425]
18+
19+
1320
sbpy.names
1421
^^^^^^^^^^
22+
1523
- Added functionality to `sbpy.Names.from_packed()` and
1624
`sbpy.Names.to_packed()` to handle new extended provisional designations
1725
to be implemented by the MPC in anticipation of higher asteroid discovery
1826
rates in the LSST survey era [#406]
1927

28+
2029
API Changes
2130
-----------
31+
2232
- Deprecated `sbpy.ginga_plugins` in favor of using `sbpy-ginga` at
2333
https://github.com/NASA-Planetary-Science/sbpy-ginga [#413]
2434

35+
2536
sbpy.data.ephem
2637
^^^^^^^^^^^^^^^
2738

2839
- New command-line script: ``sbpy-ephem``. [#396]
2940

41+
3042
Other Changes and Additions
3143
---------------------------
3244

@@ -35,6 +47,7 @@ sbpy.activity.gas
3547
- Replaced calls to the deprecated function `scipy.integrate.romberg` with
3648
`scipy.integrate.quad`. [#412]
3749

50+
3851
sbpy.names
3952
^^^^^^^^^^
4053
- Fixed `sbpy.Names.to_packed()' to raise an error in cases of invalid
@@ -53,6 +66,7 @@ sbpy.names
5366
"P2015XN77"), which was previously being interpreted as a packed
5467
asteroid designation, but now raises a TargetNameParseError [#422]
5568

69+
5670
0.5.0 (2024-08-28)
5771
==================
5872

docs/sbpy/activity/gas.rst

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,42 @@ Two functions provide reference data for the photolysis of gas molecules in opti
2626
Use :func:`~sbpy.activity.gas.photo_timescale` to retrieve photolysis timescales:
2727

2828
>>> gas.photo_timescale(None)
29-
Traceback (most recent call last):
30-
...
31-
ValueError: Invalid species None. Choose from:
32-
CH3OH [C94]
33-
CN [H92]
34-
CO [CE83]
35-
CO2 [CE83]
36-
H2CO [C94]
37-
H2O [CS93]
38-
HCN [C94]
39-
OH [CS93]
29+
species source default tau bibcode
30+
------- ------ ------- ------------------- -------------------
31+
H2O CS93 True 52000.0 s 1993Icar..105..235C
32+
H2O HM15 False [82940. 49390.] s 2015P&SS..106...11H
33+
OH CS93 True 160000.0 s 1993Icar..105..235C
34+
HCN C94 True 67000.0 s 1994JGR....99.3777C
35+
CH3OH C94 True 77000.0 s 1994JGR....99.3777C
36+
H2CO C94 True 5000.0 s 1994JGR....99.3777C
37+
CO CE83 True 1500000.0 s 1983A&A...126..170C
38+
CO2 CE83 True 500000.0 s 1983A&A...126..170C
39+
CO2 HM15 False [494800. 210100.] s 2015P&SS..106...11H
40+
CN H92 True [315000. 135000.] s 1992Ap&SS.195....1H
41+
-------------------------------------------------------------------------
42+
ValueError Traceback (most recent call last)
43+
Cell In[1], line 1
44+
----> 1 photo_timescale()
45+
46+
File /disks/data0/astro/Projects/sbpy/sbpy/activity/gas/core.py:177, in photo_timescale(species, source)
47+
167 rows.append(
48+
168 {
49+
169 "species": sp,
50+
(...)
51+
174 }
52+
175 )
53+
176 Table(rows).pprint_all()
54+
--> 177 raise ValueError("Invalid species {}".format(species))
55+
179 gas = data[species]
56+
180 source = default_sources[species] if source is None else source
57+
58+
ValueError: Invalid species None
59+
4060
>>> gas.photo_timescale('H2O') # doctest: +FLOAT_CMP
4161
<Quantity 52000. s>
4262

43-
Some sources provide values for the quiet and active Sun (Huebner et al. 1992):
63+
Some sources provide values for the quiet and active Sun (e.g., Huebner et al.
64+
1992):
4465

4566
>>> gas.photo_timescale('CN', source='H92') # doctest: +FLOAT_CMP
4667
<Quantity [315000., 135000.] s>

sbpy/activity/gas/core.py

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2-
"""activity.gas core
3-
4-
"""
2+
"""activity.gas core"""
53

64
__all__ = [
75
"photo_lengthscale",
@@ -18,6 +16,7 @@
1816

1917
import numpy as np
2018
import astropy.units as u
19+
from astropy.table import Table
2120

2221
try:
2322
import scipy
@@ -86,8 +85,7 @@ def photo_lengthscale(species, source=None):
8685
for k, v in sorted(data.items()):
8786
summary += "\n{} [{}]".format(k, ", ".join(v.keys()))
8887

89-
raise ValueError(
90-
"Invalid species {}. Choose from:{}".format(species, summary))
88+
raise ValueError("Invalid species {}. Choose from:{}".format(species, summary))
9189

9290
gas = data[species]
9391
source = default_sources[species] if source is None else source
@@ -105,24 +103,25 @@ def photo_lengthscale(species, source=None):
105103
return gamma
106104

107105

108-
def photo_timescale(species, source=None):
106+
def photo_timescale(species=None, source=None):
109107
"""Photodissociation timescale for a gas species.
110108
111109
112110
Parameters
113111
----------
114-
species : string
115-
Species to look up.
112+
species : string, optional
113+
Species to look up. Use ``None`` to show a list of all species and
114+
sources.
116115
117116
source : string, optional
118-
Retrieve values from this source. See references for keys.
117+
Retrieve values from this source. See References for keys.
119118
120119
121120
Returns
122121
-------
123122
tau : `~astropy.units.Quantity`
124-
The timescale at 1 au. May be a two-element array: (quiet Sun,
125-
active Sun).
123+
The timescale at 1 au. May be a two-element array: (quiet Sun, active
124+
Sun).
126125
127126
128127
Examples
@@ -133,15 +132,17 @@ def photo_timescale(species, source=None):
133132
134133
References
135134
----------
136-
[CS93] Table IV of Cochran & Schleicher 1993, Icarus 105, 235-253.
137-
Quoted for intermediate solar activity.
135+
[CS93] Table IV of Cochran & Schleicher 1993, Icarus 105, 235-253. Quoted
136+
for intermediate solar activity.
138137
139138
[C94] Crovisier 1994, JGR 99, 3777-3781.
140139
141140
[CE83] Crovisier & Encrenaz 1983, A&A 126, 170-182.
142141
143142
[H92] Huebner et al. 1992, Astroph. & Space Sci. 195, 1-294.
144143
144+
[HM15] Huebner and Mukherjee 2015, Plan. & Space Sci. 106, 11-45.
145+
145146
"""
146147

147148
from .data import photo_timescale as data
@@ -158,12 +159,20 @@ def photo_timescale(species, source=None):
158159
}
159160

160161
if species not in data:
161-
summary = ""
162-
for k, v in sorted(data.items()):
163-
summary += "\n{} [{}]".format(k, ", ".join(v.keys()))
164-
165-
raise ValueError(
166-
"Invalid species {}. Choose from:{}".format(species, summary))
162+
rows = []
163+
for sp, sources in data.items():
164+
for source, (tau, bibcode) in sources.items():
165+
rows.append(
166+
{
167+
"species": sp,
168+
"source": source,
169+
"default": source == default_sources[sp],
170+
"tau": tau,
171+
"bibcode": ",".join(bibcode.values()),
172+
}
173+
)
174+
Table(rows).pprint_all()
175+
raise ValueError("Invalid species {}".format(species))
167176

168177
gas = data[species]
169178
source = default_sources[species] if source is None else source
@@ -549,9 +558,7 @@ def f(rho, sigma):
549558
550559
"""
551560
return (
552-
rho
553-
* np.exp(-(rho**2) / sigma**2 / 2)
554-
* self._column_density(rho)
561+
rho * np.exp(-(rho**2) / sigma**2 / 2) * self._column_density(rho)
555562
)
556563

557564
sigma = aper.sigma.to_value("m")
@@ -662,12 +669,7 @@ def _total_number(self, aper):
662669
daughter = self.daughter.to(rho.unit)
663670
y = (rho / daughter).to_value("")
664671
N *= (daughter / (parent - daughter)).to_value("") * (
665-
self._iK0(y)
666-
- self._iK0(x)
667-
+ x**-1
668-
- y**-1
669-
+ self._K1(y)
670-
- self._K1(x)
672+
self._iK0(y) - self._iK0(x) + x**-1 - y**-1 + self._K1(y) - self._K1(x)
671673
)
672674

673675
return N
@@ -692,6 +694,7 @@ class VMParent:
692694
sigma : float
693695
See VectorialModel documentation.
694696
"""
697+
695698
v_outflow: float
696699
tau_d: float
697700
tau_T: float
@@ -711,6 +714,7 @@ class VMFragment:
711714
tau_T : float
712715
See VectorialModel documentation.
713716
"""
717+
714718
v_photo: float
715719
tau_T: float
716720

@@ -733,6 +737,7 @@ class VMGridParams:
733737
radial_substeps : int
734738
See VectorialModel documentation.
735739
"""
740+
736741
radial_points: int
737742
angular_points: int
738743
radial_substeps: int
@@ -755,6 +760,7 @@ class VMParams:
755760
max_fragment_lifetimes : float
756761
See VectorialModel documentation.
757762
"""
763+
758764
parent_destruction_level: float
759765
fragment_destruction_level: float
760766
max_fragment_lifetimes: float
@@ -780,6 +786,7 @@ class VMFragmentSputterPolar:
780786
List of fragment densities at the corresponding ``rs[i]`` and
781787
``thetas[j]``.
782788
"""
789+
783790
rs: np.ndarray
784791
thetas: np.ndarray
785792
fragment_density: np.ndarray
@@ -861,6 +868,7 @@ class VMResult:
861868
will also measure how long the effects of a single outburst can affect
862869
the density.
863870
"""
871+
864872
volume_density_grid: np.ndarray = None
865873
volume_density: np.ndarray = None
866874
column_density_grid: np.ndarray = None
@@ -1275,13 +1283,11 @@ def _setup_calculations(self) -> None:
12751283
# occupy)
12761284
# NOTE: Equation (16) of Festou 1981 where alpha is the percent
12771285
# destruction of molecules
1278-
parent_beta_r = - \
1279-
np.log(1.0 - self.model_params.parent_destruction_level)
1286+
parent_beta_r = -np.log(1.0 - self.model_params.parent_destruction_level)
12801287
parent_r = parent_beta_r * vp * self.parent.tau_T
12811288
self.vmr.coma_radius = parent_r * u.m
12821289

1283-
fragment_beta_r = - \
1284-
np.log(1.0 - self.model_params.fragment_destruction_level)
1290+
fragment_beta_r = -np.log(1.0 - self.model_params.fragment_destruction_level)
12851291
# Calculate the time needed to hit a steady, permanent production of
12861292
# fragments
12871293
perm_flow_radius = self.vmr.coma_radius.value + (
@@ -1510,8 +1516,7 @@ def _fragment_sputter(self, r: np.float64, theta: np.float64) -> np.float64:
15101516

15111517
# differential addition to the density integrating along dr,
15121518
# similar to eq. (36) Festou 1981
1513-
n_r = (p_extinction * f_extinction *
1514-
q_r_eps) / (sep_dist**2 * v)
1519+
n_r = (p_extinction * f_extinction * q_r_eps) / (sep_dist**2 * v)
15151520

15161521
sputter += n_r * dr
15171522

@@ -1567,8 +1572,7 @@ def _compute_fragment_density(self) -> None:
15671572
# Equivalent to summing over j for sin(theta[j]) *
15681573
# fragment_sputter[i][j] with numpy magic
15691574
self.solid_angle_sputter = np.sin(thetas) * self.fragment_sputter
1570-
self.fast_voldens = 2.0 * np.pi * \
1571-
np.sum(self.solid_angle_sputter, axis=1)
1575+
self.fast_voldens = 2.0 * np.pi * np.sum(self.solid_angle_sputter, axis=1)
15721576

15731577
# Tag with proper units
15741578
self.vmr.volume_density = self.fast_voldens / (u.m**3)
@@ -1633,8 +1637,7 @@ def _column_density_at_rho(self, rho: np.float64) -> np.float64:
16331637
def column_density_integrand(z):
16341638
return self._volume_density(np.sqrt(z**2 + rhosq))
16351639

1636-
c_dens = 2 * quad(column_density_integrand, 0,
1637-
z_max, epsrel=0.0001)[0]
1640+
c_dens = 2 * quad(column_density_integrand, 0, z_max, epsrel=0.0001)[0]
16381641

16391642
# result is in 1/m^2
16401643
return c_dens
@@ -1709,8 +1712,7 @@ def _calc_num_fragments_theory(self) -> np.float64:
17091712
for i, t in enumerate(time_slices[:-1]):
17101713
extinction_one = t / p_tau_T
17111714
extinction_two = time_slices[i + 1] / p_tau_T
1712-
mult_factor = -np.e ** (-extinction_one) + \
1713-
np.e ** (-extinction_two)
1715+
mult_factor = -np.e ** (-extinction_one) + np.e ** (-extinction_two)
17141716
theory_total += self.production_at_time(t) * mult_factor
17151717

17161718
return theory_total * alpha - edge_adjust

0 commit comments

Comments
 (0)