PyNeb is a package for the analysis of emission lines, which evolved from the IRAF package nebular (Shaw and Dufour 1995; Shaw et al 1998). It is a library rather than a code: this means that, to use it, one has to write a python script or enter an interactive python session to call PyNeb classes and functions. In the following we'll provide some examples on how to use the different classes and functions. Please note that the name of the code and the tarball are CapitalCase (PyNeb, PyNeb-[version-number]), whereas the module and directories are all lowercase (pyneb, pynebcore.py, etc).
References: Whenever you use PyNeb for calculations that lead to a published paper, you are kindly asked to cite the code as:
Luridiana, V., Morisset, C., & Shaw, R. A. 2015: PyNeb: a new tool for the analysis of emission lines. I. Code description and validation of results, A&A, 573, 42
The paper is accessible at http://adsabs.harvard.edu/abs/2015A%26A...573A..42L
To run PyNeb, you must have python v. 2.6 or above installed (including python 3.n, which is a different python branch), plus the matplotlib, numpy and scipy libraries. Numpy minimum version is 1.5.1.
In [23]:
%matplotlib inline
%config InlineBackend.figure_format = 'png'
import matplotlib.pyplot as plt
This is the easiest way to install or upgrade PyNeb. Once pip is installed (it comes with Anaconda package for example, see https://pypi.python.org/pypi/pip), enter from the command line:
pip install pyneb
to install PyNeb and:
pip install --upgrade pyneb
for any subsequent upgrade. Uninstalling PyNeb is easy as well:
pip uninstall pyneb
PyNeb's webpage at www.iac.es/proyecto/PyNeb contains a Troubleshooting page to address most frequent installation problems.
In [24]:
import pyneb as pn # We use the pn alias for PyNeb
In the following, we will always assume that the PyNeb package has been imported under the alias “pn”.
In [25]:
print(pn.__version__)
A sketch of the organization of PyNeb can help to understand the role played by the different classes.
The main classes are Atom, RecAtom, EmisGrid, Observations, and Diagnostics. Some classes use other classes; for example, Atom is used in almost all the other classes. A detailed description of each class is given in the following, and the exhaustive list of all the methods of all the classes is available from the reference manual.
Please note: PyNeb uses the Object Oriented (OO) method of programming to define most of its features, but the scripts written as PyNeb wrappers need not be OO; they may follow the more classical functional or structured programming style.
PyNeb distinguishes between atoms emitting collisionally-excited lines (called here "collisional atoms") and atoms emitting recombination lines ("recombination atoms"). Both are represented as n-level systems and share the same basic syntax, but they are encoded in different classes and their internal representation is different in either case, as detailed in the following sections.
The critical features of the physical atom relevant for our scope are encapsulated, for the collisional case, in the Atom data structure. Atom contains the way atomic data are read and managed to compute, for example, line emissivities and to determine diagnostics from line ratios, as well as ionic and total abundances.
Instantiation of the Atom class to create an Atom object is done by specifying an ion:
In [26]:
import pyneb as pn
O3 = pn.Atom('O', 3)
This command tells the code to create an O++ ion model (corresponding to the [O III] spectrum, hence the "3") by reading the [O III] atomic data.
You can create (instantiate) as many atoms as you need, or even create atoms for the same ion using different atomic data. Some basic info on an existing Atom object can be retrieved by the print command:
In [27]:
print(O3)
The two *.dat files mentioned contain the atomic data used to fill in the structure of this particular Atom object. The organisation of these data files will be explained in the section on atomic data.
The Atom object contains methods (functions) to explore it; for example you can display the ion's intrinsic properties:
In [28]:
O3.name
Out[28]:
In [29]:
O3.spec
Out[29]:
In [30]:
O3.gs
Out[30]:
In [31]:
O3.Z
Out[31]:
In [32]:
print('{} eV - {} eV'.format(O3.IP, O3.IP_up))
In [33]:
print('Energy of the 4th level = {:.2f} ev.'.format(O3.getEnergy(4, unit='eV')))
The complete inventory of features and methods of the Atom class can be displayed by entering:
In [34]:
print(dir(O3))
The various methods, which can be either public or private, are described in the PyNeb Reference Manual. Private methods have names starting with underscore “_” and are not supposed to be used by “standard” users.
As always, use the “?” from within an ipython session, or the help method in any python session, or consult the User Reference Manual, to gain access to the different options of the methods:
In [35]:
help(O3.getEnergy)
The printIonic method displays informations on the atom's transitions:
In [36]:
O3.printIonic()
Some arguments can be passed to the method to obtain more information:
In [37]:
O3.printIonic(tem=10000., den=1e3, printA=True, printPop=True, printCrit=True)
Each block describes a transition: the transition probability (in s-1; first row), the wavelength of the corresponding emission line (in Angstrom or microns; second row), the two atomic levels (third row), and the emissivity of the line (fourth row).
You can plot the line emissivities using the following command:
In [38]:
f, ax = plt.subplots(figsize=(8, 6))
O3.plotEmiss(tem_min=1000, tem_max=20000, ionic_abund=1.0, den=1e3, style='-',
legend_loc=4, temLog=False, plot_total=False, plot_only_total=False,
legend=True, total_color='black', total_label='TOTAL', ax=ax)
You can use then take advantage of matplotlib's plotting tools to zoom, crop, or move the figure as you need.
A Grotrian diagram of the ion (i.e., a plot of the energy levels and transition wavelengths) can be obtained using:
In [39]:
f, ax = plt.subplots(figsize=(8, 6))
O3.plotGrotrian(tem=1e4, den=1e2, thresh_int=1e-3, unit = 'eV', ax=ax)
The diagram can be tailored in various ways, zoomed in or saved into a file. Atomic data are accessible using the following commands:
In [40]:
O3.getA()
Out[40]:
In [41]:
O3.getOmegaArray().shape # 5*5 levels, 25 temperatures
Out[41]:
In [42]:
O3.getOmega(tem=1e4)
Out[42]:
In [43]:
help(O3.getOmega)