xdust 1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. xdust-1.0/LICENSE +25 -0
  2. xdust-1.0/PKG-INFO +68 -0
  3. xdust-1.0/README.md +43 -0
  4. xdust-1.0/pyproject.toml +43 -0
  5. xdust-1.0/setup.cfg +4 -0
  6. xdust-1.0/setup.py +5 -0
  7. xdust-1.0/src/xdust/__init__.py +5 -0
  8. xdust-1.0/src/xdust/graindist/__init__.py +6 -0
  9. xdust-1.0/src/xdust/graindist/composition/__init__.py +165 -0
  10. xdust-1.0/src/xdust/graindist/composition/cmdrude.py +72 -0
  11. xdust-1.0/src/xdust/graindist/composition/cmgraphite.py +61 -0
  12. xdust-1.0/src/xdust/graindist/composition/cmsilicate.py +32 -0
  13. xdust-1.0/src/xdust/graindist/composition/minerals.py +91 -0
  14. xdust-1.0/src/xdust/graindist/graindist.py +190 -0
  15. xdust-1.0/src/xdust/graindist/shape/__init__.py +42 -0
  16. xdust-1.0/src/xdust/graindist/shape/sphere.py +54 -0
  17. xdust-1.0/src/xdust/graindist/sizedist/__init__.py +85 -0
  18. xdust-1.0/src/xdust/graindist/sizedist/astrodust.py +137 -0
  19. xdust-1.0/src/xdust/graindist/sizedist/exp_cutoff.py +130 -0
  20. xdust-1.0/src/xdust/graindist/sizedist/grain.py +74 -0
  21. xdust-1.0/src/xdust/graindist/sizedist/powerlaw.py +126 -0
  22. xdust-1.0/src/xdust/graindist/sizedist/weingartner.py +366 -0
  23. xdust-1.0/src/xdust/graindist/tables/PAHion_30 +36129 -0
  24. xdust-1.0/src/xdust/graindist/tables/PAHneu_30 +36129 -0
  25. xdust-1.0/src/xdust/graindist/tables/Table1.WD.dat +22 -0
  26. xdust-1.0/src/xdust/graindist/tables/Table3_LMC2.WD.dat +10 -0
  27. xdust-1.0/src/xdust/graindist/tables/Table3_LMCavg.WD.dat +9 -0
  28. xdust-1.0/src/xdust/graindist/tables/Table3_SMC.WD.dat +7 -0
  29. xdust-1.0/src/xdust/graindist/tables/callindex.out_CpaD03_0.01 +391 -0
  30. xdust-1.0/src/xdust/graindist/tables/callindex.out_CpaD03_0.10 +391 -0
  31. xdust-1.0/src/xdust/graindist/tables/callindex.out_CpeD03_0.01 +388 -0
  32. xdust-1.0/src/xdust/graindist/tables/callindex.out_CpeD03_0.10 +388 -0
  33. xdust-1.0/src/xdust/graindist/tables/callindex.out_sil.D03 +842 -0
  34. xdust-1.0/src/xdust/grainpop.py +587 -0
  35. xdust-1.0/src/xdust/halos/__init__.py +2 -0
  36. xdust-1.0/src/xdust/halos/galhalo.py +605 -0
  37. xdust-1.0/src/xdust/halos/halo.py +449 -0
  38. xdust-1.0/src/xdust/helpers.py +103 -0
  39. xdust-1.0/src/xdust/scatteringmodel/__init__.py +247 -0
  40. xdust-1.0/src/xdust/scatteringmodel/ggadt.py +21 -0
  41. xdust-1.0/src/xdust/scatteringmodel/make_ggadt.py +243 -0
  42. xdust-1.0/src/xdust/scatteringmodel/make_ggadt_astrodust.py +157 -0
  43. xdust-1.0/src/xdust/scatteringmodel/miescat.py +340 -0
  44. xdust-1.0/src/xdust/scatteringmodel/pah.py +182 -0
  45. xdust-1.0/src/xdust/scatteringmodel/rgscat.py +131 -0
  46. xdust-1.0/src/xdust.egg-info/PKG-INFO +68 -0
  47. xdust-1.0/src/xdust.egg-info/SOURCES.txt +57 -0
  48. xdust-1.0/src/xdust.egg-info/dependency_links.txt +1 -0
  49. xdust-1.0/src/xdust.egg-info/requires.txt +14 -0
  50. xdust-1.0/src/xdust.egg-info/top_level.txt +1 -0
  51. xdust-1.0/tests/test_cmindex.py +58 -0
  52. xdust-1.0/tests/test_galhalo.py +169 -0
  53. xdust-1.0/tests/test_ggadt_file.py +149 -0
  54. xdust-1.0/tests/test_graindist.py +73 -0
  55. xdust-1.0/tests/test_grainpop.py +168 -0
  56. xdust-1.0/tests/test_inits.py +36 -0
  57. xdust-1.0/tests/test_scatmodels.py +162 -0
  58. xdust-1.0/tests/test_shape.py +18 -0
  59. xdust-1.0/tests/test_sizedist.py +66 -0
xdust-1.0/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2017, Lia Corrales
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
xdust-1.0/PKG-INFO ADDED
@@ -0,0 +1,68 @@
1
+ Metadata-Version: 2.4
2
+ Name: xdust
3
+ Version: 1.0
4
+ Summary: Library of dust scattering codes
5
+ Author-email: Lia Corrales <liac@umich.edu>
6
+ License: BSD 2-clause
7
+ Project-URL: Homepage, https://github.com/eblur/xdust
8
+ Project-URL: Documentation, https://eblur.github.io/xdust
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy
13
+ Requires-Dist: astropy
14
+ Requires-Dist: scipy
15
+ Requires-Dist: matplotlib
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=7.0; extra == "dev"
18
+ Provides-Extra: docs
19
+ Requires-Dist: sphinx>=7.0; extra == "docs"
20
+ Requires-Dist: furo; extra == "docs"
21
+ Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
22
+ Requires-Dist: sphinx-autobuild; extra == "docs"
23
+ Requires-Dist: myst-nb; extra == "docs"
24
+ Dynamic: license-file
25
+
26
+ # Xdust
27
+
28
+
29
+ *Previously eblur/newdust*
30
+
31
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7500048.svg)](https://doi.org/10.5281/zenodo.7500048)
32
+
33
+ This package calculates extinction curves and small-angle scattering halos from a user-defined dust grain size distribution. It calculates scattering and absorption from first principles (optical constants of the material, Mie or Rayleigh-Gans scattering).
34
+
35
+ **Updated 2026.06** to by installable via PyPI and documented with Sphinx
36
+
37
+ **Documentation:** https://eblur.github.io/xdust
38
+
39
+ ## Installation
40
+
41
+ ### Typical installation
42
+
43
+ ```
44
+ pip install xdust
45
+ ```
46
+
47
+ ### For developers
48
+
49
+ If you need to stay up to date with development versions of xdust, use:
50
+
51
+ ```
52
+ git clone https://github.com/eblur/xdust.git
53
+
54
+ cd xdust
55
+
56
+ pip install -e .
57
+ ```
58
+
59
+ ## To invoke:
60
+
61
+ ```
62
+ import xdust
63
+ ```
64
+
65
+ ## How to use:
66
+
67
+ See the jupyter notebooks in **examples/**
68
+ for examples of setting up grain populations and modeling scattering halos from Galactic dust.
xdust-1.0/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Xdust
2
+
3
+
4
+ *Previously eblur/newdust*
5
+
6
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7500048.svg)](https://doi.org/10.5281/zenodo.7500048)
7
+
8
+ This package calculates extinction curves and small-angle scattering halos from a user-defined dust grain size distribution. It calculates scattering and absorption from first principles (optical constants of the material, Mie or Rayleigh-Gans scattering).
9
+
10
+ **Updated 2026.06** to by installable via PyPI and documented with Sphinx
11
+
12
+ **Documentation:** https://eblur.github.io/xdust
13
+
14
+ ## Installation
15
+
16
+ ### Typical installation
17
+
18
+ ```
19
+ pip install xdust
20
+ ```
21
+
22
+ ### For developers
23
+
24
+ If you need to stay up to date with development versions of xdust, use:
25
+
26
+ ```
27
+ git clone https://github.com/eblur/xdust.git
28
+
29
+ cd xdust
30
+
31
+ pip install -e .
32
+ ```
33
+
34
+ ## To invoke:
35
+
36
+ ```
37
+ import xdust
38
+ ```
39
+
40
+ ## How to use:
41
+
42
+ See the jupyter notebooks in **examples/**
43
+ for examples of setting up grain populations and modeling scattering halos from Galactic dust.
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "xdust"
7
+ version = "1.0"
8
+ description = "Library of dust scattering codes"
9
+ authors = [
10
+ { name = "Lia Corrales", email = "liac@umich.edu" }
11
+ ]
12
+ readme = "README.md"
13
+ license = { text = "BSD 2-clause" }
14
+ requires-python = ">=3.7"
15
+ dependencies = [
16
+ "numpy",
17
+ "astropy",
18
+ "scipy",
19
+ "matplotlib"
20
+ ]
21
+
22
+ [project.optional-dependencies]
23
+ dev = ["pytest>=7.0"]
24
+ docs = [
25
+ "sphinx>=7.0",
26
+ "furo",
27
+ "sphinx-autodoc-typehints",
28
+ "sphinx-autobuild",
29
+ "myst-nb"
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/eblur/xdust"
34
+ Documentation = "https://eblur.github.io/xdust"
35
+
36
+ [tool.setuptools.packages.find]
37
+ where = ["src"]
38
+
39
+ [tool.setuptools.package-data]
40
+ xdust = [
41
+ "graindist/tables/*",
42
+ "scatteringmodel/tables/*",
43
+ ]
xdust-1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
xdust-1.0/setup.py ADDED
@@ -0,0 +1,5 @@
1
+
2
+ #! /usr/bin/env python
3
+ # Configuration has moved to pyproject.toml
4
+ from setuptools import setup
5
+ setup()
@@ -0,0 +1,5 @@
1
+ from . import helpers
2
+ from . import graindist
3
+ from . import scatteringmodel
4
+ from . import halos
5
+ from .grainpop import *
@@ -0,0 +1,6 @@
1
+
2
+ from . import sizedist
3
+ from . import composition
4
+ from . import shape
5
+
6
+ from .graindist import *
@@ -0,0 +1,165 @@
1
+ import os
2
+ import numpy as np
3
+ import astropy.units as u
4
+
5
+ GTYPES = ['Graphite', 'Silicate', 'Drude']
6
+
7
+ def _find_cmfile(name):
8
+ root_path = os.path.dirname(__file__).rstrip('composition')
9
+ data_path = root_path + 'tables/'
10
+ return data_path + name
11
+
12
+ class Composition(object):
13
+ """
14
+ Composition class for storing information about grain material
15
+
16
+ Attributes
17
+ ----------
18
+ cmtype : str
19
+ Label for the compound.
20
+
21
+ rho : float
22
+ Density of the material [g cm^-3].
23
+
24
+ citation : str
25
+ Citation for the optical constants loaded.
26
+
27
+ wavel : astropy.units.Quantity
28
+ Wavelength grid for optical constants.
29
+
30
+ revals : numpy.ndarray
31
+ Real part of the complex index of refraction.
32
+
33
+ imvals : numpy.ndarray
34
+ Imaginary part of the complex index of refraction.
35
+ """
36
+ def __init__(self):
37
+ self.cmtype = None
38
+ self.rho = None
39
+ self.citation = None
40
+ self.wavel = None
41
+ self.revals = 1.0
42
+ self.imvals = 0.0
43
+
44
+ def rp(self, x):
45
+ """
46
+ Interpolate over the input wavelength grid to get the real part of the
47
+ complex index of refraction.
48
+
49
+ Parameters
50
+ ----------
51
+ x : astropy.units.Quantity or numpy.ndarray
52
+ Wavelength or energy; if an ``astropy.units.Quantity``, converted to
53
+ the same units as ``self.wavel``; if a plain array, keV units are assumed.
54
+
55
+ Returns
56
+ -------
57
+ numpy.ndarray
58
+ ``np.interp(x, self.wavel, self.revals, left=1.0, right=1.0)``
59
+ """
60
+ # If the input is an astropy quantity, convert it to the same unit as wavel
61
+ if isinstance(x, u.Quantity):
62
+ new_x = x.to(self.wavel.unit, equivalencies=u.spectral()).value
63
+ # Otherwise, assume the unit is keV
64
+ else:
65
+ new_x = (x * u.keV).to(self.wavel.unit, equivalencies=u.spectral()).value
66
+ return np.interp(new_x, self.wavel.value, self.revals, left=1.0, right=1.0)
67
+
68
+ def ip(self, x):
69
+ """
70
+ Interpolate over the input wavelength grid to get the imaginary part of the
71
+ complex index of refraction.
72
+
73
+ Parameters
74
+ ----------
75
+ x : astropy.units.Quantity or numpy.ndarray
76
+ Wavelength or energy; if an ``astropy.units.Quantity``, converted to
77
+ the same units as ``self.wavel``; if a plain array, keV units are assumed.
78
+
79
+ Returns
80
+ -------
81
+ numpy.ndarray
82
+ ``np.interp(x, self.wavel, self.imvals, left=0.0, right=0.0)``
83
+ """
84
+ # If the input is an astropy quantity, convert it to the same unit as wavel
85
+ if isinstance(x, u.Quantity):
86
+ new_x = x.to(self.wavel.unit, equivalencies=u.spectral()).value
87
+ # Otherwise, assume the unit is keV
88
+ else:
89
+ new_x = (x * u.keV).to(self.wavel.unit, equivalencies=u.spectral()).value
90
+ return np.interp(new_x, self.wavel.value, self.imvals, left=0.0, right=0.0)
91
+
92
+ def cm(self, x):
93
+ """
94
+ Returns the complex index of refraction using Python complex numbers
95
+
96
+ Parameters
97
+ ----------
98
+ x : astropy.units.Quantity or numpy.ndarray
99
+ Wavelength or energy; if an ``astropy.units.Quantity``, converted to
100
+ the same units as ``self.wavel``; if a plain array, keV units are assumed.
101
+
102
+ Returns
103
+ -------
104
+ complex or numpy.ndarray of complex
105
+ Complex index of refraction :math:`n = n_r + i n_i`.
106
+ """
107
+ return self.rp(x) + 1j * self.ip(x)
108
+
109
+ def plot(self, ax, lam=None, rppart=True, impart=True, xunit=None, label=''):
110
+ """
111
+ Plots the different parts of the complex index of refraction on a matplotlib axis
112
+
113
+ Parameters
114
+ ----------
115
+ ax : matplotlib.pyplot.Axes
116
+ The axes on which to plot.
117
+
118
+ lam : astropy.units.Quantity or numpy.ndarray, optional
119
+ If ``None``, plots using the default ``self.wavel`` grid; otherwise
120
+ interpolates onto the provided grid. Plain arrays are assumed to be
121
+ in keV.
122
+
123
+ rppart : bool
124
+ If ``True`` (default), plot the real part :math:`|Re(m)-1|`.
125
+
126
+ impart : bool
127
+ If ``True`` (default), plot the imaginary part :math:`Im(m)`.
128
+
129
+ xunit : str, optional
130
+ Unit string for the x-axis. Defaults to ``self.wavel.unit``.
131
+
132
+ label : str
133
+ Prefix string appended to legend labels.
134
+ """
135
+ if xunit is None:
136
+ xunit = self.wavel.unit
137
+ # If no grid specified, plot the default one
138
+ if lam is None:
139
+ rp_m1 = np.abs(self.revals - 1.0)
140
+ ip = self.imvals
141
+ x = self.wavel.to(xunit, equivalencies=u.spectral()).value
142
+ # Else, plot the interpolated values
143
+ else:
144
+ rp_m1 = np.abs(self.rp(lam)-1.0)
145
+ ip = self.ip(lam)
146
+ # Check if the input value had units
147
+ if isinstance(lam, u.Quantity):
148
+ x = lam.to(xunit, equivalencies=u.spectral()).value
149
+ # If not, assume keV units
150
+ else:
151
+ x = (lam * u.keV).to(xunit, equivalencies=u.spectral()).value
152
+ # If the user wants to plot Real Part
153
+ if rppart:
154
+ ax.plot(x, rp_m1, ls='-', label='{} |Re(m-1)|'.format(label))
155
+ # If the user wants to plot Imaginary Part
156
+ if impart:
157
+ ax.plot(x, ip, ls='--', label='{} Im(m)'.format(label))
158
+ ax.set_xlabel(xunit)
159
+ ax.legend()
160
+
161
+
162
+
163
+ from .cmdrude import CmDrude
164
+ from .cmsilicate import CmSilicate
165
+ from .cmgraphite import CmGraphite
@@ -0,0 +1,72 @@
1
+ import numpy as np
2
+ import astropy.units as u
3
+ import astropy.constants as c
4
+
5
+ from . import Composition
6
+
7
+ __all__ = ['CmDrude']
8
+
9
+ RHO_DRUDE = 3.0 # g cm^-3
10
+
11
+ ## -- Some constants to use for the calculation
12
+ # Classical electron radius
13
+ RE_CM = 2.8179403227e-15 * u.m.to('cm')
14
+ # Mass of proton
15
+ MP_G = c.m_p.to('g').value
16
+
17
+ class CmDrude(Composition):
18
+ """
19
+ Optical constants under the Drude approximation.
20
+ """
21
+ def __init__(self, rho=RHO_DRUDE): # Returns a CM using the Drude approximation
22
+ Composition.__init__(self)
23
+ self.cmtype = 'Drude'
24
+ self.rho = rho
25
+ self.citation = "Using the Drude approximation.\nBohren, C. F. & Huffman, D. R., 1983, Absorption and Scattering of Light by Small Particles (New York: Wiley)"
26
+
27
+ # Set up default values so that inherited plotting method from Composition will work
28
+ self.wavel = np.linspace(1.0, 10.0, 50) * u.keV
29
+ self.revals = self.rp(self.wavel)
30
+ self.imvals = self.ip(self.wavel)
31
+
32
+ def rp(self, x):
33
+ """
34
+ Calculate the real part of the complex index of refraction under the Drude approximation.
35
+
36
+ Parameters
37
+ ----------
38
+ x : astropy.units.Quantity or numpy.ndarray
39
+ Wavelength or energy; plain arrays are assumed to be in keV.
40
+
41
+ Returns
42
+ -------
43
+ numpy.ndarray
44
+ :math:`1 + (\\rho / 2 m_p)(r_e / 2\\pi)\\lambda^2`
45
+ """
46
+ if isinstance(x, u.Quantity):
47
+ lam_cm = x.to('cm', equivalencies=u.spectral()).value
48
+ else:
49
+ lam_cm = (x * u.keV).to('cm', equivalencies=u.spectral()).value
50
+
51
+ mm1 = self.rho / (2.0*MP_G) * RE_CM/(2.0*np.pi) * np.power(lam_cm, 2)
52
+ return mm1 + 1.0
53
+
54
+ def ip(self, x):
55
+ """
56
+ Gives the imaginary part of the complex index of refraction under the Drude approximation.
57
+
58
+ Parameters
59
+ ----------
60
+ x : astropy.units.Quantity or numpy.ndarray
61
+ Wavelength or energy; plain arrays are assumed to be in keV.
62
+
63
+ Returns
64
+ -------
65
+ float or numpy.ndarray
66
+ ``0.0`` for scalar input; array of zeros matching the length of ``x``
67
+ for array input.
68
+ """
69
+ if np.size(x) > 1:
70
+ return np.zeros(np.size(x))
71
+ else:
72
+ return 0.0
@@ -0,0 +1,61 @@
1
+ import numpy as np
2
+ from astropy.io import ascii
3
+ from astropy import units as u
4
+
5
+ from . import _find_cmfile
6
+ from . import Composition
7
+
8
+ __all__ = ['CmGraphite']
9
+
10
+ RHO_GRA = 2.2 # g cm^-3
11
+
12
+ class CmGraphite(Composition):
13
+ """
14
+ Optical constants for Graphite from
15
+ `Draine (2003), ApJ 598, 1026 <http://adsabs.harvard.edu/abs/2003ApJ...598.1026D>`_
16
+
17
+ Attributes
18
+ ----------
19
+ size : str
20
+ ``'big'`` gives results for 0.1 um sized graphite grains at 20 K;
21
+ ``'small'`` gives results for 0.01 um sized grains at 20 K.
22
+
23
+ orient : str
24
+ ``'perp'`` gives results for E-field perpendicular to the c-axis;
25
+ ``'para'`` gives results for E-field parallel to the c-axis.
26
+ """
27
+ def __init__(self, rho=RHO_GRA, size='big', orient='perp'):
28
+ Composition.__init__(self)
29
+ self.cmtype = 'Graphite'
30
+ self.rho = rho
31
+ self.citation = "Using optical constants for graphite,\nDraine, B. T. 2003, ApJ, 598, 1026\nhttp://adsabs.harvard.edu/abs/2003ApJ...598.1026D"
32
+ # Additional info not in default class
33
+ self.size = size
34
+ self.orient = orient
35
+
36
+ # Populate the wavelength and optical constants info
37
+ if size == 'big':
38
+ D03file_para = _find_cmfile('callindex.out_CpaD03_0.10')
39
+ D03file_perp = _find_cmfile('callindex.out_CpeD03_0.10')
40
+ if size == 'small':
41
+ D03file_para = _find_cmfile('callindex.out_CpaD03_0.01')
42
+ D03file_perp = _find_cmfile('callindex.out_CpeD03_0.01')
43
+
44
+ D03dat_para = ascii.read(D03file_para, header_start=4, data_start=5)
45
+ D03dat_perp = ascii.read(D03file_perp, header_start=4, data_start=5)
46
+
47
+ # The wavelength grid needs to be in ascending order
48
+ # for np.interp to run correctly
49
+ if orient == 'perp':
50
+ wavel = D03dat_perp['wave(um)'] * u.micron
51
+ wsort = np.argsort(wavel.value)
52
+ self.wavel = wavel[wsort]
53
+ self.revals = 1.0 + D03dat_perp['Re(n)-1'][wsort]
54
+ self.imvals = D03dat_perp['Im(n)'][wsort]
55
+
56
+ if orient == 'para':
57
+ wavel = D03dat_para['wave(um)'] * u.micron
58
+ wsort = np.argsort(wavel)
59
+ self.wavel = wavel[wsort]
60
+ self.revals = 1.0 + D03dat_para['Re(n)-1'][wsort]
61
+ self.imvals = D03dat_para['Im(n)'][wsort]
@@ -0,0 +1,32 @@
1
+ import numpy as np
2
+ from astropy.io import ascii
3
+ from astropy import units as u
4
+
5
+ from . import _find_cmfile
6
+ from . import Composition
7
+
8
+ __all__ = ['CmSilicate']
9
+
10
+ RHO_SIL = 3.8 # g cm^-3
11
+
12
+ class CmSilicate(Composition):
13
+ """
14
+ Optical constants for Silicate from
15
+ `Draine (2003), ApJ 598, 1026 <http://adsabs.harvard.edu/abs/2003ApJ...598.1026D>`_
16
+ """
17
+ def __init__(self, rho=RHO_SIL):
18
+ Composition.__init__(self)
19
+ self.cmtype = 'Silicate'
20
+ self.rho = rho
21
+ self.citation = "Using optical constants for astrosilicate,\nDraine, B. T. 2003, ApJ, 598, 1026\nhttp://adsabs.harvard.edu/abs/2003ApJ...598.1026D"
22
+
23
+ D03file = _find_cmfile('callindex.out_sil.D03')
24
+ D03dat = ascii.read(D03file, header_start=4, data_start=5)
25
+
26
+ # The wavelength grid needs to be in ascending order for np.interp to run correctly
27
+ wavel = D03dat['wave(um)'] * u.micron
28
+ wsort = np.argsort(wavel.value)
29
+
30
+ self.wavel = wavel[wsort]
31
+ self.revals = 1.0 + D03dat['Re(n)-1'][wsort]
32
+ self.imvals = D03dat['Im(n)'][wsort]
@@ -0,0 +1,91 @@
1
+ #
2
+ # minerals.py -- Some tables for ISM abundances and depletion factors
3
+ # that are useful for calculating dust mass and dust-to-gas ratios
4
+ #
5
+ # 2016.01.22 - lia@space.mit.edu
6
+ ##----------------------------------------------------------------
7
+
8
+ import numpy as np
9
+
10
+ amu = {'H':1.008,'He':4.0026,'C':12.011,'N':14.007,'O':15.999,'Ne':20.1797,
11
+ 'Na':22.989,'Mg':24.305,'Al':26.981,'Si':28.085,'P':30.973,'S':32.06,
12
+ 'Cl':35.45,'Ar':39.948,'Ca':40.078,'Ti':47.867,'Cr':51.9961,'Mn':54.938,
13
+ 'Fe':55.845,'Co':58.933,'Ni':58.6934}
14
+ amu_g = 1.661e-24 # g
15
+ mp = 1.673e-24 # g (proton mass)
16
+
17
+ wilms = {'H':12.0, 'He':10.99, 'C':8.38, 'N':7.88, 'O':8.69, 'Ne':7.94,
18
+ 'Na':6.16, 'Mg':7.40, 'Al':6.33, 'Si':7.27, 'P':5.42, 'S':7.09,
19
+ 'Cl':5.12, 'Ar':6.41, 'Ca':6.20, 'Ti':4.81, 'Cr':5.51, 'Mn':5.34,
20
+ 'Fe':7.43, 'Co':4.92, 'Ni':6.05} # 12 + log A_z
21
+
22
+ # Fraction of elements still in gas form
23
+ wilms_1mbeta = {'H':1.0, 'He':1.0, 'C':0.5, 'N':1.0, 'O':0.6, 'Ne':1.0, 'Na':0.25,
24
+ 'Mg':0.2, 'Al':0.02, 'Si':0.1, 'P':0.6, 'S':0.6, 'Cl':0.5, 'Ar':1.0,
25
+ 'Ca':0.003, 'Ti':0.002, 'Cr':0.03, 'Mn':0.07, 'Fe':0.3, 'Co':0.05,
26
+ 'Ni':0.04}
27
+
28
+ class Mineral(object):
29
+ """
30
+ | Use a dictionary to define the composition.
31
+ | e.g. Olivines of pure MgFe^{2+}SiO_4 composition would be
32
+ | olivine_halfMg = Mineral( {'Mg':1.0, 'Fe':1.0, 'Si':1.0, 'O':4.0} )
33
+ | self.composition : dictionary containing elements and their weights
34
+ |
35
+ | @property
36
+ | self._weight_amu : amu weight of unit crystal
37
+ | self.weight_g : g weight of unit crystal
38
+ """
39
+ def __init__(self, comp):
40
+ self.composition = comp
41
+
42
+ @property
43
+ def weight_amu(self):
44
+ result = 0.0
45
+ for atom in self.composition.keys():
46
+ result += self.composition[atom] * amu[atom]
47
+ return result
48
+
49
+ @property
50
+ def weight_g(self):
51
+ return self.weight_amu * amu_g
52
+
53
+ def calc_mass_conversion(elem, mineral):
54
+ """
55
+ | Returns the number of atoms per gram of a particular mineral object
56
+ | Useful for converting mass column to a number density column for an element
57
+ """
58
+ assert type(mineral) == Mineral
59
+ assert type(elem) == str
60
+ return mineral.composition[elem] / mineral.weight_g # g^{-1}
61
+
62
+
63
+ def calc_element_column(NH, fmineral, atom, mineral, d2g=0.009):
64
+ """
65
+ Calculate the column density of an element for a particular NH value,
66
+ assuming a dust-to-gas ratio (d2g) and the fraction of dust in that
67
+ particular mineral species (fmineral)
68
+ """
69
+ dust_mass = NH * mp * d2g * fmineral # g cm^{-2}
70
+ print('Dust mass = %.3e g cm^-2' % (dust_mass))
71
+ return calc_mass_conversion(atom, mineral) * dust_mass # cm^{-2}
72
+
73
+
74
+ def get_ISM_abund(elem, abund_table=wilms):
75
+ """
76
+ Given an abundance table, calculate the number per H atom of a
77
+ given element in any ISM form
78
+ """
79
+ assert type(elem) == str
80
+ assert type(abund_table) == dict
81
+ return np.power(10.0, abund_table[elem] - 12.0) # number per H atom
82
+
83
+ def get_dust_abund(elem, abund_table=wilms, gas_ratio=wilms_1mbeta):
84
+ """
85
+ Given an abundance table (dict) and a table of gas ratios (dict),
86
+ calculate the number per H atom of a given ISM element in *solid* form
87
+ """
88
+ assert type(elem) == str
89
+ assert type(abund_table) == dict
90
+ assert type(gas_ratio) == dict
91
+ return get_ISM_abund(elem, abund_table) * (1.0 - gas_ratio[elem]) # number per H atom