├── .gitignore ├── .readthedocs.yaml ├── LICENSE.txt ├── README.rst └── pyatomdb ├── COPYING.txt ├── MANIFEST.in ├── README.rst ├── README.txt ├── docs ├── Makefile ├── _static │ └── readme.stuff ├── _templates │ └── layout.html ├── apec.rst ├── atomdb.rst ├── atomic.rst ├── conf.py ├── const.rst ├── contact.rst ├── examples.rst ├── index.rst ├── installation.rst ├── license.rst ├── modules.rst ├── requirements.txt ├── spectrum.rst └── util.rst ├── examples ├── Rsapec_hitomi.svg ├── aciss_meg1_cy22.garf ├── aciss_meg1_cy22.grmf ├── ah100040030_sxs_cl2_HP_small.rmf ├── ah100040030sxs_p0px1010_cl2_HP.pi ├── ah100040030sxs_p0px1010_ptsrc.arf ├── apec_example_1_get_ionbal.py ├── apec_examples_1_1.pdf ├── apec_examples_1_1.svg ├── apec_examples_1_2.pdf ├── apec_examples_1_2.svg ├── atomdb_example_1_get_data.py ├── atomdb_example_2_get_maxwell.py ├── atomdb_examples_2_1.pdf ├── atomdb_examples_2_1.svg ├── atomdb_examples_2_2.pdf ├── atomdb_examples_2_2.svg ├── calc_power.py ├── calc_power_examples_1_1.pdf ├── calc_power_examples_1_1.svg ├── calc_power_nei.py ├── calc_power_nei_examples_1_1.pdf ├── calc_power_nei_examples_1_1.svg ├── first_installation.py ├── make_line_list.py ├── make_spectrum.py ├── new_make_spectrum.py ├── osc_str.py ├── output.txt ├── photoionization_data.py ├── rsapec.py ├── spectrum_NEIsession_examples.py ├── spectrum_NEIsession_linelist_examples.py ├── spectrum_session_examples.py ├── spectrum_session_examples_1.py ├── spectrum_session_examples_1_1.pdf ├── spectrum_session_examples_1_1.svg ├── spectrum_session_examples_1b.py ├── spectrum_session_examples_1b_1.pdf ├── spectrum_session_examples_1b_1.svg ├── spectrum_session_examples_2.py ├── spectrum_session_examples_2_1.pdf ├── spectrum_session_examples_2_1.svg ├── spectrum_session_examples_2b.py ├── spectrum_session_examples_2b_1.pdf ├── spectrum_session_examples_2b_1.svg ├── spectrum_session_examples_3_1.pdf ├── spectrum_session_examples_3_1.svg ├── spectrum_session_examples_3_abund.py ├── spectrum_session_examples_4_1.pdf ├── spectrum_session_examples_4_1.svg ├── spectrum_session_examples_4_abund.py ├── spectrum_session_examples_5_linelist.py ├── spectrum_session_examples_6_1.pdf ├── spectrum_session_examples_6_1.svg ├── spectrum_session_examples_6_line_emissivity.py ├── spectrum_session_examples_7_1.pdf ├── spectrum_session_examples_7_1.svg ├── spectrum_session_examples_7_nei.py ├── spectrum_session_examples_8_nei_linelist.py ├── spectrum_session_linelist_examples.py └── wrapper_xspec_examples.py ├── linear_approx.c ├── make_test_outputs.py ├── pyatomdb ├── __init__.py ├── apec.py ├── atomdb.py ├── atomic.py ├── const.py ├── spectrum.py └── util.py ├── pyproject.toml ├── setup.py ├── tests ├── __init__.py ├── test1.py └── testdata │ ├── aciss_heg1_cy19.garf │ ├── aciss_heg1_cy19.grmf │ ├── test_set_response_spec1.npy │ ├── test_set_response_spec1_309.npy │ └── test_set_response_spec2_309.npz └── wrappers ├── IonE_apec_xspec.py ├── apec_xspec.py ├── bapec_xspec.py └── rsapec_xspec.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | pyatomdb/docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: pyatomdb/docs/conf.py 17 | 18 | 19 | # We recommend specifying your dependencies to enable reproducible builds: 20 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 21 | python: 22 | install: 23 | - requirements: pyatomdb/docs/requirements.txt 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2015-16 Smithsonian Institution. Permission is granted to use, copy, 2 | modify, and distribute this software and its documentation for educational, 3 | research and non-profit purposes, without fee and without a signed 4 | licensing agreement, provided that this notice, including the following 5 | two paragraphs, appear in all copies, modifications and distributions. 6 | For commercial licensing, contact the Office of the Chief Information 7 | Officer, Smithsonian Institution, 380 Herndon Parkway, MRC 1010, Herndon, 8 | VA. 20170, 202-633-5256. 9 | 10 | This software and accompanying documentation is supplied "as is" without 11 | warranty of any kind. The copyright holder and the Smithsonian 12 | Institution: (1) expressly disclaim any warranties, express or implied, 13 | including but not limited to any implied warranties of merchantability, 14 | fitness for a particular purpose, title or non-infringement; (2) do not 15 | assume any legal liability or responsibility for the accuracy, 16 | completeness, or usefulness of the software; (3) do not represent that use 17 | of the software would not infringe privately owned rights; (4) do not 18 | warrant that the software is error-free or will be maintained, supported, 19 | updated or enhanced; (5) will not be liable for any indirect, incidental, 20 | consequential special or punitive damages of any kind or nature, 21 | including but not limited to lost profits or loss of data, on any basis 22 | arising from contract, tort or otherwise, even if any of the parties has 23 | been warned of the possibility of such loss or damage. 24 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | pyatomdb/README.txt -------------------------------------------------------------------------------- /pyatomdb/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright 2015-25 Smithsonian Institution. Permission is granted to use, copy, 2 | modify, and distribute this software and its documentation for educational, 3 | research and non-profit purposes, without fee and without a signed 4 | licensing agreement, provided that this notice, including the following 5 | two paragraphs, appear in all copies, modifications and distributions. 6 | For commercial licensing, contact the Office of the Chief Information 7 | Officer, Smithsonian Institution, 380 Herndon Parkway, MRC 1010, Herndon, 8 | VA. 20170, 202-633-5256. 9 | 10 | This software and accompanying documentation is supplied "as is" without 11 | warranty of any kind. The copyright holder and the Smithsonian 12 | Institution: (1) expressly disclaim any warranties, express or implied, 13 | including but not limited to any implied warranties of merchantability, 14 | fitness for a particular purpose, title or non-infringement; (2) do not 15 | assume any legal liability or responsibility for the accuracy, 16 | completeness, or usefulness of the software; (3) do not represent that use 17 | of the software would not infringe privately owned rights; (4) do not 18 | warrant that the software is error-free or will be maintained, supported, 19 | updated or enhanced; (5) will not be liable for any indirect, incidental, 20 | consequential special or punitive damages of any kind or nature, 21 | including but not limited to lost profits or loss of data, on any basis 22 | arising from contract, tort or otherwise, even if any of the parties has 23 | been warned of the possibility of such loss or damage. 24 | -------------------------------------------------------------------------------- /pyatomdb/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING.txt 2 | include pyproject.toml 3 | recursive-include docs * 4 | recursive-include examples * 5 | recursive-include wrappers * 6 | prune docs/_* 7 | -------------------------------------------------------------------------------- /pyatomdb/README.rst: -------------------------------------------------------------------------------- 1 | README.txt -------------------------------------------------------------------------------- /pyatomdb/README.txt: -------------------------------------------------------------------------------- 1 | ======== 2 | PYATOMDB 3 | ======== 4 | 5 | This code is designed to interact with the AtomDB database. It is in active 6 | development but is now approaching feature complete for creating spectra 7 | and interacting with fitting codes like XSPEC and Sherpa. 8 | 9 | Full documentation can be found at http://atomdb.readthedocs.io 10 | 11 | ============ 12 | Installation 13 | ============ 14 | 15 | Standard python installation. 16 | 17 | #. From `PyPI `_ , using the simple ``pip install pyatomdb`` command. 18 | #. From `GitHub `_ , using the command ``git clone https://github.com/AtomDB/pyatomdb.git`` to get the source, then ``pip install -e python ``. 19 | #. If using ``Conda``: Pyatomdb is not packaged with Conda as it requires compiling of some C code and (as far as I can tell) Conda cannot handle this. I recommend installing the dependencies independently, e.g.: ``conda install requests wget "numpy>=1.9.0" "scipy>=1.9.0" joblib mock astropy pycurl``, then install pip within conda (``conda install pip``), and then ``pip install -e python ``. 20 | #. Using ``setuptools`` (deprecated): python setup.py install 21 | 22 | 23 | 24 | 25 | 26 | =============== 27 | Version History 28 | =============== 29 | 30 | 0.0.0.1 31 | July 17th 2015: initial release 32 | 33 | 0.0.0.2 34 | July 21st 2015: added ``dummyfirst`` keyword to 35 | ``pyatomdb.spectrum.make_spectrum`` 36 | 37 | 0.0.0.3 38 | August 12th 2015: fixed some errors in spectrum.py. Updated readme. 39 | 40 | 0.0.0.4 41 | August 12th 2015: fixed example script in manual. 42 | 43 | 0.0.0.5 44 | August 17th 2015: added PI cross section graphing data. 45 | Updated get_data to fetch files from remote server 46 | 47 | 0.0.0.6 48 | August 18th 2015: Fixed bug with documentation 49 | 50 | 0.0.1.0 51 | September 23rd 2015: Added significant documentation. Converted all 'z0' to 'Z' and 'rmJ' to 'z1' throught the code for consistency. 52 | 53 | 0.0.1.1 54 | September 25th 2015: Major documentation revamp. 55 | Separated datacache from settings keyword 56 | Introduced automatic install and update into util package. 57 | 58 | 0.0.1.2 59 | October 13th 2015: More documentation improvements 60 | Removed use of "curl" library, as apparently is non-standard. Replaced with 61 | wget, ftplib and requests. 62 | 63 | 0.0.1.3 64 | November 5th 2015: Many minor bugfixes. Added "switch_version" to util package 65 | to allow looking at older AtomDB version data. Added use option to get total RRC 66 | emission using integral to infinity. 67 | 68 | 0.0.1.5 69 | February 12th 2016: As ever, bugfixes. Also added ability to calculate 70 | ionization balance to apec module. 71 | 72 | 0.0.1.6 73 | April 22nd 2016: Bugfixes! Also: 74 | Major change to get_maxwell_rate interface 75 | Added ability to apply RMF and ARF to spectra in spectrum module 76 | Fixed hydrogenic RRC calculation 77 | 78 | 0.0.1.7 79 | May 23rd 2016: Bugfix:update switch_version to get NEI files too. 80 | 81 | 0.0.1.8 82 | October 07th 2016: Bugfixes! Also: 83 | APEC now included in apec.py. Can create a full apec run from a par file. 84 | 85 | 0.0.1.9 86 | October 13th 2016: Bugfixes! wget was causing problems during file download due to bugs, Now fixed 87 | 88 | 0.0.2.0 89 | November 01st 2016: Removed use of sparse algebra. Wasn't accurate enough, causing issues with suprious lines in low ionization states. 90 | 91 | Implemented faster ionization balance calculations in "apec.solve_ionbal_eigen" 92 | 93 | 94 | 0.0.2.1 95 | November 16th 2016: Bugfix to the level population calculation for recombination. For ions with level resolved rates and PI cross sections, we were double counting. Fixed now. 96 | 97 | 0.0.2.2 98 | November 30th 2016: Bugfix to download of new files: urllib.urlcleanup now called more often. 99 | 100 | 0.0.2.3 101 | December 8th 2016: Updated to handle 3.0.7. 102 | 103 | 0.0.2.4 104 | January 16th 2017: Bugfix for installation, include joblib as a requirement 105 | 106 | 0.0.2.5 107 | January 17th 2017: Bugfix for installation, include mock as a requirement 108 | 109 | 0.0.3.0 110 | February 21st 2017: Introduced new way to calculated spectra, using the Session 111 | and Spec objects in spectrum.py. It is intended to make this the main way to 112 | calculate spectra, as it should lead to significant speed enhancements by 113 | avoiding lots of unnecessary recalculation of the same numbers. 114 | 115 | 0.0.3.1 116 | February 21st 2017: A series of bug fixes to installation and spectral calculation routines. Closes bugs #1, 2, 5 from github 117 | 118 | 0.0.3.2 119 | March 21st 2017: Several bug fixes and enhancements to the spectrum module. Updated setup.py to handle import of mock more gracefully 120 | 121 | 0.0.3.3 122 | May 5th 2017: Several bug fixes and initial inclusion of charge exchange model 123 | 124 | 0.0.3.4 125 | May 23rd 2017: Bug fix to spectrum.apply_response, now handles response files 126 | indexed from zero (thank you Lia Corrales for finding this issue) 127 | 128 | 0.5.0 129 | January 9th 2018: Major updates to include CX models. Increased version number to something relevant to 3 decimal style. 130 | 131 | 0.5.1 132 | February 14th 2018: Bugfix to use 64bit floats for ionization fraction calculation, which was occasionally causing issues. 133 | 134 | 0.5.2 135 | May 10th 2018: Bugfixes, including one where angstrom spectra where generated backwards. 136 | 137 | 0.5.3 138 | June 14th 2018: Bugfixes: NEI spectrum session fixed to assign bin units correctly when using a response file 139 | 140 | 0.5.4 141 | September 03rd 2018: Bugfix: NEI spectrum.Session.set_specbins now correctly resets the spectra when changed. Thanks to Shinya Nakashima for discovering this bug. 142 | 143 | 144 | 0.6.0 145 | November 20th 2018: Switch to python 3 support only. Python 2.7 support available for now through Github 146 | 147 | 0.7.0 148 | Bug fixes aplenty, mostly due to python 3 conversion. 149 | 150 | 0.7.1 151 | April 22nd 2019: Fixed bug occuring with spectrum continuum broadening. 152 | 153 | 0.7.2 154 | May 6th 2019: Add option 'ALL' to get_data to download all the data files for 155 | an ion at once 156 | 157 | 0.8.0 158 | January 27th 2020: Major overhaul of Spectrum module. 159 | Updated paths for the FTP server due to file move. 160 | 161 | 0.8.1 162 | February 5th 2020: Corrections to NEISpectrum. Spectrum summation much faster and 163 | bugs in logic fixed. 164 | 165 | 0.9.0 166 | March 20th 2020: Added PShockSession class to specturm module, mimicking XSPEC pshock (parallel shock) model. Other minor bugfixes. 167 | 168 | 0.10.0 169 | May 12th 2020: Major update to documentation, spectrum and atomdb modules. Significant rationalization of routines, making many non-public in the documentation. This should help new users understand what is going on. I apologise if it breaks whatever you were doing, please get in touch if the fix is not obvious. 170 | 171 | 0.10.1 172 | May 12th 2020: Minor packaging fixes 173 | 174 | 0.10.2 175 | May 27th 2020: Bugfix to read_data 176 | 177 | 0.10.3 178 | July 14th 2020: Added force keyword to switch_version. Amended make_linelist to handle non-51 temperature files 179 | 180 | 0.10.4 181 | July 20th 2020: Fixed PShockSession initialization error. Added automatic removal of old pickle files generated from fits files when detected. 182 | 183 | 0.10.5 184 | September 4th 2020: Fixed issue when handling temperatures above or below the maximum and minimum values in the APEC emissivity files. Added Electron-electron bremsstrahlung emission into APEC model. 185 | 186 | 0.10.6 187 | September 9th 2020: Fixed missing filename in build - README.txt had been renamed README.rst. Also included pycurl in requirements list 188 | 189 | 0.10.7 190 | October 12th 2020: Fixed a series of bugs - 28 and 29 on Github, and merged in ionization balance storage information pull request from Jim Slavin. 191 | 192 | 0.10.8 193 | November 9th 2020: Minor changes for compatibility with changes to kappa module. 194 | 195 | 0.10.9 196 | June 16th 2022: Several quality of life issues overdue for inclusion 197 | 198 | - Spectrum session now has a verbosity switch 199 | - Added more to the wrappers folder 200 | - Added the ability to update wavelengths on the fly in spectrum objects 201 | - Fixed errors when forcing use of older Mazzotta data for ionization 202 | 203 | 0.10.10 204 | July 22nd 2022: Updated spectrum.py set_response to handle 0keV minimum energy responses 205 | 206 | 0.10.11 207 | August 2nd 2022: Added "sparse" option to set_response, which uses sparse matrices in the RMF, allowing for large responses (e.g. XRISM) to be handled with limited memory usage. 208 | 209 | 0.10.12 210 | December 13th 2022 211 | Fixed(?) issues with curl library 212 | Corrected bug with return_spectrum leading to overestimate in E-E brems of ~20% 213 | 214 | 0.10.13 215 | February 6th 2023 216 | Another attempt to fix issues with curl library 217 | 218 | 0.11.0 219 | October 5th 2023 220 | Added rsapec model 221 | 222 | 0.11.1 223 | November 13th 2023 224 | Bugfix to atomic.elsymb_to_Z. Thank you to Guan-Fu Liu for spotting this. 225 | 226 | 0.11.2 227 | November 22nd 2023 228 | Added formatting to level list print outs, in spectrum.CIESession.format_linelist 229 | 230 | 0.11.3 231 | December 5th 2023 232 | Bugfix to spectrum.py, resolving issue 47 233 | 234 | 0.11.4 235 | January 17th 2024 236 | Updated atomic.py to hold uniform L shell labels up to L=27 237 | 238 | 0.11.5 239 | May 15th 2024 240 | Updated rmf handling routines in spectrum.py to handle RMF with inconsistent F_CHAN and EBOUNDS indexing. 241 | 242 | 0.11.6-7 243 | July 3rd 2024 244 | Documentation issues with Mock and ReadTheDocs being addressed. 245 | 246 | 0.11.8 247 | August 8th 2024 248 | Updates to replace deprecated keywords/functions in numpy, astropy and scipy. 249 | Should now work with scipy v1.14 and greater. 250 | 251 | 0.12.0 252 | October 1st 2024 253 | Updated to allow access to AtomDB v3.1.0 files. These differ due to variable length continuum arrays, and required a re-write to the spectrum module and apec modules for reading/writing the files. 254 | 255 | 1.0.0 256 | January 3rd 2025 257 | Updated to allow access to all AtomDB v3.1.0 files (couldn't do equilibrium previously). This version was used to compile AtomDB v3.1.0. 258 | 259 | 1.0.1 260 | January 31st 2025 261 | Updated to allow access to all AtomDB v3.1.x eigenvector files (path was hardcoded so v3.1.1 couldn't read them). 262 | 263 | 1.0.2 264 | January 31st 2025 265 | Removed debug output erroneously added to spectrum.py calls. 266 | 267 | 1.0.3 268 | March 7th 2025 269 | Repaired util.py check_version command, along with other bug fixes. 270 | 271 | 1.0.4 272 | March 13th 2025 273 | Improved check_version to print currently used database version. 274 | Added clean_pickle_cache routine to clean out cache of pickle files 275 | Changed spectrum Session objects to handle .dopseudo, .docont and .dopickle 276 | attributes correctly and consistently. 277 | 278 | 1.0.5 279 | April 8th 2025 280 | Remade and updated examples to work with AtomDB 3.1.X 281 | Fixed bug with return_spectrum when initial population was specified in K. 282 | Finally purged all use of pycurl 283 | -------------------------------------------------------------------------------- /pyatomdb/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyAtomDB.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyAtomDB.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/PyAtomDB" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyAtomDB" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /pyatomdb/docs/_static/readme.stuff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/docs/_static/readme.stuff -------------------------------------------------------------------------------- /pyatomdb/docs/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {% block menu %} 4 | {{ super() }} 5 | Index 6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /pyatomdb/docs/apec.rst: -------------------------------------------------------------------------------- 1 | apec module 2 | =========== 3 | 4 | This modules contains the APEC code. It calls many different subroutines from throughout the PyAtomDB module. 5 | 6 | It is expected (as of May 2020) that this code will go through a major rewrite to make it more pythonic and to make 7 | many helper routines private to declutter the module. Be wary of embedding too 8 | many links to this module in your code. 9 | 10 | .. automodule:: pyatomdb.apec 11 | :members: 12 | :undoc-members: 13 | :inherited-members: 14 | :show-inheritance: 15 | -------------------------------------------------------------------------------- /pyatomdb/docs/atomdb.rst: -------------------------------------------------------------------------------- 1 | atomdb module 2 | ============= 3 | 4 | This modules is designed to interact with the main atomic database, extracting real values of coefficients and so on. 5 | 6 | .. automodule:: pyatomdb.atomdb 7 | :members: 8 | :undoc-members: 9 | :inherited-members: 10 | :show-inheritance: 11 | -------------------------------------------------------------------------------- /pyatomdb/docs/atomic.rst: -------------------------------------------------------------------------------- 1 | atomic module 2 | ============= 3 | 4 | This module contains basic atomic parameters (i.e. atomic numbers, element symbols) 5 | 6 | .. automodule:: pyatomdb.atomic 7 | :members: 8 | :undoc-members: 9 | :inherited-members: 10 | :show-inheritance: 11 | -------------------------------------------------------------------------------- /pyatomdb/docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # PyAtomDB documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Sep 18 17:07:36 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys 16 | import os 17 | import shlex 18 | #import numpydoc 19 | 20 | try: 21 | from unittest.mock import MagicMock 22 | except ImportError: 23 | from mock import Mock as MagicMock 24 | 25 | class Mock(MagicMock): 26 | @classmethod 27 | def __getattr__(cls, name): 28 | return Mock() 29 | 30 | MOCK_MODULES=['liblinapprox'] 31 | 32 | 33 | def get_version(relpath): 34 | """read version info from file without importing it""" 35 | from os.path import dirname, join 36 | for line in open(join(dirname(__file__), relpath)): 37 | if '__version__' in line: 38 | if '"' in line: 39 | # __version__ = "0.9" 40 | return line.split('"')[1] 41 | elif "'" in line: 42 | return line.split("'")[1] 43 | 44 | # If extensions (or modules to document with autodoc) are in another directory, 45 | # add these directories to sys.path here. If the directory is relative to the 46 | # documentation root, use os.path.abspath to make it absolute, like shown here. 47 | #sys.path.insert(0, os.path.abspath('.')) 48 | sys.path.insert(0,os.path.abspath('.')) 49 | sys.path.insert(0,os.path.abspath('..')) 50 | #for i in sys.path: 51 | # print i 52 | # -- General configuration ------------------------------------------------ 53 | 54 | # If your documentation needs a minimal Sphinx version, state it here. 55 | #needs_sphinx = '1.0' 56 | 57 | # Add any Sphinx extension module names here, as strings. They can be 58 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 59 | # ones. 60 | extensions = [ 61 | 'sphinx.ext.autodoc', 62 | 'sphinx.ext.coverage', 63 | 'sphinx.ext.autosummary', 64 | 'numpydoc', 65 | 'sphinx.ext.todo', 66 | 'sphinx.ext.mathjax', 67 | 'sphinx.ext.viewcode', 68 | 'sphinx_rtd_theme', 69 | ] 70 | 71 | # Add any paths that contain templates here, relative to this directory. 72 | templates_path = ['_templates'] 73 | 74 | # The suffix(es) of source filenames. 75 | # You can specify multiple suffix as a list of string: 76 | # source_suffix = ['.rst', '.md'] 77 | source_suffix = '.rst' 78 | 79 | # The encoding of source files. 80 | #source_encoding = 'utf-8-sig' 81 | 82 | # The master toctree document. 83 | master_doc = 'index' 84 | 85 | # General information about the project. 86 | project = u'PyAtomDB' 87 | copyright = u'2015-2023, Adam Foster' 88 | author = u'Adam Foster' 89 | 90 | # The version info for the project you're documenting, acts as replacement for 91 | # |version| and |release|, also used in various other places throughout the 92 | # built documents. 93 | # 94 | # The short X.Y version. 95 | version = get_version('../pyatomdb/__init__.py') 96 | # The full version, including alpha/beta/rc tags. 97 | release = get_version('../pyatomdb/__init__.py') 98 | 99 | # The language for content autogenerated by Sphinx. Refer to documentation 100 | # for a list of supported languages. 101 | # 102 | # This is also used if you do content translation via gettext catalogs. 103 | # Usually you set "language" from the command line for these cases. 104 | language = 'en' 105 | 106 | # There are two options for replacing |today|: either, you set today to some 107 | # non-false value, then it is used: 108 | #today = '' 109 | # Else, today_fmt is used as the format for a strftime call. 110 | #today_fmt = '%B %d, %Y' 111 | 112 | # List of patterns, relative to source directory, that match files and 113 | # directories to ignore when looking for source files. 114 | exclude_patterns = ['_build'] 115 | 116 | # The reST default role (used for this markup: `text`) to use for all 117 | # documents. 118 | #default_role = None 119 | 120 | # If true, '()' will be appended to :func: etc. cross-reference text. 121 | #add_function_parentheses = True 122 | 123 | # If true, the current module name will be prepended to all description 124 | # unit titles (such as .. function::). 125 | #add_module_names = True 126 | 127 | # If true, sectionauthor and moduleauthor directives will be shown in the 128 | # output. They are ignored by default. 129 | #show_authors = False 130 | 131 | # The name of the Pygments (syntax highlighting) style to use. 132 | pygments_style = 'sphinx' 133 | 134 | # A list of ignored prefixes for module index sorting. 135 | #modindex_common_prefix = [] 136 | 137 | # If true, keep warnings as "system message" paragraphs in the built documents. 138 | #keep_warnings = False 139 | 140 | # If true, `todo` and `todoList` produce output, else they produce nothing. 141 | todo_include_todos = True 142 | 143 | 144 | # -- Options for HTML output ---------------------------------------------- 145 | 146 | # The theme to use for HTML and HTML Help pages. See the documentation for 147 | # a list of builtin themes. 148 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 149 | html_theme = 'sphinx_rtd_theme' 150 | 151 | if not on_rtd: # only import and set the theme if we're building docs locally 152 | import sphinx_rtd_theme 153 | html_theme = 'sphinx_rtd_theme' 154 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 155 | 156 | # Theme options are theme-specific and customize the look and feel of a theme 157 | # further. For a list of options available for each theme, see the 158 | # documentation. 159 | html_theme_options = { 160 | 'navigation_depth': 4, 161 | 'collapse_navigation': False, 162 | } 163 | 164 | # Add any paths that contain custom themes here, relative to this directory. 165 | #html_theme_path = [] 166 | 167 | # The name for this set of Sphinx documents. If None, it defaults to 168 | # " v documentation". 169 | #html_title = None 170 | 171 | # A shorter title for the navigation bar. Default is the same as html_title. 172 | #html_short_title = None 173 | 174 | # The name of an image file (relative to this directory) to place at the top 175 | # of the sidebar. 176 | #html_logo = None 177 | 178 | # The name of an image file (within the static path) to use as favicon of the 179 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 180 | # pixels large. 181 | #html_favicon = None 182 | 183 | # Add any paths that contain custom static files (such as style sheets) here, 184 | # relative to this directory. They are copied after the builtin static files, 185 | # so a file named "default.css" will overwrite the builtin "default.css". 186 | html_static_path = ['_static'] 187 | 188 | # Add any extra paths that contain custom files (such as robots.txt or 189 | # .htaccess) here, relative to this directory. These files are copied 190 | # directly to the root of the documentation. 191 | #html_extra_path = [] 192 | 193 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 194 | # using the given strftime format. 195 | #html_last_updated_fmt = '%b %d, %Y' 196 | 197 | # If true, SmartyPants will be used to convert quotes and dashes to 198 | # typographically correct entities. 199 | #html_use_smartypants = True 200 | 201 | # Custom sidebar templates, maps document names to template names. 202 | #html_sidebars = {} 203 | 204 | # Additional templates that should be rendered to pages, maps page names to 205 | # template names. 206 | #html_additional_pages = {} 207 | 208 | # If false, no module index is generated. 209 | #html_domain_indices = True 210 | 211 | # If false, no index is generated. 212 | #html_use_index = True 213 | 214 | # If true, the index is split into individual pages for each letter. 215 | #html_split_index = False 216 | 217 | # If true, links to the reST sources are added to the pages. 218 | #html_show_sourcelink = True 219 | 220 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 221 | #html_show_sphinx = True 222 | 223 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 224 | #html_show_copyright = True 225 | 226 | # If true, an OpenSearch description file will be output, and all pages will 227 | # contain a tag referring to it. The value of this option must be the 228 | # base URL from which the finished HTML is served. 229 | #html_use_opensearch = '' 230 | 231 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 232 | #html_file_suffix = None 233 | 234 | # Language to be used for generating the HTML full-text search index. 235 | # Sphinx supports the following languages: 236 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 237 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' 238 | #html_search_language = 'en' 239 | 240 | # A dictionary with options for the search language support, empty by default. 241 | # Now only 'ja' uses this config value 242 | #html_search_options = {'type': 'default'} 243 | 244 | # The name of a javascript file (relative to the configuration directory) that 245 | # implements a search results scorer. If empty, the default will be used. 246 | #html_search_scorer = 'scorer.js' 247 | 248 | # Output file base name for HTML help builder. 249 | htmlhelp_basename = 'PyAtomDBdoc' 250 | 251 | # -- Options for LaTeX output --------------------------------------------- 252 | 253 | latex_elements = { 254 | # The paper size ('letterpaper' or 'a4paper'). 255 | #'papersize': 'letterpaper', 256 | 257 | # The font size ('10pt', '11pt' or '12pt'). 258 | #'pointsize': '10pt', 259 | 260 | # Additional stuff for the LaTeX preamble. 261 | #'preamble': '', 262 | 263 | # Latex figure (float) alignment 264 | #'figure_align': 'htbp', 265 | } 266 | 267 | # Grouping the document tree into LaTeX files. List of tuples 268 | # (source start file, target name, title, 269 | # author, documentclass [howto, manual, or own class]). 270 | latex_documents = [ 271 | (master_doc, 'PyAtomDB.tex', u'PyAtomDB Documentation', 272 | u'Adam Foster', 'manual'), 273 | ] 274 | 275 | # The name of an image file (relative to this directory) to place at the top of 276 | # the title page. 277 | #latex_logo = None 278 | 279 | # For "manual" documents, if this is true, then toplevel headings are parts, 280 | # not chapters. 281 | #latex_use_parts = False 282 | 283 | # If true, show page references after internal links. 284 | #latex_show_pagerefs = False 285 | 286 | # If true, show URL addresses after external links. 287 | #latex_show_urls = False 288 | 289 | # Documents to append as an appendix to all manuals. 290 | #latex_appendices = [] 291 | 292 | # If false, no module index is generated. 293 | #latex_domain_indices = True 294 | 295 | 296 | # -- Options for manual page output --------------------------------------- 297 | 298 | # One entry per manual page. List of tuples 299 | # (source start file, name, description, authors, manual section). 300 | man_pages = [ 301 | (master_doc, 'pyatomdb', u'PyAtomDB Documentation', 302 | [author], 1) 303 | ] 304 | 305 | # If true, show URL addresses after external links. 306 | #man_show_urls = False 307 | 308 | 309 | # -- Options for Texinfo output ------------------------------------------- 310 | 311 | # Grouping the document tree into Texinfo files. List of tuples 312 | # (source start file, target name, title, author, 313 | # dir menu entry, description, category) 314 | texinfo_documents = [ 315 | (master_doc, 'PyAtomDB', u'PyAtomDB Documentation', 316 | author, 'PyAtomDB', 'Python interface to AtomDB.', 317 | 'Miscellaneous'), 318 | ] 319 | 320 | # Documents to append as an appendix to all manuals. 321 | #texinfo_appendices = [] 322 | 323 | # If false, no module index is generated. 324 | #texinfo_domain_indices = True 325 | 326 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 327 | #texinfo_show_urls = 'footnote' 328 | 329 | # If true, do not generate a @detailmenu in the "Top" node's menu. 330 | #texinfo_no_detailmenu = False 331 | 332 | 333 | numpydoc_show_class_members = False 334 | -------------------------------------------------------------------------------- /pyatomdb/docs/const.rst: -------------------------------------------------------------------------------- 1 | const module 2 | ============ 3 | 4 | A series of physical constants and constants relevant to running the APEC code. 5 | 6 | .. automodule:: pyatomdb.const 7 | :members: 8 | :undoc-members: 9 | :inherited-members: 10 | :show-inheritance: 11 | -------------------------------------------------------------------------------- /pyatomdb/docs/contact.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Contact 3 | ======= 4 | 5 | This module is still in very active development. If you have feature requests, bug 6 | reports or any other questions, please contact us through the project's 7 | `GitHub `_ page. 8 | -------------------------------------------------------------------------------- /pyatomdb/docs/examples.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | PyAtomDB Example Scripts 3 | ======================== 4 | 5 | 6 | 7 | ---------------- 8 | Module Structure 9 | ---------------- 10 | 11 | These are examples of using the PyAtomDB module in your projects. They can all be found in the examples subdirectory of your PyAtomDB installation. 12 | 13 | The examples here are separated by the module in which they are implemented. Generally speaking, the roles of these modules can be split into the following areas: 14 | 15 | spectrum 16 | Obtaining emissivities from the AtomDB emissivity files (e.g. the ``apec`` model). This module is used to create spectra as required. 17 | 18 | apec 19 | Related to the APEC code - creating the AtomDB emissivity files from the underlying atomic database 20 | 21 | atomdb 22 | Accessing the atomic database - returning rates and coefficients, fetching files 23 | 24 | atomic 25 | Basic atomic functions - getting atomic masses, converting to element symbols etc. 26 | 27 | util 28 | File utilities (not generally interesting to end users) 29 | 30 | const 31 | List of physical constants and code-related constants used throughout PyAtomDB (again, not generally interesting to end users) 32 | 33 | 34 | 35 | 36 | ------- 37 | Spectra 38 | ------- 39 | The spectrum.py module contains routines for taking the spectrum generated from the 40 | apec model and extracting line emissivities or continuum emission, applying responses, 41 | changing abundances, etc. In these examples, we will use the 42 | `Chandra ACIS-S MEG +1 `_ 43 | order grating responses as examples where one is required, but you can use any. 44 | 45 | Similarly, we use ``pylab`` for plotting. You can of course use whatever system you 46 | like for plotting, this is just what we did. It is included in matplotlib and 47 | therefore hopefully present on most systems. 48 | 49 | ++++++++++++++++ 50 | CIESession Class 51 | ++++++++++++++++ 52 | 53 | The heart of the spectral analysis is the spectrum.py class. This reads in the results of an apec run (by default, $ATOMDB/apec_line.fits and $ATOMDB/apec_coco.fits) and allows the user to obtain spectra at a range of temperatures accounting for instrument responses, thermal and velocity broadening, abundance changes and other issues. 54 | 55 | ~~~~~~~~~~~~~~~~~ 56 | Making a Spectrum 57 | ~~~~~~~~~~~~~~~~~ 58 | 59 | .. literalinclude:: ../examples/spectrum_session_examples_1.py 60 | 61 | .. figure:: ../examples/spectrum_session_examples_1_1.svg 62 | :align: center 63 | :alt: Spectrum Example 1 64 | :figclass: align-center 65 | 66 | A kT=0.4keV simple spectrum created with and without an instrument response 67 | 68 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | Handling Large Response Matrices 70 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 71 | 72 | Some missions, for example XRISM, have a large number of bins in their response files (XRISM has 50,000). Creating a 50,000x50,000 response matrix would require of order 16GB of memory, most of which would be zeros. Setting ``sparse=True`` when setting the response will use `sparse matrices `_ to save memory. The code below shows how to do this and also how to compare any innacuracies caused (testing so far has shown nothing larger than numerical rounding errors, 1 part in 10 :sup:`15`) 73 | 74 | .. literalinclude:: ../examples/spectrum_session_examples_1b.py 75 | 76 | .. figure:: ../examples/spectrum_session_examples_1b_1.svg 77 | :align: center 78 | :alt: Spectrum Example 1(b) - sparse matrices for large responses 79 | :figclass: align-center 80 | 81 | A kT=0.4keV simple spectrum created with regular and sparse instrument responses. The same code can be used to compare the accuracy of the two methods for different response matrices, but will require large amounts of memory if using large responses. 82 | 83 | ~~~~~~~~~~~~~~~ 84 | Line Broadening 85 | ~~~~~~~~~~~~~~~ 86 | 87 | By default, line broadening is off. The command ``session.set_broadening`` allows you to turn on thermal broadening and, if desired, add additional turbulent velocity broadening too. 88 | 89 | .. literalinclude:: ../examples/spectrum_session_examples_2.py 90 | 91 | .. figure:: ../examples/spectrum_session_examples_2_1.svg 92 | :align: center 93 | :alt: Spectrum Example 2 94 | :figclass: align-center 95 | 96 | A kT=3.0keV spectrum unbroadened, thermally broadened and then additionally velocity broadend. 97 | 98 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 99 | Line Broadening of Weak Lines 100 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 | 102 | When line broadening is enabled, it by default only broadens lines with an emissivity :math:`>10^{-18}` :math:`ph ~ cm^3 s^{-1}`. This can sometimes lead to "spikes" in the spectrum. This can be changed by adjusting the ``broaden_limit`` parameter when calling ``session.set_broadening``, as shown below. 103 | 104 | .. literalinclude:: ../examples/spectrum_session_examples_2b.py 105 | 106 | .. figure:: ../examples/spectrum_session_examples_2b_1.svg 107 | :align: center 108 | :alt: Spectrum Example 2b 109 | :figclass: align-center 110 | 111 | A kT=10.0keV spectrum unbroadened, thermally and velocity broadend, and then with the limit lowered so weak features are also broadened. 112 | 113 | ~~~~~~~~~~~~~~~~~~~ 114 | Changing Abundances 115 | ~~~~~~~~~~~~~~~~~~~ 116 | 117 | There are several ways to change the abundances. By default, all are set to 1.0 times the solar value of `Anders and Grevesse `_. 118 | The ``session.set_abund`` command implements this. 119 | 120 | .. literalinclude:: ../examples/spectrum_session_examples_3_abund.py 121 | 122 | .. figure:: ../examples/spectrum_session_examples_3_1.svg 123 | :align: center 124 | :alt: Spectrum Example 3 125 | :figclass: align-center 126 | 127 | A kT=1.0keV spectrum with assorted different abundances applied. 128 | 129 | 130 | You can also change the entire abundance set in use using ``session.set_abundset``. 131 | 132 | .. literalinclude:: ../examples/spectrum_session_examples_4_abund.py 133 | 134 | .. figure:: ../examples/spectrum_session_examples_4_1.svg 135 | :align: center 136 | :alt: Spectrum Example 4 137 | :figclass: align-center 138 | 139 | A kT=1.0keV spectrum with assorted different abundance sets applied. 140 | 141 | ~~~~~~~~~~~~~~~~ 142 | Return line list 143 | ~~~~~~~~~~~~~~~~ 144 | 145 | To obtain a list of lines and their emissivities in a spectral range, use ``session.return_linelist``. This 146 | returns the data as a numpy array of the lines in the region, applying all current abundance information 147 | to the linelist. It also interpolates in temperature between the two nearest points. Note 148 | that since AtomDB cuts off lines with emissivities below :math:`10^{-20}` :math:`ph ~ cm^3 s^{-1}`, lines 149 | will diappear below this emissivity. Lines beyond the last temperature point at which they are tabulated will 150 | not be included in the returned linelist. 151 | 152 | .. literalinclude:: ../examples/spectrum_session_examples_5_linelist.py 153 | 154 | ~~~~~~~~~~~~~~~~~~~~~~ 155 | Return line emissivity 156 | ~~~~~~~~~~~~~~~~~~~~~~ 157 | 158 | To calculate the emissvitiy of a specific line, you can use ``session.return_line_emissivity`` along 159 | with the ion, element, upper and lower levels of the transition. You can supply a single or a range 160 | of temperatures, and a dictionary will be returned containing much of the information along with 161 | emissivity (epsilon) you requested. 162 | 163 | .. literalinclude:: ../examples/spectrum_session_examples_6_line_emissivity.py 164 | 165 | .. figure:: ../examples/spectrum_session_examples_6_1.svg 166 | :align: center 167 | :alt: Spectrum Example 6 168 | :figclass: align-center 169 | 170 | Emissivity of the resonance line of O VII. 171 | 172 | ++++++++++++++++ 173 | NEISession Class 174 | ++++++++++++++++ 175 | 176 | Derived from the CIESession class, this handles non-equilibrium spectra. As such, all of the calls to it are 177 | exactly the same. Adding response, setting abundances obtaining spectra, etc all work the same way. 178 | Therefore I will only outline what is different. 179 | 180 | The main difference is that a non equilibrium plasma requires 2 more pieces of information to define it. The 181 | current electron temperature is as with the CIE case. The other two are: 182 | 183 | tau 184 | The ionization timescale (:math:`n_e t`) in |cm-3s| since the plasma left its previous 185 | equilibrium 186 | init_pop 187 | The initial population the plasma was in at tau=0. 188 | 189 | Tau is a single number in all cases. init_pop can be be defined in a range of ways: 190 | 191 | float 192 | If it is a single number, this is assumed to be an electron temperature. The ionization fraction will 193 | be calculated at this :math:`T_e`. 194 | 195 | dict 196 | If a dictionary is provided, it should be an explicit ionization fraction for each element. 197 | So dict[6]= [0.0, 0.1, 0.2, 0.3, 0.3, 0.1, 0.0] would be the ionization fraction for carbon, 198 | dict[8]= [0.0, 0.0, 0.1, 0.1, 0.1, 0.15,0.3,0.2,0.05] would be for oxygen etc. 199 | 200 | 'ionizing' 201 | If the string ionizing is provided, set all elements to be entirely neutral. This is the default. 202 | 203 | 'recombining' 204 | If the string recombining is provided, set all elements to be fully ionized. 205 | 206 | ~~~~~~~~~~~~~~~~~ 207 | Making a Spectrum 208 | ~~~~~~~~~~~~~~~~~ 209 | 210 | As an example, this will plot a simple recombining spectrum within initial temperature of 1.0keV. 211 | 212 | .. literalinclude:: ../examples/spectrum_session_examples_7_nei.py 213 | 214 | .. figure:: ../examples/spectrum_session_examples_7_1.svg 215 | :align: center 216 | :alt: Spectrum Example 7 217 | :figclass: align-center 218 | 219 | Recombining spectrum specified by an initial temperature 220 | 221 | ~~~~~~~~~~~~~~~~~ 222 | Making a Linelist 223 | ~~~~~~~~~~~~~~~~~ 224 | 225 | This is again exactly the same as the CIESession case, except with extra parameters ``tau`` and ``init_pop``. 226 | The only additional option is the ability to separate the linelist by driving ion. This is the ion which gives 227 | rise to the emission. For example, if the emission is largely from ionization into an excited state and then 228 | subsequent cascade, then that part of the emissivity has a different driving ion than that driven by 229 | excitation of the ion's ground state. 230 | 231 | Separating out these features can be turned on and off using the ``by_ion_drv`` keyword, 232 | 233 | .. literalinclude:: ../examples/spectrum_session_examples_8_nei_linelist.py 234 | 235 | 236 | ------------------- 237 | Getting Atomic Data 238 | ------------------- 239 | The ``atomdb`` module is designed to read data from the database and either 240 | return raw opened files (e.g. all the energy levels of an ion) or 241 | individual useful data (e.g. a rate coefficient). 242 | 243 | AtomDB stores data sorted by ion in a series of files in the ``$ATOMDB/APED``. There are several files for 244 | each ion, covering different data types: 245 | 246 | * 'IR' - ionization and recombination 247 | * 'LV' - energy levels 248 | * 'LA' - radiative transition data (lambda and A-values) 249 | * 'EC' - electron collision data 250 | * 'PC' - proton collision data 251 | * 'DR' - dielectronic recombination satellite line data 252 | * 'PI' - XSTAR photoionization data 253 | * 'AI' - autoionization data 254 | * 'ALL' - reads all of the above. Does not return anything. Used for bulk downloading. 255 | 256 | Or, for non-ion-specific data (abundances and bremstrahlung coeffts): 257 | 258 | * 'ABUND' - abundance tables 259 | * 'HBREMS' - Hummer bremstrahlung coefficients 260 | * 'RBREMS' - relativistic bremstrahlung coefficitients 261 | * 'IONBAL' - ionization balance tables 262 | * 'EIGEN' - eigenvalue files (for non-equilibrium ionization) 263 | 264 | The raw atomic data files can be downloaded using ``atomdb.get_data``. 265 | 266 | .. note:: Datacache 267 | 268 | Often, when using AtomDB data you will want to use the same file over and over again. However, 269 | the whole database is too large to be loaded into memory as a matter of course. To get around this, 270 | the ``datacache`` keyword is used in several routines. This is a dictionary which is populated 271 | with any data files that you have to open. The atomdb function which ultimately opens the raw 272 | data files, ``get_data``, will always check for an already existing data file here before 273 | going to the disk to open the file anew. If there is no data there, then the file is opened 274 | and its data is stored in the datacache so that next time the routine is called it will 275 | already be there. 276 | 277 | If you need to save memory, you can empty the cache by declaring the datacache as a 278 | new dictionary, i.e. ``datacache={}``. 279 | 280 | 281 | 282 | .. literalinclude:: ../examples/atomdb_example_1_get_data.py 283 | 284 | +++++++++++++++++++++++++ 285 | Getting Rate Coefficients 286 | +++++++++++++++++++++++++ 287 | 288 | Ionization, recombination, and excitation rate coefficients can all be 289 | obtained using ``get_maxwell_rate``. 290 | 291 | .. literalinclude:: ../examples/atomdb_example_2_get_maxwell.py 292 | 293 | .. figure:: ../examples/atomdb_examples_2_1.svg 294 | :align: center 295 | :alt: AtomDB Example 2.1 296 | :figclass: align-center 297 | 298 | Excitation rates for O\ :sup:`6+`. 299 | 300 | 301 | .. figure:: ../examples/atomdb_examples_2_2.svg 302 | :align: center 303 | :alt: AtomDB Example 2.2 304 | :figclass: align-center 305 | 306 | Ionization and recombination rates for O\ :sup:`6+` to O\ :sup:`7+`. 307 | Note that for the components breakdown, there is no excitation autionization 308 | contribution in the files. 309 | 310 | 311 | 312 | ----------------------------- 313 | Calculating Plasma Conditions 314 | ----------------------------- 315 | The ``apec`` module is used for calculating plasma related phenomena. For example, 316 | ionization fractions, non-equilibrium ionization, level populations, emission spectra. 317 | Currently, it is mostly written in such a way that it is difficult to use it outside 318 | of running the entire APEC code. A rewrite will happen soon. However, for now, 319 | here are a couple of useful routines which should be useable. 320 | 321 | +++++++++++++++++++++++++++++++++ 322 | Getting Charge State Distribution 323 | +++++++++++++++++++++++++++++++++ 324 | 325 | 326 | 327 | .. literalinclude:: ../examples/apec_example_1_get_ionbal.py 328 | 329 | .. figure:: ../examples/apec_examples_1_1.svg 330 | :align: center 331 | :alt: APEC Example 1.1 332 | :figclass: align-center 333 | 334 | Ionization balance for oxygen 335 | 336 | 337 | .. figure:: ../examples/apec_examples_1_2.svg 338 | :align: center 339 | :alt: APEC Example 1.2 340 | :figclass: align-center 341 | 342 | Charge state distribution calculated many different ways for 343 | non equilibrium ionization. 344 | 345 | -------------------------------- 346 | Including APEC models in PyXSPEC 347 | -------------------------------- 348 | 349 | .. literalinclude:: ../examples/wrapper_xspec_examples.py 350 | 351 | There are other wrapper files which work in the same way for a model with 352 | a separate temperature set for line broadening, and others will be added in 353 | the ``wrapper`` directory. 354 | 355 | 356 | ---------------------------------- 357 | Resonant Scattering (rsapec) model 358 | ---------------------------------- 359 | 360 | The RSapec model can be used to model line emissivities of optically thick lines. The following code shows an application of the resonance scattering model on the Hitomi spectrum of Perseus cluster. 361 | 362 | ++++++++++++++++++++++++++++++++++++++++++++ 363 | Example script using rsapec model in PyXSPEC 364 | ++++++++++++++++++++++++++++++++++++++++++++ 365 | 366 | .. literalinclude:: ../examples/rsapec.py 367 | 368 | .. figure:: ../examples/Rsapec_hitomi.svg 369 | :align: center 370 | :alt: rsapec example 371 | :figclass: align-center 372 | 373 | The rsapec model plotted over the Hitomi observation of Perseus outer core 374 | 375 | -------------------- 376 | Individual Use Cases 377 | -------------------- 378 | 379 | These are typically scripts created to answer user's questions which might be interesting. As a result, 380 | sometimes the exact response files etc may not be available to you. Please swap in what you need to. 381 | 382 | +++++++++++++++++++++ 383 | Get PI Cross Sections 384 | +++++++++++++++++++++ 385 | 386 | Extract the PI cross section data: ``photoionization_data.py`` 387 | 388 | .. literalinclude:: ../examples/photoionization_data.py 389 | 390 | ++++++++++++++++++ 391 | Make Cooling Curve 392 | ++++++++++++++++++ 393 | 394 | Make a cooling curve, total emissivity in keV cm3 s-1, for each element 395 | in a specfied spectral range (e.g. 2 to 10 keV). 396 | 397 | .. literalinclude:: ../examples/calc_power.py 398 | 399 | .. figure:: ../examples/calc_power_examples_1_1.svg 400 | :align: center 401 | :alt: Calc Power Example 1.1 402 | :figclass: align-center 403 | 404 | The total emissivity of the plasma between 0.001 and 100 keV. 405 | 406 | .. |cm3| replace:: cm\ :sup:`3` 407 | .. |cm-3| replace:: cm\ :sup:`-3` 408 | .. |cm-3s| replace:: cm\ :sup:`-3` s\ :sup:`1` 409 | .. |cm3s-1| replace:: cm\ :sup:`3` s\ :sup:`-1` 410 | 411 | -------------------------------------------------------------------------------- /pyatomdb/docs/index.rst: -------------------------------------------------------------------------------- 1 | .. PyAtomDB documentation master file, created by 2 | sphinx-quickstart on Fri Sep 18 17:07:36 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ================= 7 | PyAtomDB & AtomDB 8 | ================= 9 | 10 | The `AtomDB Project `_ consists of a large atomic database 11 | designed for creating spectra of collisionally excited plasmas in the UV and 12 | X-ray wavebands for use in astronomy and astrophysics research. 13 | It has been successfully used for some time within several 14 | different spectral analysis suites, such as `XSPEC `_ 15 | and `Sherpa `_. 16 | 17 | There are two main parts to AtomDB: 18 | 19 | The Astrophysical Plasma Emission Database (APED) 20 | A series of `FITS `_ 21 | files which store the atomic data necessary for modelling emission from collisional plasmas 22 | from elements from H through to Zn. 23 | 24 | The Astrophysical Plasma Emission Code (APEC) 25 | Code which takes the APED and uses it to model a collisional 26 | plasma, creating emissivity files for line and continuum emission. These output files are 27 | then used in a range of models such as the ``apec``, ``nei`` and ``pshock`` models amongst others. 28 | 29 | Starting in 2015, PyAtomDB was developed to achieve a number of goals: 30 | 31 | #. To replace the APEC code (formerly in C) with a more flexible tool for larger data sets 32 | #. To allow interactive user access to the underlying database, which was always freely 33 | available but sometimes difficult to use 34 | #. To enable creating more flexible spectra based on the outputs of AtomDB 35 | #. To enhance the types of spectra which can be modeled in AtomDB, and astronomer interaction 36 | with these models 37 | #. To facililtate inclusion of AtomDB models in other software (often python based). 38 | 39 | 40 | 41 | ======== 42 | Contents 43 | ======== 44 | 45 | .. contents:: 46 | :depth: 2 47 | :backlinks: entry 48 | 49 | .. toctree:: 50 | :maxdepth: 4 51 | 52 | installation 53 | examples 54 | modules 55 | license 56 | contact 57 | 58 | 59 | 60 | ======= 61 | Outline 62 | ======= 63 | 64 | 65 | PyAtomDB is a selection of utilities designed to interact with the `AtomDB 66 | database `_ . These utilities are under constant development. Please get in touch with any issues that arise. 67 | 68 | 69 | There are several different modules currently. These are: 70 | 71 | :doc:`atomdb ` 72 | A series of codes for interacting with the AtomDB atomic database 73 | :doc:`atomic ` 74 | Basic atomic data routines - e.g. converting element symbols to atomic number, etc. 75 | :doc:`const ` 76 | Physical and code related constants 77 | :doc:`spectrum ` 78 | Routines for generating spectra from the published AtomDB line and continuum emissivity files 79 | :doc:`util ` 80 | Utility codes (sorting etc) that pyatomdb relies on. 81 | :doc:`apec ` 82 | The full APEC code 83 | 84 | To report bugs or make feature requests, email the code authors or raise an issue at the `github page `_ 85 | 86 | 87 | 88 | 89 | ================== 90 | Indices and tables 91 | ================== 92 | 93 | * :ref:`genindex` 94 | * :ref:`modindex` 95 | * :ref:`search` 96 | 97 | -------------------------------------------------------------------------------- /pyatomdb/docs/installation.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | .. warning:: 6 | PyAtomDB runs only under Python 3. It will not work on Python 2. If you 7 | need to install Python 3 in your system, you can use your package manager 8 | or there are many other sources which 9 | can help you including `Anaconda `_. 10 | 11 | Once you have Python 3 installed, you may (depending on your system) 12 | have to add a ``3`` to many 13 | of the command line commands, e.g. ``python`` becomes ``python3``, or 14 | ``pip`` becomes ``pip3``. Commands in this guide omit the ``3``. Note 15 | that actual Python code is unaffected. 16 | 17 | 18 | 19 | PyAtomDB can be installed in two ways: 20 | 21 | #. From `PyPI `_ , using the simple ``pip install pyatomdb`` command. 22 | #. From `GitHub `_ , using the command ``git clone https://github.com/AtomDB/pyatomdb.git`` to get the source, then ``pip install -e python ``. 23 | #. If using ``Conda``: Pyatomdb is not packaged with Conda as it requires compiling of some C code and (as far as I can tell) Conda cannot handle this. I recommend installing the dependencies independently, e.g.: ``conda install requests wget "numpy>=1.9.0" "scipy>=1.9.0" joblib mock astropy pycurl``, then install pip within conda (``conda install pip``), and then ``pip install -e python ``. 24 | #. Using ``setuptools`` (deprecated): python setup.py install 25 | 26 | Note that for the PyPI and setuptools options the ``--user`` option can be useful, as it will install software in your local path if you do not have administrator priviledges on your machine. 27 | 28 | You can check that the installation was successful by running: 29 | 30 | .. code-block:: python 31 | 32 | >>> import pyatomdb 33 | 34 | If it does not immediately throw out an error, it has been successful. It will 35 | then start asking about installing the AtomDB files, see the next section. Note 36 | that there is no longer a need to run the initialize script. 37 | 38 | 39 | .. warning:: 40 | pycURL issues can arise when installing. If your install above worked without 41 | errors, then you are fine. If you encountered errors, and they are related to 42 | pycurl, you will need to consult your system's package manager (or conda if 43 | that is what you are using) and install pycurl separately - 44 | e.g. ``conda install pycurl``. 45 | 46 | I'm not sure why this refuses to install directly with pip sometimes, but it seems to be a recurring feature. 47 | 48 | 49 | ---------------- 50 | ATOMDB Directory 51 | ---------------- 52 | Whenever you import the PyAtomDB module, it performs a check for the $ATOMDB directory. 53 | This directory is where the AtomDB data files will be stored. These are not 54 | distributed with the python package as they are large and most people will only need 55 | a few. PyAtomDB will download the APED data files on demand as you require them, and 56 | they are then stored in this directory until you manually delete them. If you need to 57 | recover disk space, you can delete anything in the $ATOMDB/APED directory without 58 | repercussions - PyAtomDB will re-download the files if it needs them in the future. 59 | 60 | You will be asked to select a directory for installation and then whether to download 61 | the emissivity files. It is important that this directory is one where you have write 62 | access, as in the future further files will be added there by the code automatically. 63 | 64 | Once installation is complete, ensure that you add the ATOMDB variable to your 65 | shell startup file. Assuming you have installed into /home/username/atomdb, 66 | in bash, add this line to your ~/.bashrc or ~/.bash_profile files 67 | (depends on which one is sourced by your system): 68 | 69 | .. code-block:: bash 70 | 71 | export ATOMDB=/home/username/atomdb 72 | 73 | or for csh, add this to your ~/.cshrc or ~/.cshrc.login: 74 | 75 | .. code-block:: csh 76 | 77 | setenv ATOMDB /home/username/atomdb 78 | 79 | Recent version of Mac OS have moved to zsh, in which case modify your ~/.zshrc file as for bash above. 80 | 81 | --------------------- 82 | Usage Data Collection 83 | --------------------- 84 | 85 | You will also be asked about anonymous usage data. In order to track roughly how many 86 | people are using PyAtomDB, a randomly generated number is created when you install 87 | PyAtomDB and stored in your ``$ATOMDB/userdata`` file. Whenever PyAtomDB has to fetch 88 | a new file this number, the filename and the current timestamp is stored on our 89 | system so we can estimate how many users there are. We have no way to connect this 90 | to actual individuals, it simply tells us roughly how many unique active users 91 | there are. 92 | 93 | If you decline, this number is set to 00000000, and otherwise PyAtomDB functions 94 | as normal. 95 | -------------------------------------------------------------------------------- /pyatomdb/docs/license.rst: -------------------------------------------------------------------------------- 1 | License 2 | ======= 3 | 4 | .. include:: ../COPYING.txt 5 | -------------------------------------------------------------------------------- /pyatomdb/docs/modules.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Module Documentation 3 | ==================== 4 | 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | 9 | apec 10 | atomic 11 | atomdb 12 | const 13 | spectrum 14 | util 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pyatomdb/docs/requirements.txt: -------------------------------------------------------------------------------- 1 | astropy 2 | wget 3 | sphinx 4 | scipy 5 | requests 6 | joblib 7 | numpydoc 8 | sphinx_rtd_theme 9 | -------------------------------------------------------------------------------- /pyatomdb/docs/spectrum.rst: -------------------------------------------------------------------------------- 1 | spectrum module 2 | ==================================== 3 | 4 | This module contains codes for creating spectra from the AtomDB emissivity files 5 | 6 | .. automodule:: pyatomdb.spectrum 7 | :members: 8 | :undoc-members: 9 | :inherited-members: 10 | :show-inheritance: 11 | -------------------------------------------------------------------------------- /pyatomdb/docs/util.rst: -------------------------------------------------------------------------------- 1 | util module 2 | =========== 3 | 4 | This modules contains simple utility codes (sorting, file handling etc) that pyatomdb relies on. 5 | 6 | .. automodule:: pyatomdb.util 7 | :members: 8 | :undoc-members: 9 | :inherited-members: 10 | :show-inheritance: 11 | -------------------------------------------------------------------------------- /pyatomdb/examples/aciss_meg1_cy22.garf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/aciss_meg1_cy22.garf -------------------------------------------------------------------------------- /pyatomdb/examples/aciss_meg1_cy22.grmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/aciss_meg1_cy22.grmf -------------------------------------------------------------------------------- /pyatomdb/examples/ah100040030_sxs_cl2_HP_small.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/ah100040030_sxs_cl2_HP_small.rmf -------------------------------------------------------------------------------- /pyatomdb/examples/ah100040030sxs_p0px1010_cl2_HP.pi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/ah100040030sxs_p0px1010_cl2_HP.pi -------------------------------------------------------------------------------- /pyatomdb/examples/ah100040030sxs_p0px1010_ptsrc.arf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/ah100040030sxs_p0px1010_ptsrc.arf -------------------------------------------------------------------------------- /pyatomdb/examples/apec_example_1_get_ionbal.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | # Calculate an equilibrium ionization balance for an element 4 | kT = 0.5 5 | Z = 8 6 | 7 | # going to declare a datacache to speed up the calculations as we 8 | # will be repeating things 9 | datacache = {} 10 | 11 | ionfrac_fast = pyatomdb.apec.return_ionbal(Z, kT, teunit='keV', datacache=datacache) 12 | 13 | # The "fast" keyword makes the code open up a precalculated set of 14 | # ionization balance data, a grid os 1251 values from 10^4K <= T <= 10^9K. 15 | # By default it is true. Here, we turn it off for comparison 16 | ionfrac_slow = pyatomdb.apec.return_ionbal(Z, kT, teunit='keV', datacache=datacache, 17 | fast=False) 18 | 19 | fig = pylab.figure() 20 | fig.show() 21 | ax = fig.add_subplot(111) 22 | 23 | ax.semilogy(range(0,Z+1), ionfrac_fast, 'o', label='fast') 24 | ax.semilogy(range(0,Z+1), ionfrac_slow, '^', label='slow') 25 | ax.set_ylim([1e-6,1]) 26 | ax.set_xlabel('Ion Charge') 27 | ax.set_ylabel('Fraction') 28 | ax.legend(loc=0) 29 | 30 | pylab.draw() 31 | zzz=input("Press enter to continue") 32 | # save image files 33 | fig.savefig('apec_examples_1_1.pdf') 34 | fig.savefig('apec_examples_1_1.svg') 35 | 36 | 37 | # now to do the same for several different ways of defining non-equilbrium: 38 | tau = 1e11 39 | # 1: from neutral 40 | init_pop='ionizing' # this is the default 41 | nei1 = pyatomdb.apec.return_ionbal(Z, kT, tau = tau, init_pop = init_pop, 42 | teunit='keV', datacache=datacache) 43 | 44 | 45 | # 2: from fully stripped 46 | init_pop='recombining' 47 | nei2 = pyatomdb.apec.return_ionbal(Z, kT, tau = tau, init_pop = init_pop, 48 | teunit='keV', datacache=datacache) 49 | 50 | 51 | # 3: from a given Temperature 52 | init_pop=0.1 53 | nei3 = pyatomdb.apec.return_ionbal(Z, kT, tau = tau, init_pop = init_pop, 54 | teunit='keV', datacache=datacache) 55 | 56 | 57 | # 4: from a given array 58 | init_pop=numpy.array([0.1, #O0+ 59 | 0.1, #O1+ 60 | 0.1, #O2+ 61 | 0.1, #etc 62 | 0.3, 63 | 0.1, 64 | 0.1, 65 | 0.1, 66 | 0.0]) 67 | nei4 = pyatomdb.apec.return_ionbal(Z, kT, tau = tau, init_pop = init_pop, 68 | teunit='keV', datacache=datacache) 69 | 70 | # 5: from a dict of arrays 71 | # (this is useful if you have lots of elements to do) 72 | init_pop = {} 73 | init_pop[8] = numpy.array([0.5, #O0+ 74 | 0.0, #O1+ 75 | 0.0, #O2+ 76 | 0.0, #etc 77 | 0.0, 78 | 0.0, 79 | 0.0, 80 | 0.0, 81 | 0.5]) 82 | nei5 = pyatomdb.apec.return_ionbal(Z, kT, tau = tau, init_pop = init_pop, 83 | teunit='keV', datacache=datacache) 84 | 85 | ax.cla() 86 | ax.semilogy(range(Z+1), nei1, 'o', label='ionizing') 87 | ax.semilogy(range(Z+1), nei2, '<', label='recombining') 88 | ax.semilogy(range(Z+1), nei3, 's', label='0.1keV') 89 | ax.semilogy(range(Z+1), nei4, '^', label='array') 90 | ax.semilogy(range(Z+1), nei5, 'x', label='dict') 91 | 92 | ax.set_ylim([1e-6,1]) 93 | ax.set_xlabel('Ion Charge') 94 | ax.set_ylabel('Fraction') 95 | ax.legend(loc=0) 96 | 97 | pylab.draw() 98 | zzz=input("Press enter to continue") 99 | # save image files 100 | fig.savefig('apec_examples_1_2.pdf') 101 | fig.savefig('apec_examples_1_2.svg') 102 | -------------------------------------------------------------------------------- /pyatomdb/examples/apec_examples_1_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/apec_examples_1_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/apec_examples_1_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/apec_examples_1_2.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/atomdb_example_1_get_data.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, time 2 | 3 | # Example of using get data. I am going to get a range of different atomic data 4 | # 5 | # This routine returns the raw opened FITS data. No other processing is done. 6 | 7 | Z = 8 8 | z1 = 7 9 | 10 | # get the energy levels of O VII 11 | 12 | a = pyatomdb.atomdb.get_data(Z,z1,'LV') 13 | 14 | # print out the first few lines 15 | # note that for all the atomic data files, the useful data is in HDU 1. 16 | 17 | print(a[1].data.names) 18 | 19 | print(a[1].data[:5]) 20 | 21 | # get radiative transition information 22 | b = pyatomdb.atomdb.get_data(Z,z1,'LA') 23 | 24 | # find the transitions from level 7 25 | 26 | bb = b[1].data[ (b[1].data['UPPER_LEV']==7)] 27 | print() 28 | print(bb.names) 29 | print(bb) 30 | 31 | # and so on. 32 | 33 | # For non ion-specific data, Z and z1 are ignored. 34 | 35 | abund = pyatomdb.atomdb.get_data(0,0,'ABUND') 36 | print() 37 | print(abund[1].data.names) 38 | print(abund[1].data[:2]) 39 | 40 | 41 | # How the datacache works 42 | # The datacache variable stores opened files in memory, preventing 43 | # having to go and re-open them each time. This reduces disk access. 44 | 45 | # make sure file is downloaded for a fair test: 46 | a = pyatomdb.atomdb.get_data(Z,z1,'EC') 47 | 48 | # case 1: no datacache 49 | t1 = time.time() 50 | for i in range(10): 51 | a = pyatomdb.atomdb.get_data(Z,z1,'EC') 52 | t2 = time.time() 53 | 54 | # case 2: using datacache 55 | datacache = {} 56 | t3 = time.time() 57 | for i in range(10): 58 | a = pyatomdb.atomdb.get_data(Z,z1,'EC', datacache=datacache) 59 | t4 = time.time() 60 | 61 | print("Time without / with datacache: %f / %f seconds"%(t2-t1, t4-t3)) 62 | -------------------------------------------------------------------------------- /pyatomdb/examples/atomdb_example_2_get_maxwell.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | # We will get some maxwellian rates for a O 6+ 7->1 4 | 5 | Z = 8 6 | z1 = 7 7 | up = 7 8 | lo = 1 9 | 10 | # excitation 11 | 12 | Te = numpy.logspace(6, 7, 15) 13 | 14 | # >>> # (1) Get excitation rates for row 12 of an Fe XVII file 15 | # >>> colldata = pyatomdb.atomdb.get_data(26,17,'EC') 16 | # >>> exc, dex = get_maxwell_rate(Te, colldata=colldata, index=12) 17 | 18 | # >>> # (2) Get excitation rates for row 12 of an Fe XVII file 19 | # >>> exc, dex = get_maxwell_rate(Te, Z=26,z1=17, index=12) 20 | 21 | # >>> (3) Get excitation rates for transitions from level 1 to 15 of FE XVII 22 | # >>> exc, dex = get_maxwell_rate(Te, Z=26, z1=17, dtype='EC', finallev=15, initlev=1) 23 | 24 | datacache = {} 25 | 26 | # get data by specifying ion, upper and lower levels 27 | exc, dexc = pyatomdb.atomdb.get_maxwell_rate(Te, Z=Z, z1=z1, initlev = lo, finallev=up, dtype='EC', datacache=datacache) 28 | 29 | fig= pylab.figure() 30 | fig.show() 31 | ax = fig.add_subplot(111) 32 | ax.loglog(Te, exc, label='excitation') 33 | ax.loglog(Te, dexc, label = 'deexcitation') 34 | 35 | 36 | # preload data and find a specific transition 37 | ecdat = pyatomdb.atomdb.get_data(8,7,'EC', datacache=datacache) 38 | 39 | i = numpy.where( (ecdat[1].data['Upper_Lev']==up) &\ 40 | (ecdat[1].data['Lower_Lev']==lo))[0][0] 41 | 42 | exc, dex = pyatomdb.atomdb.get_maxwell_rate(Te,colldata=ecdat, index=i, datacache=datacache) 43 | 44 | ax.loglog(Te, exc, 'o', label='excitation') 45 | ax.loglog(Te, dexc, 'o', label = 'deexcitation') 46 | 47 | ax.legend(loc=0) 48 | ax.set_xlabel("Temperature (K)") 49 | ax.set_ylabel("Rate Coefficient (cm$^3$ s$^{-1}$)") 50 | 51 | pylab.draw() 52 | zzz=input("Press enter to continue") 53 | # save image files 54 | fig.savefig('atomdb_examples_2_1.pdf') 55 | fig.savefig('atomdb_examples_2_1.svg') 56 | 57 | # you can also obtain ionization or recombination rates (see get_maxwell_rates writeup for options) 58 | # in most cases you need to specify initlev and finallev as 1 to get the ion to ion rates. 59 | 60 | ion= pyatomdb.atomdb.get_maxwell_rate(Te,Z=Z, z1=z1, initlev=1, finallev=1, dtype='CI', datacache=datacache) 61 | print(ion) 62 | # 63 | # However it is recommended that you use get_ionrec_rate instead - it gives you everythign in one go 64 | 65 | # combining the different types 66 | ion, rec = pyatomdb.atomdb.get_ionrec_rate(Te, Z=Z, z1=z1, datacache=datacache) 67 | 68 | # as separate entities 69 | CI, EA, RR, DR=pyatomdb.atomdb.get_ionrec_rate(Te, Z=Z, z1=z1, datacache=datacache, separate=True) 70 | 71 | print("Collisional ionization: ",CI) 72 | print("Excitation Autoionization: ",EA) 73 | print("Radiative Recombination: ",RR) 74 | print("Dielectroni Recombination: ",DR) 75 | ax.cla() 76 | 77 | ax.loglog(Te, ion, label='Ionization') 78 | ax.loglog(Te, rec, label='Recombination') 79 | 80 | ax.loglog(Te, CI, '--',label='CI') 81 | ax.loglog(Te, EA, '--',label='EA') 82 | ax.loglog(Te, RR, '--',label='RR') 83 | ax.loglog(Te, DR, '--',label='DR') 84 | 85 | ax.legend(loc=0) 86 | ax.set_xlabel("Temperature (K)") 87 | ax.set_ylabel("Rate Coefficient (cm$^3$ s$^{-1}$)") 88 | 89 | pylab.draw() 90 | zzz=input("Press enter to continue") 91 | # save image files 92 | fig.savefig('atomdb_examples_2_2.pdf') 93 | fig.savefig('atomdb_examples_2_2.svg') 94 | 95 | 96 | #get_maxwell_rate(Te, colldata=False, index=-1, lvdata=False, Te_unit='K', \ 97 | # lvdatap1=False, ionpot = False, \ 98 | # force_extrap=False, silent=True,\ 99 | # finallev=False, initlev=False,\ 100 | # Z=-1, z1=-1, dtype=False, exconly=False,\ 101 | # datacache=False, settings=False, ladat=False): 102 | -------------------------------------------------------------------------------- /pyatomdb/examples/atomdb_examples_2_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/atomdb_examples_2_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/atomdb_examples_2_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/atomdb_examples_2_2.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/calc_power.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, os, pylab 2 | 3 | """ 4 | This code is an example of generating a cooling curve: the total power 5 | radiated in keV cm3 s-1 by each element at each temperature. It will 6 | generate a text file with the emission per element at each temperature 7 | from 1e4 to 1e9K. 8 | 9 | This is similar to the atomdb.lorentz_power function, but with a few 10 | normalizations removed to run a little quicker. 11 | 12 | Note that the Anders and Grevesse (1989) abundances are built in to 13 | this. These can be looked up using atomdb.get_abundance(abundset='AG89'), 14 | or the 'angr' column of the table at 15 | https://heasarc.nasa.gov/xanadu/xspec/xspec11/manual/node33.html#SECTION00631000000000000000 16 | 17 | Adjustable parameters (energy range, element choice) are in the block 18 | marked #### ADJUST THINGS HERE 19 | 20 | Note that any warnings of the nature: 21 | "kT = 0.000862 is below minimum range of 0.000862. Returning lowest kT spectrum available" 22 | should be ignored. This is returning the temperature at our lowest tabulated value but is 23 | a rounding error making it think it is outside our range. 24 | 25 | Usage: python3 calc_power.py 26 | """ 27 | 28 | def calc_power(Zlist, cie, Tlist): 29 | 30 | """ 31 | Zlist : [int] 32 | List of element nuclear charges 33 | cie : CIESession 34 | The CIEsession object with all the relevant data predefined. 35 | Tlist : array(float) 36 | The temperatures at which to calculate the power (in K) 37 | """ 38 | 39 | res = {} 40 | res['power'] = {} 41 | res['temperature'] = [] 42 | cie.set_abund(numpy.arange(1,31), 0.0) 43 | kTlist = Tlist*pyatomdb.const.KBOLTZ 44 | en = (cie.ebins_out[1:]+cie.ebins_out[:-1])/2 45 | for i, kT in enumerate(kTlist): 46 | 47 | 48 | print("Doing temperature iteration %i of %i"%(i, len(kTlist))) 49 | T = Tlist[i] 50 | 51 | res['temperature'].append(T) 52 | res['power'][i] = {} 53 | 54 | for Z in Zlist: 55 | 56 | if Z==0: 57 | # This is the electron-electron bremstrahlung component alone 58 | 59 | #set all abundances to 1 (I need a full census of electrons in the plasma for e-e brems) 60 | cie.set_abund(Zlist[1:], 1.0) 61 | # turn on e-e bremsstrahlung, turn off everything else: 62 | cie.dolines = False # Exclude lines in spectrum 63 | cie.docont = False # Exclude continuum in spectrum 64 | cie.dopseudo = False # Exclude pseudo continuum in spectrum 65 | cie.do_eebrems = True # Do electron-electron bremsstrahlung 66 | 67 | spec = cie.return_spectrum(kT) 68 | 69 | # Turn them back on 70 | # Turn off eebrems 71 | cie.dolines = True 72 | cie.docont = True 73 | cie.dopseudo = True 74 | cie.do_eebrems = False 75 | 76 | else: 77 | # This is everything else, element by element. 78 | 79 | # turn off all the elements 80 | cie.set_abund(Zlist[1:], 0.0) 81 | # turn back on this element 82 | cie.set_abund(Z, 1.0) 83 | 84 | spec = cie.return_spectrum(kT) 85 | # if Z = 1, do the eebrems (only want to calculate this once) 86 | # if Z == 1: 87 | # cie.set_eebrems(True) 88 | # else: 89 | # cie.set_eebrems(False) 90 | 91 | 92 | # get spectrum in ph cm3 s-1 93 | #spec = cie.return_spectrum(kT) 94 | 95 | # convert to keV cm3 s-1, sum 96 | res['power'][i][Z] = sum(spec*en) 97 | 98 | return res 99 | 100 | if __name__=='__main__': 101 | 102 | ############################ 103 | #### ADJUST THINGS HERE #### 104 | ############################ 105 | 106 | # Elements to include 107 | #Zlist = range(31) <- all the elements 108 | Zlist = [0,1,2,6,7,8,10,12,13,14,16,18,20,26,28] #<- just a few 109 | # Note that for this purpose, Z=0 is the electron-electron bremsstrahlung 110 | # continuum. This is not a general AtomDB convention, just what I've done here 111 | # to make this work. 112 | 113 | # specify photon energy range you want to integrate over (min = 0.001keV, max=100keV) 114 | Elo = 0.001 #keV 115 | Ehi = 100.0 # 116 | 117 | # temperatures at which to calculate curve (K) 118 | Tlist = numpy.logspace(4,9,51) 119 | 120 | # specify output file name (default output.txt) 121 | outfile = 'output.txt' 122 | 123 | ################################ 124 | #### END ADJUST THINGS HERE #### 125 | ################################ 126 | 127 | # set up the spectrum 128 | cie = pyatomdb.spectrum.CIESession() 129 | ebins = numpy.linspace(Elo, Ehi, 10001) 130 | cie.set_response(ebins, raw=True) 131 | cie.set_eebrems(True) 132 | # crunch the numbers 133 | k = calc_power(Zlist, cie, Tlist) 134 | 135 | # output generation 136 | o = open(outfile, 'w') 137 | 138 | # header row 139 | s = '# Temperature log10(K)' 140 | for i in range(len(Zlist)): 141 | s += ' %12i'%(Zlist[i]) 142 | o.write(s+'\n') 143 | 144 | # for each temperature 145 | k['totpower'] = numpy.zeros(len(k['temperature'])) 146 | 147 | for i in range(len(k['temperature'])): 148 | s = '%22e'%(numpy.log10(k['temperature'][i])) 149 | for Z in Zlist: 150 | s+=' %12e'%(k['power'][i][Z]) 151 | k['totpower'][i]+=k['power'][i][Z] 152 | o.write(s+'\n') 153 | 154 | # notes 155 | o.write("# Total Emissivity in keV cm^3 s^-1 for each element with AG89 abundances, between %e and %e keV\n"%(Elo, Ehi)) 156 | o.write("# To get cooling power, multiply by Ne NH") 157 | o.write("# Z=0 component is electron-electron bremsstrahlung component, only significant at high T") 158 | o.close 159 | 160 | fig = pylab.figure() 161 | fig.show() 162 | ax = fig.add_subplot(111) 163 | 164 | ax.loglog(k['temperature'], k['totpower']*pyatomdb.const.ERG_KEV) 165 | 166 | ax.set_xlabel('Temperature (K)') 167 | ax.set_ylabel('Radiated Power (erg cm$^3$ s$^{-1}$)') 168 | 169 | ax.set_xlim(min(Tlist), max(Tlist)) 170 | 171 | # draw graphs 172 | pylab.draw() 173 | 174 | zzz=input("Press enter to continue") 175 | 176 | # save image files 177 | fig.savefig('calc_power_examples_1_1.pdf') 178 | fig.savefig('calc_power_examples_1_1.svg') 179 | 180 | -------------------------------------------------------------------------------- /pyatomdb/examples/calc_power_examples_1_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/calc_power_examples_1_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/calc_power_nei.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, os, pylab 2 | import astropy.io.fits as pyfits 3 | 4 | """ 5 | This code is an example of generating a cooling curve: the total power 6 | radiated in keV cm3 s-1 by each element at each temperature. It will 7 | generate a text file with the emission per element at each temperature 8 | from 1e4 to 1e9K. This has been modified for a non-equilibrium plasma. 9 | 10 | This is similar to the atomdb.lorentz_power function, but with a few 11 | normalizations removed to run a little quicker. 12 | 13 | Note that the Anders and Grevesse (1989) abundances are built in to 14 | this. These can be looked up using atomdb.get_abundance(abundset='AG89'), 15 | or the 'angr' column of the table at 16 | https://heasarc.nasa.gov/xanadu/xspec/xspec11/manual/node33.html#SECTION00631000000000000000 17 | 18 | Adjustable parameters (energy range, element choice) are in the block 19 | marked #### ADJUST THINGS HERE 20 | 21 | Usage: python3 calc_power_nei.py 22 | """ 23 | 24 | 25 | def calc_power(Zlist, nei, Tlist, Taulist): 26 | init_pop = 'ionizing' 27 | res = {} 28 | res['power'] = numpy.zeros([len(Tlist), len(Taulist)]) 29 | res['temperature'] = [] 30 | res['tau'] = [] 31 | 32 | # get photon energy of each bin 33 | en = nei.ebins_out 34 | en = (en[1:]+en[:-1])/2 35 | 36 | for i, T in enumerate(Tlist): 37 | kT = T/(1000*11604.5) 38 | res['temperature'].append(kT) 39 | for j, Tau in enumerate(Taulist): 40 | print("Doing temperature iteration %i of %i"%(i, len(Tlist))) 41 | 42 | res['tau'].append(Tau) 43 | 44 | 45 | # This code would go through each element 1 by 1. 46 | # We will do all elements at the same time to simplify 47 | 48 | # for Z in Zlist: 49 | # if Z==0: 50 | # # This is the electron-electron bremstrahlung component alone 51 | # 52 | # #set all abundances to 1 (I need a full census of electrons in the plasma for e-e brems) 53 | # nei.set_abund(Zlist[1:], 1.0) 54 | # # turn on e-e bremsstrahlung 55 | # nei.set_eebrems(True) 56 | # spec = nei.return_spectrum(kT, Tau, init_pop=init_pop, \ 57 | # dolines=False, docont=False, dopseudo=False) 58 | # else: 59 | # # This is everything else, element by element. 60 | # 61 | # # turn off all the elements 62 | # nei.set_abund(Zlist[1:], 0.0) 63 | # # turn back on this element 64 | # nei.set_abund(Z, 1.0) 65 | # # turn off e-e bremsstrahlung (avoid double counting) 66 | # nei.set_eebrems(False) 67 | # 68 | # spec = nei.return_spectrum(kT, Tau, init_pop=init_pop) 69 | # 70 | 71 | spec = nei.return_spectrum(kT, Tau, init_pop=init_pop) 72 | E = spec*en 73 | res['power'][i][j] = sum(E) 74 | return(res) 75 | 76 | if __name__=='__main__': 77 | 78 | 79 | ############################ 80 | #### ADJUST THINGS HERE #### 81 | ############################ 82 | 83 | # Elements to include 84 | #Zlist = range(31) <- all the elements 85 | Zlist = [0,1,2,6,7,8,10,12,13,14,16,18,20,26,28] #<- just a few 86 | # Note that for this purpose, Z=0 is the electron-electron bremsstrahlung 87 | # continuum. This is not a general AtomDB convention, just what I've done here 88 | # to make this work. 89 | 90 | # specify photon energy range you want to integrate over (min = 0.001keV, max=100keV) 91 | Elo = 0.001 #keV 92 | Ehi = 100.0 # 93 | 94 | # temperatures at which to calculate curve (K) 95 | Tlist = numpy.logspace(4,9,51) 96 | 97 | # specify output file name (default output.txt) 98 | outfile = 'output.txt' 99 | 100 | ################################ 101 | #### END ADJUST THINGS HERE #### 102 | ################################ 103 | 104 | # set up the spectrum 105 | Zlist = numpy.array([0,1,2,6,7,8,10,12,13,14,16,18,20,26,28]) #<- just a few 106 | 107 | nei = pyatomdb.spectrum.NEISession(elements=Zlist[Zlist>0]) 108 | if 0 in Zlist: 109 | nei.set_eebrems(True) 110 | ebins = numpy.linspace(Elo, Ehi, 10001) 111 | nei.set_response(ebins, raw=True) 112 | nei.set_eebrems(True) 113 | # crunch the numbers 114 | Taulist = [1e8, 1e10, 1e14] 115 | k = calc_power(Zlist, nei, Tlist, Taulist) 116 | 117 | 118 | fig = pylab.figure() 119 | fig.show() 120 | ax = fig.add_subplot(111) 121 | 122 | for i, tau in enumerate(Taulist): 123 | ax.loglog(k['temperature'], k['power'][:,i]*pyatomdb.const.ERG_KEV, label=repr(int(numpy.log10(tau)))) 124 | ax.legend(loc=0) 125 | pylab.draw() 126 | 127 | ax.set_xlabel("Temperature (keV)") 128 | ax.set_ylabel("Radiated Power 0.001-100keV\n(erg cm$^{3}$ s$^{-1}$)") 129 | 130 | 131 | zzz=input("Press enter to continue") 132 | fig.savefig('calc_power_nei_examples_1_1.pdf') 133 | fig.savefig('calc_power_nei_examples_1_1.svg') 134 | -------------------------------------------------------------------------------- /pyatomdb/examples/calc_power_nei_examples_1_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/calc_power_nei_examples_1_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/first_installation.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | 3 | """ 4 | This script shows the commands you should run when you first download pyatomdb. 5 | 6 | It is recommended that you choose the location you want to install the 7 | AtomDB data files (not the same as the python module) and set your 8 | ATOMDB environment variable to point to it. 9 | 10 | 11 | Parameters 12 | ------ 13 | none 14 | 15 | Returns 16 | ------- 17 | none 18 | 19 | """ 20 | 21 | # call the setup routine 22 | pyatomdb.util.initialize() 23 | 24 | # this routine downloads a bunch of files and sets things up for you. It will 25 | # take a few minutes, depending on your internet connection. 26 | 27 | print("Install complete!") 28 | 29 | #and that's it! 30 | 31 | # If you want to switch versions of atomdb (in this case to 3.0.2) later, call: 32 | # pyatomdb.util.switch_version('3.0.2') 33 | 34 | -------------------------------------------------------------------------------- /pyatomdb/examples/make_line_list.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | 3 | """ 4 | This code will produce a list of lines in a given wavelength range at a 5 | given temperature. It also shows the use of an NEI version, where you 6 | have to additionally specify the initial ionization temperature (or the 7 | ionization fraction directly) and the elapsed Ne*t. 8 | 9 | The results of the list_lines codes are numpy arrays which can be sorted any 10 | way you wish. You can, of course, extract the lines easily at this point. There 11 | is also a print_lines routine for a fixed format output. 12 | 13 | Parameters 14 | ---------- 15 | none 16 | 17 | Returns 18 | ------- 19 | none 20 | 21 | """ 22 | 23 | # Adam Foster 2015-12-02 24 | # version 0.1 25 | 26 | #specify wavelength range, in Angstroms 27 | wl = [8.0,9.0] 28 | 29 | # electron temperature in K 30 | Te = 1e7 31 | 32 | # get equilibrium line list 33 | CIE = pyatomdb.spectrum.CIESession() 34 | 35 | res = CIE.return_linelist(Te, wl, specunit = 'A', teunit='K') 36 | 37 | #trim off the weaker lines 38 | res = res[res['Epsilon']> 1e-18] 39 | 40 | # reprocess lines for printing 41 | print("Unsorted line list:") 42 | print(CIE.format_linelist(res)) 43 | 44 | # re-sort lines 45 | # for more information, look up numpy.sort: res is a numpy array. 46 | # http://docs.scipy.org/doc/numpy/reference/generated/numpy.sort.html 47 | 48 | res.sort(order=['Epsilon']) 49 | res=res[::-1] 50 | print("Top 10 sorted by Emissivity:") 51 | print(CIE.format_linelist(res[:10])) 52 | 53 | # re-sort by element, ion then emissivity 54 | res.sort(order=['Element','Ion','Epsilon']) 55 | print("Top 10 sorted by Element, Ion, Emissivity:") 56 | print(CIE.format_linelist(res[:10])) 57 | 58 | 59 | # now do an NEI version. This is slow at the moment, but functional. 60 | Te_init = 1e4 61 | tau = 1e11 62 | NEI = pyatomdb.spectrum.NEISession() 63 | res_nei = NEI.return_linelist(Te, tau, wl, teunit='K', \ 64 | specunit='A',\ 65 | init_pop=Te_init) 66 | res_nei = res_nei[res_nei['Epsilon']> 1e-19] 67 | print("NEI linelist:") 68 | print(NEI.format_linelist(res_nei[:10])) 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /pyatomdb/examples/make_spectrum.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | # set up a grid of energy bins to model the spectrum on: 4 | ebins=numpy.linspace(0.3,10,10000) 5 | 6 | # define a broadening, in keV, for the lines 7 | de = 0.01 8 | 9 | # define the temperature at which to plot (keV) 10 | te = 3.0 11 | 12 | # declare a CIESession 13 | CIE = pyatomdb.spectrum.CIESession() 14 | 15 | # set the response. Raw keyword makes it a diagonal response 16 | # (no line spread or effective area) 17 | 18 | CIE.set_response(ebins, raw=True) 19 | 20 | # create both a broadened and an unbroadened spectrum 21 | a = CIE.return_spectrum(te) 22 | 23 | # turn on broadening 24 | CIE.set_broadening(True) 25 | b = CIE.return_spectrum(te) 26 | 27 | # plot the results 28 | fig = pylab.figure() 29 | fig.show() 30 | ax = fig.add_subplot(111) 31 | 32 | ax.loglog(ebins, numpy.append(a[0], a), drawstyle='steps', label='Unbroadened') 33 | ax.loglog(ebins, numpy.append(b[0],b), drawstyle='steps', label='Thermal') 34 | ax.set_xlabel('Energy (keV)') 35 | ax.set_ylabel('Emissivity (ph cm$^{3}$ s$^{-1}$ bin$^{-1}$)') 36 | ax.legend(loc=0) 37 | pylab.draw() 38 | zzz = input("Press enter to continue") 39 | 40 | print("Listing lines between 1 and 2 A") 41 | # now list the lines in a wavelength region 42 | llist = CIE.return_linelist(te, [1,2.0]) 43 | # print these to screen 44 | # print to screen, listing the energy, not the wavelength 45 | print("Listing lines between 1 and 2 A, first 10 lines only.") 46 | 47 | print(CIE.format_linelist(llist[:10])) 48 | 49 | -------------------------------------------------------------------------------- /pyatomdb/examples/new_make_spectrum.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, pylab, numpy, time 2 | 3 | 4 | rmf = 'aciss_meg1_cy22.grmf' 5 | arf = 'aciss_meg1_cy22.garf' 6 | 7 | 8 | # create a session object. This contains the apec files, response files, 9 | # and any previously calculated spectrs so that simple multiplication 10 | # can be used to get the results without recalculating everything from scratch 11 | 12 | data = pyatomdb.spectrum.CIESession() 13 | 14 | # If you want to specify custom energy bins: 15 | ebins = numpy.linspace(1,2,1001) 16 | data.set_response(ebins, raw=True) 17 | 18 | # alternative method: just load the response and use its binning. Note 19 | # that this will always be in keV currently, because reasons. 20 | 21 | data.set_response(rmf, arf=arf) 22 | ebins = data.ebins_out 23 | 24 | # now get the spectrum at 4keV. This calculates (and stores) the 25 | # spectrum at each temperature nearby (~3.7, 4.3 keV) 26 | # then linearly interpolates between the result 27 | # 28 | # vector is stored for each element at each temperature 29 | # so if you change temperature/abundance, it's a simple multiplication and 30 | # interpolation instead of a total recalculation 31 | 32 | t0 = time.time() 33 | s=data.return_spectrum(4.0, teunit='keV') 34 | t1 = time.time() 35 | # let's change the abundance 36 | data.set_abund([1,2,3,4,26],0.5) 37 | 38 | # and see how fast this goes this time, changing temperature and abund 39 | s2=data.return_spectrum(4.1, teunit='keV') 40 | t2 = time.time() 41 | 42 | print("first spectrum took %g seconds" %(t1-t0)) 43 | print("second spectrum took %g seconds" %(t2-t1)) 44 | print("note how much faster the second one was as I didn't recalculate everything from scratch!") 45 | 46 | 47 | #linedata = pyatomdb.pyfits.open('/export1/atomdb_latest/apec_v3.0.8_line.fits') 48 | 49 | 50 | #spec = speclo*rlo + specup*rup 51 | 52 | # some plotting of things 53 | 54 | fig = pylab.figure() 55 | fig.show() 56 | ax = fig.add_subplot(111) 57 | #ax2 = fig.add_subplot(212, sharex=ax) 58 | s = numpy.append(0,s) 59 | s += 1e-40 60 | 61 | s2 = numpy.append(0,s2) 62 | s2 += 1e-40 63 | #spec = numpy.append(0,spec) 64 | #spec += 1e-40 65 | 66 | ax.plot(ebins, s, drawstyle='steps') 67 | ax.plot(ebins, s2, drawstyle='steps') 68 | #ax.plot(elo, spec, drawstyle='steps') 69 | 70 | 71 | #ax2.plot(elo, s/spec, drawstyle='steps') 72 | 73 | 74 | zzz=input('Press enter to exit') 75 | -------------------------------------------------------------------------------- /pyatomdb/examples/osc_str.py: -------------------------------------------------------------------------------- 1 | ## Author: Priyanka Chakraborty 07/30/2022 2 | ## Description: this code add an extra column for oscillator strength to apec_v3.0.9_line.fits 3 | 4 | 5 | import numpy as np 6 | from astropy.io import fits 7 | import pandas as pd 8 | import time 9 | from itertools import compress 10 | import math 11 | #import pyatomdb 12 | import os 13 | #import atomdb,apec 14 | 15 | t = time.process_time() 16 | 17 | 18 | 19 | if os.path.exists(os.path.expandvars('$ATOMDB/apec_v3.0.9_osc.fits')) == False: 20 | 21 | emi_file = fits.open(os.path.expandvars('$ATOMDB/apec_v3.0.9_line.fits')) ## opening fits file 22 | 23 | for j in range(2,len(emi_file)): ### running loops on emissivity extension ## 24 | 25 | emi_lambda = emi_file[j].data['Lambda'] 26 | emi_elem = emi_file[j].data['Element'] 27 | emi_ion = emi_file[j].data['Ion'] 28 | emi_ulev = emi_file[j].data['UpperLev'] 29 | emi_llev = emi_file[j].data['LowerLev'] 30 | 31 | 32 | fij = [] 33 | datacache={} 34 | 35 | settings=apec.parse_par_file(os.path.expandvars('$ATOMDB/apec.par')) 36 | 37 | 38 | for i in range (len(emi_elem)): 39 | index = 0.1 40 | Z = emi_elem[i] 41 | z1 = emi_ion[i] 42 | 43 | ### fetching upperlevel and lower level from ladat and lvdat 44 | ladat = atomdb.get_data(Z,z1,'LA', datacache=datacache, settings=settings) 45 | lvdat = atomdb.get_data(Z,z1,'LV', datacache=datacache, settings=settings) 46 | 47 | if ladat != False: 48 | 49 | upper_lev = ladat[1].data['upper_lev'] 50 | lower_lev = ladat[1].data['lower_lev'] 51 | 52 | #### fetiching indices for matched upper and lower level 53 | get_indecies = lambda xx, xxs: [iii for (yy, iii) in zip(xxs, range(len(xxs))) if xx == yy] 54 | 55 | index_up = get_indecies(emi_ulev[i],upper_lev) 56 | index_lo = get_indecies(emi_llev[i],lower_lev) 57 | 58 | for ii in range(len(index_up)): 59 | if index_up[ii] in index_lo: 60 | index = index_up[ii] 61 | break 62 | 63 | if index != 0.1: 64 | 65 | #### estimating oscillator strength #### 66 | larate = ladat[1].data['EINSTEIN_A'][index] 67 | wavelength = ladat[1].data['wavelen'][index] 68 | 69 | stat_weight = lvdat[1].data['lev_deg'][upper_lev[index]-1]/(lvdat[1].data['lev_deg'][lower_lev[index]-1]) 70 | fij.append(1.4992e-8*larate*1e-8*(wavelength**2)*stat_weight) 71 | 72 | else: 73 | larate = 0.0 74 | wavelength = 0.0 75 | 76 | stat_weight = 0.0 77 | fij.append(0.0) 78 | 79 | print(j,i,Z,z1,emi_ulev[i],emi_llev[i]) 80 | 81 | #### writing oscillator strength to fits file as a new column #### 82 | osc_st = fits.Column(name='Oscil_str', array=fij,format='1E') 83 | new_column = emi_file[j].columns + osc_st 84 | new_hdu = fits.BinTableHDU.from_columns(new_column) 85 | emi_file[j].data = new_hdu.data 86 | emi_file.writeto('apec_v3.0.9_osc.fits',overwrite=True) 87 | 88 | print('elapsed time for',j,'th extension',time.process_time() - t) 89 | 90 | 91 | 92 | print('time for entire run',time.process_time() - t) 93 | 94 | emi_file.close() 95 | 96 | else: 97 | 98 | ## limiting upper wavelength limit to 40 angstorm 99 | 100 | linefile = "$ATOMDB/apec_v3.0.9_osc.fits" 101 | 102 | lfile = os.path.expandvars(linefile) 103 | linedata = fits.open(lfile) 104 | 105 | linedata[1].header['COMMENTS'] = 'The upper-limit of wavelength is 40 angstrom' 106 | 107 | ext_num = len(linedata[1].data['kT']) ## number of temperature parameters 108 | 109 | for i in range(2, ext_num): 110 | 111 | wlambda = linedata[i].data['Lambda'] 112 | wlambda_err = linedata[i].data['Lambda_Err'] 113 | epsilon = linedata[i].data['Epsilon'] 114 | epsilon_err = linedata[i].data['Epsilon_Err'] 115 | element = linedata[i].data['Element'] 116 | ion = linedata[i].data['Ion'] 117 | upperlev = linedata[i].data['UpperLev'] 118 | lowerlev = linedata[i].data['LowerLev'] 119 | oscil_str = linedata[i].data['Oscil_str'] 120 | 121 | ## getting the index where lambda > 40 ang 122 | 123 | index = np.where(wlambda < 40)[0] 124 | 125 | wlambda_new = fits.Column(name='Lambda', array=wlambda[index],format='1E') 126 | wlambda_err_new = fits.Column(name='Lambda_Err', array=wlambda_err[index],format='1E') 127 | epsilon_new = fits.Column(name='Epsilon', array=epsilon[index],format='1E') 128 | epsilon_err_new = fits.Column(name='Epsilon_Err', array=epsilon_err[index],format='1E') 129 | element_new = fits.Column(name='Element', array=element[index],format='1J') 130 | ion_new = fits.Column(name='Ion', array=ion[index],format='1J') 131 | upperlev_new = fits.Column(name='UpperLev', array=upperlev[index],format='1J') 132 | lowerlev_new = fits.Column(name='LowerLev', array=lowerlev[index],format='1J') 133 | oscil_str_new = fits.Column(name='Oscil_str', array=oscil_str[index],format='1E') 134 | 135 | new_hdu = fits.BinTableHDU.from_columns([wlambda_new, wlambda_err_new, epsilon_new, epsilon_err_new, element_new, ion_new, upperlev_new, lowerlev_new, oscil_str_new]) 136 | linedata[i].data = new_hdu.data 137 | 138 | 139 | 140 | linedata.writeto(os.path.expandvars('$ATOMDB/apec_v3.0.9_osc.fits'), overwrite=True) 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /pyatomdb/examples/output.txt: -------------------------------------------------------------------------------- 1 | # Temperature log10(K) 0 1 2 6 7 8 10 12 13 14 16 18 20 26 28 2 | 4.000000e+00 0.000000e+00 2.195959e-15 5.261469e-21 4.523786e-14 5.407950e-17 3.347558e-14 6.363935e-21 5.648319e-15 3.320730e-17 6.142661e-15 4.189772e-15 1.396110e-20 1.212614e-16 8.121514e-15 9.522474e-17 3 | 4.100000e+00 0.000000e+00 2.379262e-14 6.483396e-19 4.053404e-14 2.412571e-16 4.592931e-14 1.653105e-19 6.590210e-15 8.210325e-17 1.463061e-15 3.275290e-15 1.956645e-19 2.823361e-16 9.455144e-15 1.209662e-16 4 | 4.200000e+00 0.000000e+00 8.487070e-14 3.057073e-17 1.491507e-14 1.706225e-15 3.167218e-14 2.215953e-18 7.116494e-15 1.875367e-16 9.484036e-16 3.714312e-15 1.113854e-18 2.920430e-16 1.068787e-14 1.644499e-16 5 | 4.300000e+00 0.000000e+00 6.978293e-14 6.713104e-16 7.677669e-15 4.418319e-15 2.396890e-14 1.635206e-17 3.372379e-15 3.726760e-16 1.501606e-15 4.362858e-15 2.466714e-18 1.040153e-16 8.030644e-15 1.869592e-16 6 | 4.400000e+00 0.000000e+00 3.977845e-14 6.921377e-15 9.228002e-15 6.053239e-15 2.967312e-14 3.788214e-17 7.756705e-16 6.492158e-16 2.751824e-15 4.544359e-15 2.723287e-17 2.965747e-17 7.504755e-15 1.853446e-16 7 | 4.500000e+00 0.000000e+00 2.342998e-14 2.574437e-14 1.599300e-14 7.483791e-15 3.845682e-14 2.888141e-17 1.985610e-16 9.707860e-16 4.762501e-15 4.128916e-15 1.947034e-16 9.773225e-18 7.914278e-15 2.044016e-16 8 | 4.600000e+00 0.000000e+00 1.478446e-14 2.278605e-14 3.171295e-14 8.903714e-15 4.945423e-14 9.703458e-17 6.343667e-17 9.090477e-16 7.560151e-15 4.126068e-15 3.456402e-16 6.585472e-18 4.926309e-15 2.219130e-16 9 | 4.700000e+00 0.000000e+00 9.920347e-15 2.030359e-14 6.237693e-14 1.087040e-14 6.449884e-14 5.864157e-16 2.467847e-17 2.709168e-16 1.114469e-14 4.830316e-15 4.747119e-16 1.491276e-17 2.992966e-15 2.252101e-16 10 | 4.800000e+00 0.000000e+00 7.014237e-15 3.473816e-14 1.063634e-13 1.527021e-14 8.682272e-14 1.956662e-15 1.300999e-17 6.306839e-17 1.485882e-14 6.229224e-15 7.093201e-16 4.550725e-17 3.341292e-15 2.123360e-16 11 | 4.900000e+00 0.000000e+00 5.200220e-15 6.214042e-14 1.537850e-13 2.259194e-14 1.184434e-13 4.123644e-15 1.919092e-17 1.884960e-17 1.124295e-14 8.681712e-15 1.114727e-15 1.180792e-16 4.331414e-15 1.692964e-16 12 | 5.000000e+00 0.000000e+00 4.026130e-15 4.997439e-14 1.576903e-13 3.224212e-14 1.617901e-13 7.614470e-15 7.325795e-17 7.548654e-18 2.837977e-15 1.195943e-14 1.668858e-15 2.593129e-16 5.358048e-15 1.282324e-16 13 | 5.100000e+00 0.000000e+00 3.239060e-15 2.978967e-14 5.567488e-14 4.273280e-14 2.201737e-13 1.329159e-14 2.746179e-16 5.771556e-18 6.770713e-16 1.470368e-14 2.338679e-15 4.939399e-16 6.037933e-15 9.230286e-17 14 | 5.200000e+00 0.000000e+00 2.706216e-15 1.786532e-14 1.190646e-14 4.694527e-14 2.858023e-13 2.030703e-14 8.147993e-16 1.337471e-17 2.294897e-16 1.589466e-14 3.050145e-15 8.485639e-16 6.454971e-15 8.535107e-17 15 | 5.300000e+00 0.000000e+00 2.338926e-15 1.130942e-14 3.317182e-15 2.399501e-14 3.448630e-13 2.850150e-14 1.996075e-15 4.424592e-17 1.659653e-16 8.528958e-15 3.810216e-15 1.321806e-15 7.731081e-15 1.253471e-16 16 | 5.400000e+00 0.000000e+00 2.085772e-15 7.556607e-15 1.213071e-15 5.593975e-15 3.733613e-13 3.784446e-14 3.747795e-15 1.180525e-16 3.641595e-16 1.582745e-15 4.571530e-15 1.862882e-15 1.170315e-14 2.282291e-16 17 | 5.500000e+00 0.000000e+00 1.916401e-15 5.312333e-15 5.443221e-16 1.515455e-15 2.301839e-13 4.659649e-14 5.758403e-15 2.450500e-16 1.069277e-15 4.332986e-16 4.550832e-15 2.430615e-15 1.939321e-14 3.761546e-16 18 | 5.600000e+00 0.000000e+00 1.812090e-15 3.913869e-15 3.121876e-16 5.513114e-16 7.233421e-14 5.342084e-14 7.915959e-15 4.255338e-16 2.530950e-15 3.340753e-16 1.315883e-15 2.935095e-15 2.967825e-14 5.953101e-16 19 | 5.700000e+00 0.000000e+00 1.756744e-15 3.009040e-15 3.279648e-16 2.525029e-16 2.339497e-14 5.416175e-14 1.031831e-14 6.563420e-16 4.634576e-15 5.927858e-16 2.632437e-16 2.995773e-15 4.146163e-14 9.693602e-16 20 | 5.800000e+00 3.025610e-19 1.733704e-15 2.411872e-15 6.798999e-16 1.568052e-16 9.191744e-15 3.344187e-14 1.253453e-14 8.720664e-16 7.055122e-15 1.219487e-15 1.350332e-16 1.060280e-15 5.357773e-14 1.467626e-15 21 | 5.900000e+00 3.994178e-19 1.744344e-15 2.010624e-15 1.398881e-15 1.813787e-16 4.428682e-15 1.085051e-14 1.392244e-14 1.023310e-15 9.379979e-15 2.141594e-15 1.739253e-16 2.552298e-16 6.442704e-14 2.002882e-15 22 | 6.000000e+00 5.321634e-19 1.784231e-15 1.738996e-15 2.068970e-15 3.419525e-16 2.970596e-15 3.626929e-15 1.172409e-14 1.098452e-15 1.105517e-14 3.086812e-15 3.140962e-16 1.532428e-16 7.103855e-14 2.469777e-15 23 | 6.100000e+00 7.153373e-19 1.850225e-15 1.559387e-15 2.075043e-15 6.053914e-16 3.331247e-15 1.547710e-15 5.042194e-15 9.354862e-16 1.163159e-14 3.928473e-15 5.341154e-16 1.791248e-16 7.039511e-14 2.757680e-15 24 | 6.200000e+00 9.694808e-19 1.941808e-15 1.445179e-15 1.498622e-15 8.192659e-16 5.009997e-15 8.763318e-16 1.703939e-15 4.478828e-16 9.806054e-15 4.717260e-15 7.669647e-16 2.712235e-16 5.182363e-14 2.677989e-15 25 | 6.300000e+00 1.323618e-18 2.054391e-15 1.379869e-15 9.889731e-16 7.859856e-16 7.068597e-15 7.354449e-16 7.146037e-16 1.659671e-16 4.926053e-15 5.189007e-15 9.565393e-16 4.072711e-16 1.648796e-14 2.110907e-15 26 | 6.400000e+00 1.818656e-18 2.192191e-15 1.347184e-15 6.682266e-16 5.818859e-16 7.916200e-15 9.036461e-16 4.062575e-16 7.290563e-17 1.957260e-15 4.180396e-15 1.092467e-15 5.465034e-16 8.959194e-15 7.981524e-16 27 | 6.500000e+00 2.512512e-18 2.355815e-15 1.345031e-15 4.729967e-16 4.020012e-16 6.584158e-15 1.259540e-15 3.321463e-16 4.205815e-17 9.219877e-16 1.961184e-15 1.088918e-15 6.490998e-16 8.588184e-15 3.592110e-16 28 | 6.600000e+00 3.486918e-18 2.546398e-15 1.368873e-15 3.518178e-16 2.827107e-16 4.688537e-15 1.575536e-15 3.779031e-16 3.368980e-17 5.713324e-16 8.146731e-16 7.511087e-16 6.979473e-16 1.025796e-14 3.068325e-16 29 | 6.700000e+00 4.857786e-18 2.765690e-15 1.415888e-15 2.739061e-16 2.070704e-16 3.269336e-15 1.539579e-15 4.941534e-16 3.628599e-17 4.809133e-16 4.262546e-16 3.442246e-16 5.973832e-16 1.280994e-14 3.336016e-16 30 | 6.800000e+00 6.789176e-18 3.021123e-15 1.485232e-15 2.224246e-16 1.583793e-16 2.348873e-15 1.212917e-15 6.116169e-16 4.465527e-17 5.197750e-16 3.004914e-16 1.626566e-16 3.256128e-16 1.537506e-14 4.028480e-16 31 | 6.900000e+00 9.513259e-18 3.310679e-15 1.572537e-15 1.877794e-16 1.262966e-16 1.766761e-15 8.793106e-16 6.320902e-16 5.265170e-17 6.220229e-16 2.785384e-16 9.901991e-17 1.525211e-16 1.688100e-14 4.841186e-16 32 | 7.000000e+00 1.335866e-17 3.637298e-15 1.680157e-15 1.644667e-16 1.046359e-16 1.393156e-15 6.394130e-16 5.411664e-16 5.293728e-17 7.078017e-16 3.073347e-16 7.935219e-17 8.689384e-17 1.597647e-14 5.387067e-16 33 | 7.100000e+00 1.879025e-17 4.003487e-15 1.808541e-15 1.491995e-16 8.982836e-17 1.147388e-15 4.835421e-16 4.183824e-16 4.494935e-17 6.977571e-16 3.525086e-16 7.870788e-17 6.442521e-17 1.151777e-14 5.279518e-16 34 | 7.200000e+00 2.646473e-17 4.415475e-15 1.958410e-15 1.398645e-16 7.979235e-17 9.838373e-16 3.831530e-16 3.175622e-16 3.477763e-17 5.935182e-16 3.780068e-16 8.629635e-17 5.968196e-17 6.277477e-15 3.987296e-16 35 | 7.300000e+00 3.731060e-17 4.890784e-15 2.130895e-15 1.347563e-16 7.323810e-17 8.762774e-16 3.172436e-16 2.475526e-16 2.657658e-17 4.653735e-16 3.591968e-16 9.408735e-17 6.289412e-17 3.536296e-15 2.297049e-16 36 | 7.400000e+00 5.264196e-17 5.422834e-15 2.332542e-15 1.328842e-16 6.923541e-17 8.078013e-16 2.735152e-16 2.003721e-16 2.094143e-17 3.623441e-16 3.055894e-16 9.515313e-17 6.832958e-17 2.420201e-15 1.357736e-16 37 | 7.500000e+00 7.431721e-17 6.017826e-15 2.561199e-15 1.339344e-16 6.705183e-17 7.679992e-16 2.459774e-16 1.683160e-16 1.718684e-17 2.907066e-16 2.472106e-16 8.703890e-17 7.105685e-17 1.984878e-15 9.651773e-17 38 | 7.600000e+00 1.049641e-16 6.693581e-15 2.819173e-15 1.374713e-16 6.653305e-17 7.475962e-16 2.267938e-16 1.465284e-16 1.468167e-17 2.423416e-16 2.009526e-16 7.416069e-17 6.792702e-17 1.844014e-15 8.040041e-17 39 | 7.700000e+00 1.482980e-16 7.455090e-15 3.108271e-15 1.433393e-16 6.745830e-17 7.447419e-16 2.155880e-16 1.318760e-16 1.303294e-17 2.100105e-16 1.679052e-16 6.204564e-17 6.021882e-17 1.834884e-15 7.517490e-17 40 | 7.800000e+00 2.095716e-16 8.313383e-15 3.433260e-15 1.512835e-16 6.965014e-17 7.569305e-16 2.105581e-16 1.223877e-16 1.197714e-17 1.888523e-16 1.451721e-16 5.259303e-17 5.165696e-17 1.861706e-15 7.537059e-17 41 | 7.900000e+00 2.962102e-16 9.282109e-15 3.811912e-15 1.612570e-16 7.304170e-17 7.822831e-16 2.102852e-16 1.167220e-16 1.134875e-17 1.756066e-16 1.301015e-16 4.577824e-17 4.437528e-17 1.853952e-15 7.663321e-17 42 | 8.000000e+00 4.187062e-16 1.037481e-14 4.236088e-15 1.733334e-16 7.753892e-17 8.202541e-16 2.140990e-16 1.141345e-16 1.103797e-17 1.680480e-16 1.205019e-16 4.116331e-17 3.890649e-17 1.792991e-15 7.704950e-17 43 | 8.100000e+00 5.918429e-16 1.161115e-14 4.710514e-15 1.875669e-16 8.312575e-17 8.707057e-16 2.214540e-16 1.141677e-16 1.098475e-17 1.648568e-16 1.149101e-16 3.819793e-17 3.514933e-17 1.689415e-15 7.588704e-17 44 | 8.200000e+00 8.361838e-16 1.300953e-14 5.253591e-15 2.040176e-16 8.978478e-17 9.329583e-16 2.323617e-16 1.164595e-16 1.115130e-17 1.652940e-16 1.123370e-16 3.646832e-17 3.273169e-17 1.568531e-15 7.316249e-17 45 | 8.300000e+00 1.179319e-15 1.459495e-14 5.869250e-15 2.236086e-16 9.748313e-17 1.006598e-15 2.464652e-16 1.207517e-16 1.149961e-17 1.687366e-16 1.122255e-16 3.566307e-17 3.132029e-17 1.459439e-15 6.955278e-17 46 | 8.400000e+00 1.655842e-15 1.636658e-14 6.557277e-15 2.465393e-16 1.062433e-16 1.090129e-15 2.643128e-16 1.268314e-16 1.200979e-17 1.746004e-16 1.140433e-16 3.558770e-17 3.064120e-17 1.373649e-15 6.618114e-17 47 | 8.500000e+00 2.305236e-15 1.831714e-14 7.313903e-15 2.712166e-16 1.169691e-16 1.180628e-15 2.841981e-16 1.345705e-16 1.263949e-17 1.823862e-16 1.172452e-16 3.603332e-17 3.049975e-17 1.312002e-15 6.339508e-17 48 | 8.600000e+00 3.168178e-15 2.040350e-14 8.122274e-15 2.964207e-16 1.280499e-16 1.294235e-15 3.048509e-16 1.434286e-16 1.340849e-17 1.914685e-16 1.213714e-16 3.680856e-17 3.070877e-17 1.269352e-15 6.114450e-17 49 | 8.700000e+00 4.282981e-15 2.257137e-14 8.954221e-15 3.208997e-16 1.387785e-16 1.406805e-15 3.249387e-16 1.521445e-16 1.420103e-17 2.023485e-16 1.259041e-16 3.777861e-17 3.112444e-17 1.240897e-15 5.918169e-17 50 | 8.800000e+00 5.683943e-15 2.515604e-14 9.784500e-15 3.465285e-16 1.485948e-16 1.510242e-15 3.518179e-16 1.599940e-16 1.491856e-17 2.123193e-16 1.317295e-16 3.881849e-17 3.163756e-17 1.222281e-15 5.758230e-17 51 | 8.900000e+00 7.402199e-15 2.754837e-14 1.058806e-14 3.729451e-16 1.574386e-16 1.598147e-15 3.755969e-16 1.691000e-16 1.551020e-17 2.205925e-16 1.367746e-16 4.033215e-17 3.219996e-17 1.209987e-15 5.623359e-17 52 | 9.000000e+00 1.063311e-14 2.962537e-14 1.135211e-14 3.947383e-16 1.684811e-16 1.667012e-15 3.951145e-16 1.799965e-16 1.644053e-17 2.277097e-16 1.406516e-16 4.164305e-17 3.331075e-17 1.203620e-15 5.511429e-17 53 | # Total Emissivity in keV cm^3 s^-1 for each element with AG89 abundances, between 1.000000e-03 and 1.000000e+02 keV 54 | # To get cooling power, multiply by Ne NH# Z=0 component is electron-electron bremsstrahlung component, only significant at high T -------------------------------------------------------------------------------- /pyatomdb/examples/photoionization_data.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy,os, pylab 2 | try: 3 | import astropy.io.fits as pyfits 4 | except: 5 | import pyfits 6 | 7 | # This is a sample routine that reads in the photoionization data 8 | # It also demonstrates using get_data, which should download the data you 9 | # need automagically from the AtomDB site. 10 | # 11 | # It also shows how to get the raw XSTAR PI cross sections. 12 | 13 | # going to get PI cross section from iron 16+ to 17+ (Fe XVII-XVIII) 14 | Z = 26 15 | z1 = 17 16 | 17 | # get the AtomDB level data 18 | lvdata = pyatomdb.atomdb.get_data(Z, z1, 'LV') 19 | 20 | # get the XSTAR PI data from AtomDB 21 | pidata = pyatomdb.atomdb.get_data(Z, z1, 'PI') 22 | 23 | # set up the figure 24 | fig = pylab.figure() 25 | fig.show() 26 | ax = fig.add_subplot(111) 27 | 28 | 29 | # to calculate the cross section (in cm^2) at a given single energy E (in keV) 30 | # does not currently work with vector input, so have to call in a loop if you 31 | # want multiple energies [I will fix this] 32 | 33 | E = 10. 34 | 35 | # get the ground level (the 0th entry in LV file) data 36 | lvd = lvdata[1].data[0] 37 | 38 | # This is the syntax for calculating the PI cross section of a given line 39 | # This will work for non XSTAR data too. 40 | sigma = pyatomdb.atomdb.sigma_photoion(E, Z, z1,lvd['phot_type'], lvd['phot_par'], \ 41 | xstardata=pidata, xstarfinallev=1) 42 | 43 | 44 | # To get the raw XSTAR cross sections (units: energy = keV, cross sections = Mb) 45 | # for level 1 -> 1 (ground to ground) 46 | pixsec = pyatomdb.atomdb.__sort_pi_data(pidata, 1,1) 47 | ax.loglog(pixsec['energy'], pixsec['pi_param']*1e-18, label='raw xstar data') 48 | 49 | # label the plot 50 | ax.set_title('Plotting raw XSTAR PI cross sections. Fe XVII gnd to Fe XVIII gnd') 51 | ax.set_xlabel("Energy (keV)") 52 | ax.set_ylabel("PI cross section (cm$^{2}$)") 53 | 54 | pylab.draw() 55 | zzz=input('press enter to continue') 56 | -------------------------------------------------------------------------------- /pyatomdb/examples/rsapec.py: -------------------------------------------------------------------------------- 1 | # temporarily add the wrappers folder to the path 2 | import sys 3 | sys.path.append('../wrappers') 4 | 5 | 6 | # import relevant models 7 | # inital import creates rsapec, rsvapec, rsvvapec, analagous to apec, vapec, vvapec but resonance scattered 8 | 9 | 10 | from xspec import * 11 | import rsapec_xspec 12 | import pylab 13 | import matplotlib.pyplot as plt 14 | 15 | 16 | #import the response and spectrum file of Hitomi observation of Perseus core 17 | s = Spectrum('../examples/ah100040030sxs_p0px1010_cl2_HP.pi') 18 | s.response = '../examples/ah100040030_sxs_cl2_HP_small.rmf' 19 | s.response.arf = '../examples/ah100040030sxs_p0px1010_ptsrc.arf' 20 | 21 | #set the energy range for the fitting 22 | s.ignore('**-6.0,7.0-**') 23 | 24 | 25 | # declare a new model and initiate the model parameters 26 | m1 = Model('tbabs*pyapecrs') 27 | m1.TBabs.nH=0.138 28 | m1.TBabs.nH.frozen=True 29 | m1.pyapecrs.kT=4.07740 30 | m1.pyapecrs.nL=1.22260E+22 31 | m1.pyapecrs.Velocity= 172.116 32 | m1.pyapecrs.Abundanc=0.389900 33 | m1.pyapecrs.Redshift=1.72391E-02 34 | m1.pyapecrs.Redshift.frozen=True 35 | m1.pyapecrs.norm=0.960000 36 | Fit.statMethod = "cstat" 37 | 38 | # let's overplot the model and the spectrum 39 | 40 | Plot.device='/null' 41 | Plot.xAxis = "keV" 42 | Plot.setRebin(5,10) 43 | Plot('data') 44 | chans = Plot.x() 45 | rates = Plot.y() 46 | xErrs = Plot.xErr() 47 | yErrs = Plot.yErr() 48 | folded= Plot.model(1) 49 | plt.xlim(6.5,6.6) 50 | plt.plot(chans,folded, color='orange', linewidth=2, label='rsapec model') 51 | plt.errorbar(chans, rates, xerr=xErrs,yerr=yErrs, label='Hitomi observation', fmt=",", color='blue') 52 | plt.xlabel('Energy(keV)') 53 | plt.ylabel('counts/s/keV') 54 | plt.legend(loc='upper left') 55 | pylab.draw() 56 | 57 | # save image files 58 | plt.savefig('Rsapec_hitomi.pdf') 59 | plt.savefig('Rsapec_hitomi.svg') 60 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_NEIsession_examples.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | 4 | # declare the Non-Equilibrium Ionization session 5 | sess = pyatomdb.spectrum.NEISession() 6 | 7 | # set the response (here, a dummy response) 8 | ebins = numpy.linspace(0.6,12.4,1000) 9 | sess.set_response(ebins, raw=True) 10 | 11 | # alternatively, could set to real RMF, ARF files using: 12 | # sess.set_response(rmf, arf=arf) 13 | # where rmf and arf are the file names 14 | 15 | # Turn on (or off) thermal broadening, and if desired velocity broadening 16 | # in this case turn on thermal broadening, and set velocity broadening to 500 km/s 17 | 18 | sess.set_broadening(True, velocity_broadening=500.0) 19 | 20 | # return spectrum at given temperature 21 | kT = 0.8 # temperature in keV 22 | tau = 1e11 # n_e*t cm^-3 s 23 | kT_init=0.01 # initial temperature (for initial ion distribution) 24 | 25 | spec = sess.return_spectrum(kT, tau, init_pop=kT_init) 26 | 27 | # note returned spectrum has units of photons cm^5 s^-1 bin^-1, and has 1 less 28 | # value than the energy bin grid. Prepend a 0 to it for plotting purposes 29 | fig = pylab.figure() 30 | fig.show() 31 | ax = fig.add_subplot(111) 32 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='dummy response') 33 | 34 | #label the figure 35 | ax.set_xlabel('Energy (keV)') 36 | ax.set_ylabel('Intensity (ph cm$^3$ s$^{-1}$ bin$^{-1}$)') 37 | 38 | # now do the same thing but with an instrument response 39 | sess.set_response('../tests/testdata/aciss_heg1_cy19.grmf', \ 40 | arf='../tests/testdata/aciss_heg1_cy19.garf') 41 | 42 | # return the spectrum 43 | spec = sess.return_spectrum(kT, tau, init_pop=kT_init) 44 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='HEG Ioniz') 45 | 46 | # same again, but for a recombining spectrum - set initial temperature > kT 47 | kT_init=10.0 48 | spec = sess.return_spectrum(kT, tau, init_pop=kT_init) 49 | 50 | # plot the results 51 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='HEG Recomb') 52 | ax.legend(loc=0) 53 | pylab.draw() 54 | 55 | zzz=input("Press enter to exit") 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_NEIsession_linelist_examples.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | 4 | # declare the Non-Equilibrium Ionization session 5 | sess = pyatomdb.spectrum.NEISession() 6 | 7 | kT = 0.8 # temperature in keV 8 | tau = 1e11 # n_e*t cm^-3 s 9 | kT_init=0.01 # initial temperature (for initial ion distribution) 10 | 11 | waverange = [21,27] 12 | 13 | # find the lines in a certain wavelength range 14 | llist = sess.return_linelist(kT,tau, waverange) 15 | 16 | # filter out to get only lines within 10% of the strongest 17 | llist = llist[ llist['Epsilon'] > max(llist['Epsilon'])*0.1] 18 | 19 | # print the results: 20 | 21 | # column names 22 | print(llist.dtype.names) 23 | 24 | # data 25 | print(llist) 26 | 27 | 28 | # now let's see how one of the lines varies as a function of temperature. Let's look 29 | # at the O VII resonance line (7 -> 1) 30 | 31 | # list of temperatures to look at 32 | kTlist = numpy.linspace(0.05,3.0,20) 33 | 34 | # get the emissivity as a function of temperature (returned in a dict) 35 | ldata = sess.return_line_emissivity(kTlist, tau, 8, 7, 7, 1) 36 | 37 | # print out the data 38 | for i in range(len(kTlist)): 39 | print("%.3f keV %e ph cm^3 s^-1"%(ldata['Te'][i], ldata['epsilon'][i])) 40 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # create a set of energy bins (in keV) for the response. Note these are 10 | # the n edges of the n-1 bins. 11 | ebins = numpy.linspace(0.6,12.4,1000) 12 | 13 | # set the response (raw keyword tells pyatomdb it is not a real response file) 14 | sess.set_response(ebins, raw=True) 15 | 16 | kT = 0.4 # temperature in keV 17 | spec = sess.return_spectrum(kT) 18 | 19 | 20 | # alternatively, could set to real RMF, ARF files using: 21 | # sess.set_response(rmf, arf=arf) 22 | # where rmf and arf are the file names 23 | 24 | # Turn on (or off) thermal broadening, and if desired velocity broadening 25 | # in this case turn on thermal broadening, and set velocity broadening to 500 km/s 26 | 27 | sess.set_broadening(True, velocity_broadening=500.0) 28 | 29 | # return spectrum at given temperature 30 | kT = 0.8 # temperature in keV 31 | spec = sess.return_spectrum(kT) 32 | 33 | # note returned spectrum has units of photons cm^5 s^-1 bin^-1, and has 1 less 34 | # value than the energy bin grid. Prepend a 0 to it for plotting purposes 35 | fig = pylab.figure() 36 | fig.show() 37 | ax = fig.add_subplot(111) 38 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='dummy response') 39 | 40 | #label the figure 41 | ax.set_xlabel('Energy (keV)') 42 | ax.set_ylabel('Intensity (ph cm$^3$ s$^{-1}$ bin$^{-1}$)') 43 | 44 | # now do the same thing but with an instrument response 45 | sess.set_response('../tests/testdata/aciss_heg1_cy19.grmf', \ 46 | arf='../tests/testdata/aciss_heg1_cy19.garf') 47 | 48 | # return the spectrum 49 | spec = sess.return_spectrum(kT) 50 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='HEG') 51 | 52 | # change abundance set 53 | sess.set_abundset('Feldman') 54 | spec = sess.return_spectrum(kT) 55 | ax.plot(sess.ebins_out, numpy.append(0, spec), drawstyle='steps', label='HEG+Feldman') 56 | ax.legend(loc=0) 57 | pylab.draw() 58 | 59 | zzz=input("Press enter to exit") 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_1.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # create a set of energy bins (in keV) for the response. Note these are 10 | # the n edges of the n-1 bins. 11 | ebins = numpy.linspace(0.3,1.0,10000) 12 | 13 | # set the response (raw keyword tells pyatomdb it is not a real response file) 14 | sess.set_response(ebins, raw=True) 15 | 16 | kT = 0.4 # temperature in keV 17 | spec = sess.return_spectrum(kT) 18 | 19 | # we now have a spectrum and the energy bins, 20 | 21 | # prepend a zero to the spectrum so that energy bins and spectrum have 22 | # the same length. If you use a different plotting system you may 23 | # need to add this to the end. 24 | spec = numpy.append(0, spec) 25 | 26 | # Returned spectrum has units of photons cm^5 s^-1 bin^-1 27 | fig = pylab.figure() 28 | fig.show() 29 | ax = fig.add_subplot(211) 30 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='dummy response') 31 | 32 | # label the figure 33 | ax.set_xlabel('Energy (keV)') 34 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 35 | 36 | # zoom in a bit 37 | #ax.set_xlim([0.8,0.85]) 38 | 39 | # make plot appear 40 | 41 | # now repeat the process with a real response 42 | # set response 43 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 44 | 45 | # get spectrum, prepend zero 46 | spec = sess.return_spectrum(kT) 47 | spec = numpy.append(0, spec) 48 | 49 | ax2 = fig.add_subplot(212) 50 | ax2.plot(sess.ebins_out, spec, drawstyle='steps', label='Chandra MEG') 51 | 52 | # add legends 53 | ax.legend(loc=0) 54 | ax2.legend(loc=0) 55 | 56 | # zoom in on small sections of the spectrum 57 | ax.set_xlim([0.7, 0.9]) 58 | ax2.set_xlim([0.7, 0.9]) 59 | 60 | # set axes 61 | ax2.set_xlabel('Energy (keV)') 62 | ax2.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 63 | 64 | # adjust plot spacing so labels are visible 65 | pylab.matplotlib.pyplot.subplots_adjust(hspace = 0.34) 66 | 67 | # draw graphs 68 | pylab.draw() 69 | 70 | zzz=input("Press enter to continue") 71 | 72 | # save image files 73 | fig.savefig('spectrum_session_examples_1_1.pdf') 74 | fig.savefig('spectrum_session_examples_1_1.svg') 75 | 76 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_1_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_1_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_1b.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | 10 | kT = 0.4 # temperature in keV 11 | 12 | # Returned spectrum has units of photons cm^5 s^-1 bin^-1 13 | 14 | # create figure 15 | gs = pylab.matplotlib.gridspec.GridSpec(2, 1, height_ratios=[2, 1]) 16 | fig = pylab.figure() 17 | fig.show() 18 | ax1 = fig.add_subplot(gs[0]) # for data 19 | ax2 = fig.add_subplot(gs[1], sharex=ax1) # for ratio 20 | 21 | # label the figure 22 | ax2.set_xlabel('Energy (keV)') 23 | ax1.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 24 | ax2.set_ylabel('Ratio') 25 | 26 | # set response - using a regular matrix 27 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 28 | 29 | # get spectrum, prepend zero 30 | spec = sess.return_spectrum(kT) 31 | spec = numpy.append(spec[0], spec) 32 | 33 | ax1.plot(sess.ebins_out, spec, drawstyle='steps', label='Regular') 34 | 35 | # change the response to a sparse one 36 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf', 37 | sparse=True) 38 | spec_sparse = sess.return_spectrum(kT) 39 | spec_sparse = numpy.append(spec_sparse[0], spec_sparse) 40 | 41 | ax1.plot(sess.ebins_out, spec_sparse, '--', drawstyle='steps', label='Sparse') 42 | 43 | # plot the ratio 44 | ax2.plot(sess.ebins_out, spec/spec_sparse, drawstyle='steps',\ 45 | label='Regular/Sparse') 46 | 47 | # add legend 48 | ax1.legend(loc=0) 49 | ax2.legend(loc=0) 50 | 51 | # zoom in on small sections of the spectrum 52 | ax1.set_xlim([0.5, 2.0]) 53 | 54 | # adjust plot spacing so labels are visible 55 | pylab.matplotlib.pyplot.subplots_adjust(hspace = 0) 56 | 57 | # draw graphs 58 | pylab.draw() 59 | 60 | zzz=input("Press enter to continue") 61 | 62 | # save image files 63 | fig.savefig('spectrum_session_examples_1b_1.pdf') 64 | fig.savefig('spectrum_session_examples_1b_1.svg') 65 | 66 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_1b_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_1b_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_2.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # create a set of energy bins (in keV) for the response. Note these are 10 | # the n edges of the n-1 bins. 11 | ebins = numpy.linspace(1.0,1.2,501) 12 | 13 | # set the response (raw keyword tells pyatomdb it is not a real response file) 14 | sess.set_response(ebins, raw=True) 15 | 16 | kT = 4.0 # temperature in keV 17 | vel = 400.0 # velocity to broaden with when using velocity broadening (km/s) 18 | 19 | spec = sess.return_spectrum(kT) 20 | 21 | # we now have a spectrum and the energy bins, 22 | 23 | # prepend a zero to the spectrum so that energy bins and spectrum have 24 | # the same length. If you use a different plotting system you may 25 | # need to add this to the end. 26 | spec = numpy.append(0, spec) 27 | 28 | # Returned spectrum has units of photons cm^5 s^-1 bin^-1 29 | fig = pylab.figure() 30 | fig.show() 31 | ax = fig.add_subplot(211) 32 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='dummy response') 33 | 34 | # label the figure 35 | ax.set_xlabel('Energy (keV)') 36 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 37 | 38 | 39 | 40 | sess.set_broadening(True) 41 | spec = sess.return_spectrum(kT) 42 | spec = numpy.append(0, spec) 43 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='thermal') 44 | 45 | sess.set_broadening(True, velocity_broadening=vel) 46 | spec = sess.return_spectrum(kT) 47 | spec = numpy.append(0, spec) 48 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='%.0f km/s'%(vel)) 49 | 50 | # make plot appear 51 | 52 | # now repeat the process with a real response 53 | 54 | # reset broadening to off. 55 | sess.set_broadening(False) 56 | 57 | # set response 58 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 59 | 60 | # get spectrum, prepend zero 61 | spec = sess.return_spectrum(kT) 62 | spec = numpy.append(0, spec) 63 | 64 | ax2 = fig.add_subplot(212) 65 | ax2.plot(sess.ebins_out, spec, drawstyle='steps', label='Chandra MEG') 66 | 67 | # add legends 68 | ax.legend(loc=0) 69 | ax2.legend(loc=0) 70 | 71 | # zoom in on small sections of the spectrum 72 | ax.set_xlim([1.150, 1.180]) 73 | ax2.set_xlim([1.150, 1.180]) 74 | 75 | # set axes 76 | ax2.set_xlabel('Energy (keV)') 77 | ax2.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 78 | 79 | sess.set_broadening(True) 80 | spec = sess.return_spectrum(kT) 81 | spec = numpy.append(0, spec) 82 | ax2.plot(sess.ebins_out, spec, drawstyle='steps', label='thermal') 83 | 84 | sess.set_broadening(True, velocity_broadening=vel) 85 | spec = sess.return_spectrum(kT) 86 | spec = numpy.append(0, spec) 87 | ax2.plot(sess.ebins_out, spec, drawstyle='steps', label='%.0f km/s'%(vel)) 88 | 89 | 90 | # adjust plot spacing so labels are visible 91 | pylab.matplotlib.pyplot.subplots_adjust(hspace = 0.34) 92 | 93 | # draw graphs 94 | pylab.draw() 95 | 96 | zzz=input("Press enter to continue") 97 | 98 | # save image files 99 | fig.savefig('spectrum_session_examples_2_1.pdf') 100 | fig.savefig('spectrum_session_examples_2_1.svg') 101 | 102 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_2_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_2_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_2b.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | # line broadening of weak features 6 | 7 | # declare an CIESession 8 | 9 | sess = pyatomdb.spectrum.CIESession() 10 | 11 | # create a set of energy bins (in keV) for the response. Note these are 12 | # the n edges of the n-1 bins. 13 | ebins = numpy.linspace(6.9,7.0,501) 14 | 15 | # set the response (raw keyword tells pyatomdb it is not a real response file) 16 | sess.set_response(ebins, raw=True) 17 | 18 | kT = 10.0 # temperature in keV 19 | vel = 400.0 # velocity to broaden with when using velocity broadening (km/s) 20 | 21 | spec = sess.return_spectrum(kT) 22 | 23 | # we now have a spectrum and the energy bins, 24 | 25 | # prepend a zero to the spectrum so that energy bins and spectrum have 26 | # the same length. If you use a different plotting system you may 27 | # need to add this to the end. 28 | spec = numpy.append(0, spec) 29 | 30 | # Returned spectrum has units of photons cm^5 s^-1 bin^-1 31 | fig = pylab.figure() 32 | fig.show() 33 | ax = fig.add_subplot(111) 34 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='dummy response') 35 | 36 | # label the figure 37 | ax.set_xlabel('Energy (keV)') 38 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 39 | ax.set_yscale('log') 40 | 41 | 42 | sess.set_broadening(True, velocity_broadening=vel) 43 | spec = sess.return_spectrum(kT) 44 | spec = numpy.append(0, spec) 45 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='%.0f km/s'%(vel)) 46 | 47 | # Some features from weak lines aren't broadened. Let's fix that 48 | # by setting the minimum emissivity limit to a lower value 49 | # (default is 1e-18 ph cm^3 s^-1) 50 | 51 | sess.set_broadening(True, velocity_broadening=vel, broaden_limit=1e-30) 52 | spec = sess.return_spectrum(kT) 53 | spec = numpy.append(0, spec) 54 | ax.plot(sess.ebins_out, spec, drawstyle='steps', label='Low Limit, %.0f km/s'%(vel)) 55 | 56 | # make plot appear 57 | 58 | # now repeat the process with a real response 59 | # add legends 60 | ax.legend(loc=0) 61 | 62 | # zoom in on small sections of the spectrum 63 | #ax.set_xlim([1.150, 1.180]) 64 | 65 | # draw graphs 66 | pylab.draw() 67 | 68 | zzz=input("Press enter to continue") 69 | 70 | # save image files 71 | fig.savefig('spectrum_session_examples_2b_1.pdf') 72 | fig.savefig('spectrum_session_examples_2b_1.svg') 73 | 74 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_2b_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_2b_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_3_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_3_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_3_abund.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # set response 10 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 11 | 12 | # for plotting 13 | fig = pylab.figure() 14 | fig.show() 15 | ax = fig.add_subplot(111) 16 | 17 | # make a spectrum at 1keV 18 | s1 = sess.return_spectrum(1.0) 19 | 20 | # change the abundance of Iron 21 | sess.set_abund(26,2.0) 22 | s2 = sess.return_spectrum(1.0) 23 | # change the abundance of Magnesium and Silicon 24 | sess.set_abund([12,14],0.5) 25 | s3 = sess.return_spectrum(1.0) 26 | # change the abundance of Neon and Iron separately 27 | sess.set_abund([10,26],[2.0,0.5]) 28 | s4 = sess.return_spectrum(1.0) 29 | # plot all this 30 | offset = max(s1) 31 | ax.plot(sess.ebins_out, numpy.append(0,s1), drawstyle='steps', label='Original') 32 | ax.plot(sess.ebins_out, numpy.append(0,s2)+offset, drawstyle='steps', label='Fex2') 33 | ax.plot(sess.ebins_out, numpy.append(0,s3)+offset*2, drawstyle='steps', label='Mg, Six0.5') 34 | ax.plot(sess.ebins_out, numpy.append(0,s4)+offset*3, drawstyle='steps', label='Nex2, Fex0.5') 35 | ax.legend(ncol=4, loc=0) 36 | ax.set_xlim([0.8,1.5]) 37 | ax.set_xlabel('Energy (keV)') 38 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 39 | pylab.draw() 40 | zzz=input("Press enter to continue") 41 | # save image files 42 | fig.savefig('spectrum_session_examples_3_1.pdf') 43 | fig.savefig('spectrum_session_examples_3_1.svg') 44 | 45 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_4_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_4_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_4_abund.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # set response 10 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 11 | 12 | # for plotting 13 | fig = pylab.figure() 14 | fig.show() 15 | ax = fig.add_subplot(111) 16 | 17 | # get a list of the available abundance sets 18 | sess.set_abundset() 19 | # this prints them to screen. 20 | 21 | 22 | 23 | for iabset, abset in enumerate(['Allen', 'AG89', 'GA88', 'Feldman', 'GA10', 'Lodd09']): 24 | 25 | # set abundset 26 | sess.set_abundset(abset) 27 | 28 | # get spectrum at 1keV 29 | s1 = sess.return_spectrum(1.0) 30 | if iabset == 0: 31 | baseoffset = max(s1) 32 | 33 | offset = iabset*baseoffset 34 | 35 | 36 | #plot 37 | ax.plot(sess.ebins_out, numpy.append(0,s1)+offset, drawstyle='steps', label=abset) 38 | 39 | ax.set_xlim([0.8,2.1]) 40 | 41 | ax.set_xlabel('Energy (keV)') 42 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 43 | ax.legend(loc=0, ncol=4) 44 | pylab.draw() 45 | zzz=input("Press enter to continue") 46 | # save image files 47 | fig.savefig('spectrum_session_examples_4_1.pdf') 48 | fig.savefig('spectrum_session_examples_4_1.svg') 49 | 50 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_5_linelist.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # set response 10 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 11 | 12 | # get a linelist between 1.85 and 1.88 Angstroms for a kT=4keV plasma 13 | 14 | llist = sess.return_linelist(4.0,[1.85,1.88]) 15 | 16 | # select only the strongest 10 lines 17 | llist.sort(order='Epsilon') 18 | llist = llist[-10:] 19 | 20 | # show the column names 21 | print(llist.dtype.names) 22 | 23 | # expected output: 24 | # ('Lambda', 'Lambda_Err', 'Epsilon', 'Epsilon_Err', 'Element', 'Ion', 'UpperLev', 'LowerLev') 25 | 26 | # print the data 27 | print(llist) 28 | 29 | # expected output: 30 | #[(1.8635 , nan, 8.8202775e-19, nan, 26, 24, 47, 1) 31 | # (1.8532 , nan, 1.0113579e-18, nan, 26, 24, 10089, 6) 32 | # (1.8622 , nan, 1.0681659e-18, nan, 26, 24, 10242, 3) 33 | # (1.863 , nan, 2.5785468e-18, nan, 26, 24, 10247, 2) 34 | # (1.8611 , nan, 2.8751725e-18, nan, 26, 24, 48, 1) 35 | # (1.8659 , nan, 3.8414809e-18, nan, 26, 24, 10248, 3) 36 | # (1.8554125, nan, 7.2097873e-18, nan, 26, 25, 6, 1) 37 | # (1.8595169, nan, 7.7184372e-18, nan, 26, 25, 5, 1) 38 | # (1.8681941, nan, 1.2001933e-17, nan, 26, 25, 2, 1) 39 | # (1.8503995, nan, 3.5732330e-17, nan, 26, 25, 7, 1)] 40 | 41 | # we can then do the same thing, but including the effective area of the instrument. 42 | # So the Epsilon columnw will be multiplied by the effective area at the line's energy 43 | llist = sess.return_linelist(4.0,[1.85,1.88], apply_aeff=True) 44 | 45 | llist.sort(order='Epsilon') 46 | llist = llist[-10:] 47 | 48 | print('After apply effective area:') 49 | print(llist) 50 | #[(1.8635 , nan, 1.6238816e-18, nan, 26, 24, 47, 1) 51 | # (1.8532 , nan, 1.7191134e-18, nan, 26, 24, 10089, 6) 52 | # (1.8622 , nan, 1.9665764e-18, nan, 26, 24, 10242, 3) 53 | # (1.863 , nan, 4.7473049e-18, nan, 26, 24, 10247, 2) 54 | # (1.8611 , nan, 5.2934158e-18, nan, 26, 24, 48, 1) 55 | # (1.8659 , nan, 7.3193854e-18, nan, 26, 24, 10248, 3) 56 | # (1.8554125, nan, 1.2779108e-17, nan, 26, 25, 6, 1) 57 | # (1.8595169, nan, 1.3680673e-17, nan, 26, 25, 5, 1) 58 | # (1.8681941, nan, 2.2867946e-17, nan, 26, 25, 2, 1) 59 | # (1.8503995, nan, 6.0738072e-17, nan, 26, 25, 7, 1)] 60 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_6_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_6_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_6_line_emissivity.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Collisional Ionization Equilibrium session 7 | sess = pyatomdb.spectrum.CIESession() 8 | 9 | # set response 10 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 11 | 12 | # get the emissivity of the resonance line of O VII at 5 different temperatures 13 | 14 | kTlist = numpy.array([0.1,0.3,0.5,0.7,0.9]) 15 | Z=8 16 | z1=7 17 | up=7 18 | lo = 1 19 | ldata = sess.return_line_emissivity(kTlist, Z, z1, up, lo) 20 | 21 | fig = pylab.figure() 22 | fig.show() 23 | ax= fig.add_subplot(111) 24 | 25 | ax.semilogy(ldata['Te'], ldata['epsilon']) 26 | 27 | ax.set_xlabel("Temperature (keV)") 28 | ax.set_ylabel("Epsilon ph cm$^3$ s$^{-1}$") 29 | 30 | pylab.draw() 31 | zzz=input("Press enter to continue") 32 | # save image files 33 | fig.savefig('spectrum_session_examples_6_1.pdf') 34 | fig.savefig('spectrum_session_examples_6_1.svg') 35 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_7_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/examples/spectrum_session_examples_7_1.pdf -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_7_nei.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Non-Equilibrium Ionization session. I am only using 7 | # oxygen and neon for simplicity 8 | sess = pyatomdb.spectrum.NEISession(elements=[8,10]) 9 | 10 | # set the response (raw keyword tells pyatomdb it is not a real response file) 11 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 12 | 13 | kT = 0.4 # temperature in keV 14 | tau = 1e10 # n_e * t in cm^-3 s 15 | spec = sess.return_spectrum(kT, tau, init_pop=1.0) 16 | 17 | # Returned spectrum has units of photons cm^5 s^-1 bin^-1 18 | fig = pylab.figure() 19 | fig.show() 20 | ax = fig.add_subplot(111) 21 | 22 | offset = max(spec) 23 | ax.plot(sess.ebins_out, numpy.append(0,spec), drawstyle='steps', label='mild recombining') 24 | 25 | 26 | spec = sess.return_spectrum(kT, tau, init_pop='ionizing') 27 | ax.plot(sess.ebins_out, offset+numpy.append(0,spec), drawstyle='steps', label='ionizing') 28 | 29 | spec = sess.return_spectrum(kT, tau, init_pop='recombining') 30 | ax.plot(sess.ebins_out, 2*offset+numpy.append(0,spec), drawstyle='steps', label='recombining') 31 | 32 | 33 | 34 | # manually specified initial population 35 | init_pop_dict = {} 36 | init_pop_dict[8] = numpy.zeros(9) # 9 stages of oxygen (include neutral an fully stripped) 37 | init_pop_dict[10] = numpy.zeros(11) 38 | #put everything in the H-like stage 39 | init_pop_dict[8][8] = 1.0 40 | init_pop_dict[10][10] = 1.0 41 | 42 | 43 | spec = sess.return_spectrum(kT, tau, init_pop=init_pop_dict) 44 | ax.plot(sess.ebins_out, 3*offset+numpy.append(0,spec), drawstyle='steps', label='all H-like') 45 | 46 | 47 | # label the figure 48 | ax.set_xlabel('Energy (keV)') 49 | ax.set_ylabel('Intensity (ph cm$^5$ s$^{-1}$ bin$^{-1}$)') 50 | 51 | # zoom in a bit 52 | ax.set_xlim([0.6,1.2]) 53 | ax.legend(loc=0) 54 | # make plot appear 55 | pylab.draw() 56 | 57 | zzz=input("Press enter to continue") 58 | 59 | # save image files 60 | fig.savefig('spectrum_session_examples_7_1.pdf') 61 | fig.savefig('spectrum_session_examples_7_1.svg') 62 | 63 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_examples_8_nei_linelist.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | import numpy 3 | import pylab 4 | 5 | 6 | # declare the Non-Equilibrium Ionization session. I am only using 7 | # oxygen and neon for simplicity 8 | sess = pyatomdb.spectrum.NEISession() 9 | 10 | # set the response (raw keyword tells pyatomdb it is not a real response file) 11 | sess.set_response('aciss_meg1_cy22.grmf', arf = 'aciss_meg1_cy22.garf') 12 | 13 | kT = 4.0 # temperature in keV 14 | tau = 1e11 # n_e * t in cm^-3 s 15 | llist = sess.return_linelist(kT, tau, [1.7,1.9],init_pop=1.0) 16 | 17 | # filter lines to strongest 20 18 | llist.sort(order='Epsilon') 19 | llist= llist[-20:] 20 | 21 | print("strongest 20 lines") 22 | print(llist.dtype.names) 23 | print(llist) 24 | 25 | llist = sess.return_linelist(kT, tau, [1.7,1.9],by_ion_drv=True,init_pop=1.0) 26 | 27 | # filter lines to strongest 20 28 | llist.sort(order='Epsilon') 29 | llist= llist[-20:] 30 | 31 | print("Strongest 20 lines, separated by driving ion") 32 | print(llist.dtype.names) 33 | print(llist) 34 | 35 | 36 | # Expected output 37 | # strongest 20 lines 38 | # ('Lambda', 'Lambda_Err', 'Epsilon', 'Epsilon_Err', 'Element', 'Ion', 'UpperLev', 'LowerLev') 39 | # [(1.8827 , nan, 4.3892664e-19, nan, 26, 22, 20009, 1) 40 | # (1.8622 , nan, 4.5014698e-19, nan, 26, 24, 10242, 3) 41 | # (1.8824 , nan, 4.8421002e-19, nan, 26, 22, 483, 1) 42 | # (1.8825 , nan, 5.8088691e-19, nan, 26, 22, 482, 1) 43 | # (1.8851 , nan, 5.9669826e-19, nan, 26, 22, 20008, 2) 44 | # (1.8747 , nan, 6.6686722e-19, nan, 26, 24, 44, 1) 45 | # (1.8737 , nan, 6.9597891e-19, nan, 26, 23, 20126, 3) 46 | # (1.863 , nan, 1.0866564e-18, nan, 26, 24, 10247, 2) 47 | # (1.8756001, nan, 1.0874650e-18, nan, 26, 23, 20122, 4) 48 | # (1.8706 , nan, 1.3853237e-18, nan, 26, 24, 46, 1) 49 | # (1.8738 , nan, 1.4878691e-18, nan, 26, 24, 45, 1) 50 | # (1.8659 , nan, 1.6188786e-18, nan, 26, 24, 10248, 3) 51 | # (1.857 , nan, 1.9076071e-18, nan, 26, 24, 50, 1) 52 | # (1.8554125, nan, 2.3919818e-18, nan, 26, 25, 6, 1) 53 | # (1.8595169, nan, 2.8080335e-18, nan, 26, 25, 5, 1) 54 | # (1.8635 , nan, 3.6176967e-18, nan, 26, 24, 47, 1) 55 | # (1.8704 , nan, 7.2666667e-18, nan, 26, 23, 309, 1) 56 | # (1.8681941, nan, 8.8379641e-18, nan, 26, 25, 2, 1) 57 | # (1.8611 , nan, 1.1892281e-17, nan, 26, 24, 48, 1) 58 | # (1.8503995, nan, 1.4463351e-17, nan, 26, 25, 7, 1)] 59 | # Strongest 20 lines, separated by driving ion 60 | # ('Lambda', 'Lambda_Err', 'Epsilon', 'Epsilon_Err', 'Element', 'Elem_drv', 'Ion', 'Ion_drv', 'UpperLev', 'LowerLev') 61 | # [(1.8622 , nan, 4.5014698e-19, nan, 26, 26, 24, 25, 10242, 3) 62 | # (1.8824 , nan, 4.8421002e-19, nan, 26, 26, 22, 22, 483, 1) 63 | # (1.8825 , nan, 5.6233666e-19, nan, 26, 26, 22, 22, 482, 1) 64 | # (1.8851 , nan, 5.9669826e-19, nan, 26, 26, 22, 23, 20008, 2) 65 | # (1.8747 , nan, 6.5364458e-19, nan, 26, 26, 24, 24, 44, 1) 66 | # (1.8737 , nan, 6.9597891e-19, nan, 26, 26, 23, 24, 20126, 3) 67 | # (1.863 , nan, 1.0866564e-18, nan, 26, 26, 24, 25, 10247, 2) 68 | # (1.8756001, nan, 1.0874650e-18, nan, 26, 26, 23, 24, 20122, 4) 69 | # (1.8706 , nan, 1.3512313e-18, nan, 26, 26, 24, 24, 46, 1) 70 | # (1.8738 , nan, 1.4619381e-18, nan, 26, 26, 24, 24, 45, 1) 71 | # (1.8659 , nan, 1.6188786e-18, nan, 26, 26, 24, 25, 10248, 3) 72 | # (1.857 , nan, 1.8978882e-18, nan, 26, 26, 24, 24, 50, 1) 73 | # (1.8554125, nan, 2.3303760e-18, nan, 26, 26, 25, 25, 6, 1) 74 | # (1.8595169, nan, 2.7651213e-18, nan, 26, 26, 25, 25, 5, 1) 75 | # (1.8681941, nan, 3.3107048e-18, nan, 26, 26, 25, 25, 2, 1) 76 | # (1.8635 , nan, 3.6059715e-18, nan, 26, 26, 24, 24, 47, 1) 77 | # (1.8681941, nan, 5.3853784e-18, nan, 26, 26, 25, 24, 2, 1) 78 | # (1.8704 , nan, 7.2068723e-18, nan, 26, 26, 23, 23, 309, 1) 79 | # (1.8611 , nan, 1.1865456e-17, nan, 26, 26, 24, 24, 48, 1) 80 | # (1.8503995, nan, 1.4405425e-17, nan, 26, 26, 25, 25, 7, 1)] 81 | # 82 | -------------------------------------------------------------------------------- /pyatomdb/examples/spectrum_session_linelist_examples.py: -------------------------------------------------------------------------------- 1 | import pyatomdb, numpy, pylab 2 | 3 | 4 | # declare the Collisional Ionization Equilibrium session 5 | sess = pyatomdb.spectrum.CIESession() 6 | 7 | kT = 0.8 # temperature in keV 8 | 9 | waverange = [21,27] 10 | 11 | # find the lines in a certain wavelength range 12 | llist = sess.return_linelist(kT, waverange) 13 | 14 | # filter out to get only lines within 10% of the strongest 15 | llist = llist[ llist['Epsilon'] > max(llist['Epsilon'])*0.1] 16 | 17 | # print the results: 18 | 19 | # column names 20 | print(llist.dtype.names) 21 | 22 | # data 23 | print(llist) 24 | 25 | 26 | # now let's see how one of the lines varies as a function of temperature. Let's look 27 | # at the O VII resonance line (7 -> 1) 28 | 29 | # list of temperatures to look at 30 | kTlist = numpy.linspace(0.05,3.0,20) 31 | 32 | # get the emissivity as a function of temperature (returned in a dict) 33 | ldata = sess.return_line_emissivity(kTlist, 8, 7, 7, 1) 34 | 35 | # print out the data 36 | for i in range(len(kTlist)): 37 | print("%.3f keV %e ph cm^3 s^-1"%(ldata['Te'][i], ldata['epsilon'][i])) 38 | -------------------------------------------------------------------------------- /pyatomdb/examples/wrapper_xspec_examples.py: -------------------------------------------------------------------------------- 1 | # temporarily add the wrappers folder to the path 2 | import sys 3 | sys.path.append('../wrappers') 4 | 5 | 6 | from apec_xspec import * 7 | 8 | # declare a new model 9 | # inital import creates pyapec, pyvapec, pyvvapec, analagous to apec, vapec, vvapec 10 | 11 | m1 = xspec.Model('pyapec') 12 | 13 | m1.show() 14 | 15 | m1.pyapec.kT=5.0 16 | 17 | 18 | # let's plot a spectrum 19 | xspec.Plot.device='/xs' 20 | 21 | xspec.Plot('model') 22 | 23 | # you can fiddle with some aspects of the model directly 24 | cie.set_eebrems(False) # turn off electron-electron bremsstrahlung 25 | 26 | xspec.Plot('model') 27 | 28 | # it is also possible to go in and change broadening, etc. The interface can be 29 | # adjust quite easily by looking at apec_xspec.py to add extra parameters 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /pyatomdb/linear_approx.c: -------------------------------------------------------------------------------- 1 | /* Original: stl2.f -- translated by f2c (version 19970219). */ 2 | #include 3 | #include 4 | #include 5 | 6 | void linear_approx(double *x, double *y, double *e, int *m, double *u, 7 | double *v, double *w, int *k, int *ip) { 8 | 9 | /* System generated locals */ 10 | int i__1; 11 | double r__1, r__2; 12 | 13 | /* Local variables */ 14 | int indc, keep, itch, init; 15 | double smin; 16 | int ipiv; 17 | double smax, xeye, yeye, test, svmn=0, svmx=0, temp1, temp2; 18 | int i__, j, l, n, idiot; 19 | double epsln, slope=0, xinit, yinit; 20 | int kp=0; 21 | double dx; 22 | int it, igraze; 23 | double sgn, svx=0, svy=0; 24 | 25 | /* From D.G. Wilson, 1976, ACM Transactions on Mathematical Software,2,388 */ 26 | 27 | /* Piecewise linear approximations of fewest line segments within 28 | given tolerances. x, y, e and m contain input data. u,v,k and 29 | possibly w contain output. ip is a parameter determining the 30 | operation of the program. x and y are input data arrays of m 31 | elements x(i),y(i) contains the ith data point. e may be a 32 | single tolerance or a table of tolerances depending on the value 33 | of ip. If e is an array, then e(i) is the tolerance associated 34 | with x(i),y(i) and e must contain m nonnegative elements. u and 35 | v are output arrays of k+1 elements. u is a partition of the 36 | interval (x(1),x(n)) with u(1)=x(1) and u(k+1)=x(n). v(i) is an 37 | ordinate to be associated with u(i) in the approximation. (If a 38 | continuous approximation is requested, then v(i) is 'the' 39 | ordinate to be associated with u(i).) If a continuous 40 | approximation is requested, then w is not used. In this case the 41 | ith approximating segment is the straight line from u(i),v(i) to 42 | u(i+1),v(i+1). If a continuous approximation is not requested, 43 | then w is a k-element output array. In this case the ith 44 | approximating segment is the straight line from u(i),w(i) to 45 | u(i+1),v(i+1), and v(1) is set equal to w(1). k is the number of 46 | segments in the piece- wise linear approximation generated. In 47 | case of an error return, k will be set to zero. 48 | 49 | The control parameter ip is the product of three indicators i1,i2 50 | and i3. i1 indicates whether or not e is an array of tolerances. 51 | i1 = -1 indicates e is an array i1 = +1 indicates e is a single 52 | number. 53 | 54 | i2 indicates whether or not the approximation is to be restricted to 55 | the 'tolerance band' about the data. 56 | i2 = 1 indicates no band restriction 57 | i2 = 2 indicates apply this restriction 58 | (the 'tolerance band' is a piecewise linear band centered at the 59 | data whose width is determined by the tolerances at the data 60 | points.) 61 | 62 | i3 indicates whether or not the approximation must be continuous. 63 | i3 = 1 indicates continuity not required 64 | i3 = 3 indicates continuity is required 65 | 66 | call stl2 (x,y,e,m,x,y,e,m,ip) will not cause problems provided 67 | that either a continuous approximation is equested, or e is a 68 | sufficiently large array. 69 | 70 | The program performs the following data checks. Are the x-values 71 | in increasing order? Are the tolerance(s) nonnegative? Is the 72 | number of data points greater than one? If any check fails, the 73 | program returns with k set equal to 0. In this case no further 74 | processing is attempted. */ 75 | 76 | /* Parameter adjustments */ 77 | --w; 78 | --v; 79 | --u; 80 | --e; 81 | --y; 82 | --x; 83 | 84 | /* Function Body */ 85 | n = *m; 86 | itch = *ip; 87 | j = 1; 88 | /* ERROR CHECKS */ 89 | if (n <= 1) { 90 | printf("linear_approx: n (%d) is <= 1\n",n); 91 | goto L400; 92 | } 93 | if (e[1] < (double)0.) { 94 | printf("linear_approx: tolerance[0] (%e) is < 0\n",e[1]); 95 | goto L400; 96 | } 97 | i__1 = n; 98 | for (l = 2; l <= i__1; ++l) { 99 | if (x[l - 1] >= x[l]) { 100 | printf("linear_approx: x[%d] (%e) > x[%d] (%e)\n",l-2,x[l-1], 101 | l-1,x[l]); 102 | goto L400; 103 | } 104 | if (itch >= 0) { 105 | goto L10; 106 | } 107 | if (e[l] < (double)0.) { 108 | printf("linear_approx: tolerance[%d] (%e) is < 0 for (%e)\n", 109 | l-1,e[l],y[l]); 110 | goto L400; 111 | } 112 | L10: 113 | ; 114 | } 115 | /* INITIALIZATION FOR ENTIRE PROGRAM */ 116 | epsln = e[1]; 117 | sgn = (double)1.; 118 | keep = 1; 119 | i__ = 1; 120 | u[1] = x[1]; 121 | j = 2; 122 | init = 1; 123 | indc = 0; 124 | goto L30; 125 | /* INITIALIZATION FOR EACH SEGMENT */ 126 | L20: 127 | ++j; 128 | init = i__; 129 | indc = 0; 130 | if (abs(itch) < 3) { 131 | keep = i__; 132 | } 133 | if ((i__1 = abs(itch) - 4, abs(i__1)) != 2) { 134 | goto L30; 135 | } 136 | /* RESTRICTED TO TOLERANCE BAND */ 137 | xeye = u[j - 1]; 138 | yeye = v[j - 1]; 139 | temp1 = epsln; 140 | if (itch < 0) { 141 | temp1 += (sgn * e[i__ - 1] - epsln) * (x[i__] - u[j - 1]) / (x[i__] - 142 | x[i__ - 1]); 143 | } 144 | yinit = yeye - temp1 - temp1; 145 | goto L40; 146 | L30: 147 | /* NOT RESTRICTED TO TOLERANCE BAND */ 148 | xeye = x[i__]; 149 | yeye = y[i__] + epsln; 150 | yinit = y[i__] - epsln; 151 | if (abs(itch) == 1 || i__ == 1) { 152 | goto L40; 153 | } 154 | temp1 = epsln; 155 | if (itch < 0) { 156 | temp1 = sgn * e[i__ + 1]; 157 | } 158 | smin = (y[i__ + 1] - yeye - temp1) / (x[i__ + 1] - xeye); 159 | if (itch < 0) { 160 | temp1 = sgn * e[i__ - 1]; 161 | } 162 | smax = (yeye - y[i__ - 1] + temp1) / (xeye - x[i__ - 1]); 163 | if (keep == i__ - 1) { 164 | goto L50; 165 | } 166 | it = i__ - 2; 167 | xinit = xeye; 168 | ipiv = i__; 169 | igraze = i__; 170 | ++i__; 171 | goto L150; 172 | L40: 173 | if (xeye >= x[i__]) { 174 | ++i__; 175 | } 176 | if (itch < 0) { 177 | epsln = sgn * e[i__]; 178 | } 179 | dx = x[i__] - xeye; 180 | smax = (y[i__] + epsln - yeye) / dx; 181 | smin = (y[i__] - epsln - yeye) / dx; 182 | L50: 183 | xinit = xeye; 184 | ipiv = i__; 185 | igraze = i__; 186 | /* DETERMINATION OF INDIVIDUAL SEGMENT */ 187 | L60: 188 | if (i__ == n) { 189 | goto L260; 190 | } 191 | ++i__; 192 | L70: 193 | /* TEST FOR NEW *MAX* SLOPE */ 194 | dx = x[i__] - xeye; 195 | if (itch < 0) { 196 | epsln = sgn * e[i__]; 197 | } 198 | temp1 = (y[i__] + epsln - yeye) / dx; 199 | test = temp1 - smax; 200 | if (sgn <= (double)0.) { 201 | test = -test; 202 | } 203 | if (test < (double)0.) { 204 | goto L80; 205 | } else if (test == 0) { 206 | goto L90; 207 | } else { 208 | goto L100; 209 | } 210 | L80: 211 | /* TEST FOR END OF CANDIDATE SEGMENT */ 212 | test = temp1 - smin; 213 | if (sgn <= (double)0.) { 214 | test = -test; 215 | } 216 | if (test < (double)0.) { 217 | goto L210; 218 | } 219 | smax = temp1; 220 | L90: 221 | /* TEST FOR NEW *MIN* SLOPE */ 222 | ipiv = i__; 223 | L100: 224 | temp2 = (y[i__] - epsln - yeye) / dx; 225 | test = temp2 - smax; 226 | if (sgn <= (double)0.) { 227 | test = -test; 228 | } 229 | if (test < (double)0.) { 230 | goto L110; 231 | } else if (test == 0) { 232 | goto L120; 233 | } else { 234 | goto L140; 235 | } 236 | L110: 237 | test = smin - temp2; 238 | if (sgn <= (double)0.) { 239 | test = -test; 240 | } 241 | if (test < (double)0.) { 242 | goto L120; 243 | } else if (test == 0) { 244 | goto L130; 245 | } else { 246 | goto L60; 247 | } 248 | L120: 249 | smin = temp2; 250 | L130: 251 | igraze = i__; 252 | goto L60; 253 | /* CHECK FOR PIVOT AT NEW EYE POINT */ 254 | L140: 255 | if (xeye == x[ipiv]) { 256 | goto L220; 257 | } 258 | if (itch < 0) { 259 | epsln = sgn * e[ipiv]; 260 | } 261 | indc = 1; 262 | svx = xeye; 263 | svy = yeye; 264 | svmn = smin; 265 | svmx = smax; 266 | xeye = x[ipiv]; 267 | yeye = y[ipiv] + epsln; 268 | smin = smax; 269 | smax = (yinit - yeye) / (xinit - xeye); 270 | if (keep >= ipiv) { 271 | goto L170; 272 | } 273 | it = ipiv - 1; 274 | L150: 275 | temp2 = yeye + epsln; 276 | i__1 = it; 277 | for (l = keep; l <= i__1; ++l) { 278 | if (itch < 0) { 279 | temp2 = yeye + sgn * e[l]; 280 | } 281 | temp1 = (y[l] - temp2) / (x[l] - xeye); 282 | test = temp1 - smax; 283 | if (sgn <= (double)0.) { 284 | test = -test; 285 | } 286 | if (test < (double)0.) { 287 | smax = temp1; 288 | } 289 | /* L160: */ 290 | } 291 | L170: 292 | if (ipiv >= i__ - 1) { 293 | goto L70; 294 | } 295 | it = i__ - 2; 296 | temp2 = yeye - epsln; 297 | idiot = ipiv; 298 | i__1 = it; 299 | for (l = idiot; l <= i__1; ++l) { 300 | dx = x[l + 1] - xeye; 301 | if (itch < 0) { 302 | temp2 = yeye - sgn * e[l + 1]; 303 | } 304 | temp1 = (y[l + 1] - temp2) / dx; 305 | test = temp1 - smax; 306 | if (sgn <= (double)0.) { 307 | test = -test; 308 | } 309 | if (test < (double)0.) { 310 | goto L180; 311 | } else if (test == 0) { 312 | goto L190; 313 | } else { 314 | goto L200; 315 | } 316 | L180: 317 | smax = temp1; 318 | L190: 319 | ipiv = l + 1; 320 | L200: 321 | ; 322 | } 323 | goto L70; 324 | /* END OF CURRENT SEGMENT */ 325 | L210: 326 | temp2 = smin; 327 | if (i__ == n) { 328 | goto L240; 329 | } 330 | keep = igraze; 331 | goto L250; 332 | L220: 333 | temp2 = smax; 334 | if (i__ == n) { 335 | goto L230; 336 | } 337 | sgn = -sgn; 338 | epsln = -epsln; 339 | keep = ipiv; 340 | goto L250; 341 | L230: 342 | if (indc == 0 || xeye != x[n - 1]) { 343 | goto L240; 344 | } 345 | xeye = svx; 346 | yeye = svy; 347 | smin = svmn; 348 | smax = svmx; 349 | L240: 350 | u[j] = x[n - 1]; 351 | yinit = y[n - 1]; 352 | goto L270; 353 | L250: 354 | if ((i__1 = abs(itch) - 4, abs(i__1)) != 2) { 355 | goto L300; 356 | } 357 | /* DETERMINE KNOT ON EDGE OF TOLERANCE BAND */ 358 | temp1 = (double)0.; 359 | if (itch < 0) { 360 | temp1 = epsln - sgn * e[i__ - 1]; 361 | } 362 | temp1 = (y[i__] - y[i__ - 1] + temp1) / (x[i__] - x[i__ - 1]); 363 | u[j] = (y[i__] + epsln - yeye - temp1 * x[i__] + temp2 * xeye) / (temp2 - 364 | temp1); 365 | goto L310; 366 | L260: 367 | u[j] = x[n]; 368 | yinit = y[n]; 369 | L270: 370 | /* CONTINUITY CHECK FOR LAST SEGMENT */ 371 | if (abs(itch) >= 3 || init == 1) { 372 | goto L290; 373 | } 374 | it = init - 1; 375 | svmx = smax + sgn; 376 | temp2 = yeye + epsln; 377 | i__1 = it; 378 | for (l = kp; l <= i__1; ++l) { 379 | if (itch < 0) { 380 | temp2 = yeye + sgn * e[l]; 381 | } 382 | temp1 = (y[l] - temp2) / (x[l] - xeye); 383 | test = temp1 - svmx; 384 | if (sgn <= (double)0.) { 385 | test = -test; 386 | } 387 | if (test < (double)0.) { 388 | svmx = temp1; 389 | } 390 | /* L280: */ 391 | } 392 | if ((r__1 = svmx - smax + svmx - smin, fabs(r__1)) <= (r__2 = smax - smin, 393 | fabs(r__2))) { 394 | smax = svmx; 395 | } 396 | L290: 397 | /* NEARNESS CHECK FOR LAST SEGMENT */ 398 | temp2 = smax; 399 | temp1 = yeye + smax * (u[j] - xeye); 400 | test = yinit - temp1; 401 | if (sgn < (double)0.) { 402 | test = -test; 403 | } 404 | if (test > (double)0.) { 405 | goto L310; 406 | } 407 | temp2 = smin; 408 | temp1 = yeye + smin * (u[j] - xeye); 409 | test = yinit - temp1; 410 | if (sgn < (double)0.) { 411 | test = -test; 412 | } 413 | if (test < (double)0.) { 414 | goto L310; 415 | } 416 | temp2 = (yinit - yeye) / (u[j] - xeye); 417 | v[j] = yinit; 418 | goto L320; 419 | L300: 420 | if (abs(itch) >= 3) { 421 | goto L330; 422 | } 423 | u[j] = (x[i__] + x[i__ - 1]) * (double).5; 424 | L310: 425 | v[j] = yeye + temp2 * (u[j] - xeye); 426 | L320: 427 | if (xeye != xinit) { 428 | goto L330; 429 | } 430 | if (abs(itch) == 2) { 431 | goto L360; 432 | } 433 | if (abs(itch) != 6) { 434 | goto L330; 435 | } 436 | if (j <= 2) { 437 | goto L380; 438 | } 439 | goto L390; 440 | L330: 441 | /* RECOMPUTATION OF KNOT FOR CONTINUITY */ 442 | if (j <= 2) { 443 | goto L370; 444 | } 445 | if (slope == temp2) { 446 | goto L360; 447 | } 448 | yinit = v[j - 2]; 449 | if (abs(itch) < 3) { 450 | yinit = w[j - 2]; 451 | } 452 | temp1 = (xeye * temp2 - u[j - 2] * slope + yinit - yeye) / (temp2 - slope) 453 | ; 454 | if (abs(itch) >= 3) { 455 | goto L350; 456 | } 457 | if (temp1 > xinit) { 458 | goto L360; 459 | } 460 | test = fabs(epsln); 461 | idiot = init - kp; 462 | i__1 = idiot; 463 | for (l = 1; l <= i__1; ++l) { 464 | it = init - l; 465 | if (temp1 >= x[it]) { 466 | goto L350; 467 | } 468 | dx = y[it] - yeye - temp2 * (x[it] - xeye); 469 | if (itch < 0) { 470 | test = e[it]; 471 | } 472 | if (fabs(dx) > test) { 473 | goto L360; 474 | } 475 | /* L340: */ 476 | } 477 | L350: 478 | u[j - 1] = temp1; 479 | v[j - 1] = yeye + temp2 * (u[j - 1] - xeye); 480 | if (abs(itch) < 3) { 481 | w[j - 1] = v[j - 1]; 482 | } 483 | goto L390; 484 | L360: 485 | w[j - 1] = yeye + temp2 * (u[j - 1] - xeye); 486 | goto L390; 487 | L370: 488 | if (abs(itch) < 3) { 489 | goto L360; 490 | } 491 | L380: 492 | v[1] = yeye + temp2 * (u[1] - xeye); 493 | L390: 494 | slope = temp2; 495 | kp = keep; 496 | if (i__ < n) { 497 | goto L20; 498 | } 499 | if (x[n] == u[j]) { 500 | goto L400; 501 | } 502 | if (abs(itch) < 3) { 503 | w[j] = v[j]; 504 | } 505 | ++j; 506 | u[j] = x[n]; 507 | v[j] = y[n]; 508 | L400: 509 | if (j >= 2 && abs(itch) < 3) { 510 | v[1] = w[1]; 511 | } 512 | *k = j - 1; 513 | } 514 | 515 | -------------------------------------------------------------------------------- /pyatomdb/make_test_outputs.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | 3 | pyatomdbversion=pyatomdb.__version__ 4 | 5 | PYADBVERS = pyatomdbversion.replace('.','') 6 | 7 | ADBVERS = '309' 8 | 9 | s = pyatomdb.spectrum.CIESession() 10 | 11 | ebins=pyatomdb.numpy.linspace(0.1,10,1000) 12 | s.set_response(ebins*1.0, raw=True) 13 | y = s.return_spectrum(1.0) 14 | 15 | pyatomdb.numpy.save("tests/testdata/test_set_response_spec1_%s.npy"%(ADBVERS),y) 16 | 17 | 18 | s = pyatomdb.spectrum.CIESession() 19 | t = {} 20 | s.set_response('tests/testdata/aciss_heg1_cy19.grmf',\ 21 | arf='tests/testdata/aciss_heg1_cy19.garf') 22 | 23 | t['spec'] = s.return_spectrum(1.0) 24 | 25 | s.set_broadening(True) 26 | t['tbroadspec'] = s.return_spectrum(1.0) 27 | 28 | s.set_response('tests/testdata/aciss_heg1_cy19.grmf',arf=False) 29 | t['tbroadspec_noarf'] = s.return_spectrum(1.0) 30 | 31 | pyatomdb.numpy.savez("tests/testdata/test_set_response_spec2_%s.npz"%(ADBVERS),\ 32 | spec=t['spec'],\ 33 | tbroadspec=t['tbroadspec'],\ 34 | tbroadspec_noarf=t['tbroadspec_noarf']) 35 | 36 | -------------------------------------------------------------------------------- /pyatomdb/pyatomdb/__init__.py: -------------------------------------------------------------------------------- 1 | __all__=["atomdb","util","atomic","spectrum","const","apec"] 2 | 3 | #from .atomdb import * 4 | import os 5 | from . import spectrum 6 | from . import atomic 7 | import ctypes 8 | from . import apec 9 | from . import util 10 | import sys, glob 11 | 12 | __version__="1.0.5" 13 | 14 | try: 15 | PATH = os.path.dirname(__file__) 16 | g = glob.glob("%s/../linear_approx*.dylib"%(PATH)) 17 | if len(g) ==1: 18 | liblinapprox_file = os.path.join(PATH,g[0]) 19 | else: 20 | g = glob.glob("%s/../linear_approx*.so"%(PATH)) 21 | liblinapprox_file = os.path.join(PATH,g[0]) 22 | 23 | liblinapprox = ctypes.CDLL( liblinapprox_file, ctypes.RTLD_GLOBAL) 24 | except (OSError, IndexError): 25 | on_rtd=os.environ.get('READTHEDOCS')=='True' 26 | if on_rtd: 27 | pass 28 | else: 29 | raise 30 | 31 | # check initialization 32 | on_rtd=os.environ.get('READTHEDOCS')=='True' 33 | if on_rtd: 34 | pass 35 | else: 36 | if os.environ.get('ATOMDB')==None: 37 | # issues here 38 | install = '' 39 | while not install in ['yes','no']: 40 | install = util.question("ATOMDB environment variable not set. Set up AtomDB files now?", "yes",multichoice=["yes","no","info"]) 41 | if install=='info': 42 | print("If yes, this will run the pyatomdb.util.initialize() script, which installs the necessary data files to run pyatomdb") 43 | if install=='yes': 44 | util.initialize() 45 | 46 | elif not os.path.exists(os.path.expandvars("$ATOMDB/userdata")): 47 | install = '' 48 | while not install in ['yes','no']: 49 | install = util.question("ATOMDB Environment Variable Not Set. Set up AtomDB files now?", "yes",multichoice=["yes","no","info"]) 50 | if install=='info': 51 | print("If yes, this will run the pyatomdb.util.initialize() script, which installs the necessary data files to run pyatomdb") 52 | 53 | if install=='yes': 54 | util.initialize() 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /pyatomdb/pyatomdb/const.py: -------------------------------------------------------------------------------- 1 | """ 2 | This contains a list of constants, both physical and apec code related. 3 | 4 | Version 0.1 - initial release 5 | Adam Foster July 17th 2015 6 | """ 7 | 8 | #PHYSICAL CONSTANTS 9 | KBOLTZ = 8.617385e-8# /*!< in units of keV/K *== 1/(11604.5*1000)/ 10 | M_E = 2.7182818284590452354 # /*!< Euler e */ 11 | UPSILON_COLL_COEFF = 8.629e-6 # /*!< sqrt{2 pi / kB} hbar^2/m_e^{1.5} */ 12 | ERG_KEV = 1.60219e-9 13 | ME_KEV = 510.99895 14 | RYDBERG = 0.013605693122 # in keV, updated to NIST value 6/11/2024. Previously 0.013605804 15 | BREMS_COEFF = 1.6542996e-20 16 | PLANCK_CONSTANT = 6.626176e-27 # erg-seconds 17 | CLASSICAL_ELECTRON_RADIUS = 2.8179403262e-13 # m 18 | PROTON_MASS = 1.67262192e-24 # gm 19 | ELECTRON_MASS =9.1e-28 #gm 20 | BOLTZMAN_CONSTANT = 1.380649e-16 #cgs 21 | 22 | HC_IN_KEV_A = 12.398425 # hc for converting keV to Ang 23 | 24 | HC_IN_ERG_A = 1.9862e-8 # /* = hc (erg A) = 12398.425 * 1.602e-12 */ 25 | SAF_COEFF = 3.30e-24 26 | 27 | LIGHTSPEED = 299792458. # m/s 28 | 29 | AMUKG = 1.66054E-27 30 | 31 | 32 | # APEC SPECIFIC CONSTANTS 33 | MAX_UPS = 20 34 | MAX_CHI = 200.0 35 | MAX_IONREC = 20 36 | 37 | E_UPSILON=1 # /*!< Electron upsilon values (unitless) */ 38 | E_RATE_COEFF=2 #/*!< Electron rate coefficient (cm^3/s) */ 39 | P_UPSILON=3 #/*!< Proton upsilon values (unitless) */ 40 | P_RATE_COEFF=4 #/*!< Proton rate coefficient (cm^3/s) */ 41 | EI_UPSILON=5 # /*!< Electron-impact ionization upsilon values (unitless) */ 42 | 43 | BURGESSTULLY=1 #/*!< Burgess-Tully-type data*/ 44 | CHIANTI_1=11 #/*!< CHIANTI pre-4.0 type 1 data (5 pt spline) */ 45 | CHIANTI_2=12 #/*!< CHIANTI pre-4.0 type 2 data (5 pt spline) */ 46 | CHIANTI_3=13 #/*!< CHIANTI pre-4.0 type 3 data (5 pt spline) */ 47 | CHIANTI_4=14 #/*!< CHIANTI pre-4.0 type 4 data (5 pt spline) */ 48 | CHIANTI_5=15 #/*!< CHIANTI pre-4.0 type 5 data (5 pt spline) */ 49 | CHIANTI_6=16 #/*!< CHIANTI pre-4.0 type 6 data (5 pt spline) */ 50 | 51 | CHIANTI4_1=21 #/*!< CHIANTI 4.0 type 1 data (9 pt spline) */ 52 | CHIANTI4_2=22 #/*!< CHIANTI 4.0 type 2 data (9 pt spline) */ 53 | CHIANTI4_3=23 #/*!< CHIANTI 4.0 type 3 data (9 pt spline) */ 54 | CHIANTI4_4=24 #/*!< CHIANTI 4.0 type 4 data (9 pt spline) */ 55 | CHIANTI4_5=25 #/*!< CHIANTI 4.0 type 5 data (9 pt spline) */ 56 | CHIANTI4_6=26 #/*!< CHIANTI 4.0 type 6 data (9 pt spline) */ 57 | 58 | SGC_1=31 #/*!< Sampson, Goett and Clark (1983) S-type He-like data */ 59 | SGC_2=32 #/*!< Sampson, Goett and Clark (1983) P-type He-like data */ 60 | SGC_3=33 #/*!< Sampson, Goett and Clark (1983) S-type H-like data */ 61 | KATO_NAKAZAKI_1=41 #/*!< Kato and Nakazaki (1989), ADNDT 42, 313 */ 62 | KATO_NAKAZAKI_2=42 #/*!< Kato and Nakazaki (1989), ADNDT 42, 313 */ 63 | 64 | #/* These must be spaced by at least MAX_UPS */ 65 | 66 | INTERP_E_UPSILON=100 #/*!< Include both left & right boundaries */ 67 | INTERP_P_UPSILON=200 #/*!< Include both left & right boundaries */ 68 | INTERP_E_RATE_COEFF=300 #/*!< Include both left & right boundaries */ 69 | INTERP_P_RATE_COEFF=400 #/*!< Include both left & right boundaries */ 70 | 71 | INTERP_E_UPS_OPEN=150 #/*!< Include neither boundary */ 72 | INTERP_P_UPS_OPEN=250 #/*!< Include neither boundary */ 73 | INTERP_E_RATE_OPEN=350 #/*!< Include neither boundary */ 74 | INTERP_P_RATE_OPEN=450 #/*!< Include neither boundary */ 75 | 76 | INTERP_E_UPS_INC_MIN=500 #/*!< Include only minimum; max is out */ 77 | INTERP_P_UPS_INC_MIN=600 #/*!< Include only minimum; max is out */ 78 | INTERP_E_RATE_INC_MIN=700 #/*!< Include only minimum; max is out */ 79 | INTERP_P_RATE_INC_MIN=800 #/*!< Include only minimum; max is out */ 80 | 81 | INTERP_E_UPS_INC_MAX=550 #/*!< Include only maximum; min is out */ 82 | INTERP_P_UPS_INC_MAX=650 #/*!< Include only maximum; min is out */ 83 | INTERP_E_RATE_INC_MAX=750 #/*!< Include only maximum; min is out */ 84 | INTERP_P_RATE_INC_MAX=850 #/*!< Include only maximum; min is out */ 85 | 86 | INTERP_I_UPSILON=900 #/*!< Include both left & right boundaries */ 87 | 88 | PROTON_BT=1001 #/*!< For Burgess-Tully Proton excitation rates */ 89 | 90 | 91 | CI_YOUNGER = 51 92 | CI_URDAMPILLETA = 52 93 | CI_HAHNMULLERSAVIN = 53 # Double ionization rate coeffts 94 | EA_ARNROTH_LITHIUM = 61 95 | EA_ARNROTH = 62 96 | EA_MAZZOTTA_IRON = 63 97 | EA_URDAMPILLETA = 64 98 | RR_SHULL = 71 99 | RR_VERNER = 72 100 | RR_ARNRAY = 73 101 | RR_BADNELL = 74 102 | DR_MAZZOTTA = 81 103 | DR_BADNELL = 82 104 | CI_DERE = 100 105 | 106 | INTERP_IONREC_RATE_COEFF = 300 107 | INTERP_IONREC_RATE_OPEN = 350 108 | INTERP_IONREC_RATE_INC_MIN = 700 109 | INTERP_IONREC_RATE_INC_MAX = 750 110 | 111 | 112 | NO_PHOT= -1 113 | HYDROGENIC= 0 114 | CLARK= 1 115 | VERNER= 2 116 | XSTAR= 3 117 | XSTAR_49_MIN =10000 118 | XSTAR_49_MAX =19999 119 | XSTAR_53_MIN =20000 120 | XSTAR_53_MAX =29999 121 | 122 | 123 | #Bremsstrahlung types: 124 | HUMMER = 1 125 | KELLOGG = 2 126 | RELATIVISTIC = 3 127 | BREMS_NONE = 4 128 | 129 | #MISCfile types in FILEMAP files 130 | ABUNDANCE = 10 131 | HUMMER_TYPE = 11 132 | GAUNT_FF_TYPE = 13 133 | 134 | 135 | RRC_COEFF = 1.31e8 136 | TOT_ABSACC = 1.e-21 137 | TOT_RELACC = 0.0001 138 | BIN_ABSACC = 1.e-21 139 | BIN_RELACC = 0.01 140 | 141 | TOLERANCE = 0.01 142 | 143 | MIN_RRC_EXPONENT=-150. 144 | MAX_RRC_EXPONENT=150. 145 | 146 | 147 | ROMANIK = 1 148 | SAFRANOVA = 2 149 | 150 | # ATOMDB ONLINE CONSTANTS 151 | FILEDOWNLOAD = 1 152 | 153 | # APEC SIZE LIMITS 154 | NLEV_NOSPARSE = 60000 155 | MIN_IONPOP = 1e-10 156 | MIN_LEVPOP = 1e-40 157 | 158 | # MISC 159 | MAXZ_CIE = 30 160 | MAXZ_NEI = 30 161 | 162 | MINEPSOFFSET=1e-40 163 | 164 | 165 | FTPPATH = 'https://hea-www.cfa.harvard.edu/AtomDB' 166 | -------------------------------------------------------------------------------- /pyatomdb/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools >= 64"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | dynamic = ["version"] 7 | name = 'pyatomdb' 8 | dependencies = ["numpydoc", "requests", "wget", "numpy>=1.9.0", "scipy>=1.9.0", "joblib", "mock", "astropy"] 9 | authors = [ 10 | {name = "Adam Foster", email = "afoster@cfa.harvard.edu"} 11 | ] 12 | maintainers = [ 13 | {name = "Adam Foster", email = "afoster@cfa.harvard.edu"} 14 | ] 15 | description="AtomDB python library." 16 | #url=['http://www.atomdb.org'] 17 | #packages=['pyatomdb','tests'] 18 | 19 | classifiers=["Development Status :: 4 - Beta", 20 | # "Environment :: Console", 21 | "Intended Audience :: Developers", 22 | "Intended Audience :: Education", 23 | "Intended Audience :: End Users/Desktop", 24 | "Intended Audience :: Science/Research", 25 | "Topic :: Scientific/Engineering :: Astronomy", 26 | "Topic :: Scientific/Engineering :: Physics", 27 | "Programming Language :: Python :: 3", 28 | "Operating System :: POSIX"] 29 | 30 | readme = "README.rst" 31 | license = {file = "COPYING.txt"} 32 | [project.urls] 33 | Homepage = "http://www.atomdb.org" 34 | Documentation = "https://atomdb.readthedocs.io/en/master/" 35 | Repository = "https://github.com/AtomDB/pyatomdb.git" 36 | Issues = "https://github.com/AtomDB/pyatomdb/issues" 37 | #Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md" 38 | 39 | [tool.setuptools.dynamic] 40 | version = {attr = "pyatomdb.__version__"} 41 | -------------------------------------------------------------------------------- /pyatomdb/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, Extension 2 | import os 3 | 4 | import sys 5 | 6 | 7 | on_rtd = os.environ.get('READTHEDOCS')=='True' 8 | 9 | 10 | def get_version(relpath): 11 | """read version info from file without importing it""" 12 | from os.path import dirname, join 13 | for line in open(join(dirname(__file__), relpath)): 14 | if '__version__' in line: 15 | if '"' in line: 16 | # __version__ = "0.10" 17 | return line.split('"')[1] 18 | elif "'" in line: 19 | return line.split("'")[1] 20 | 21 | 22 | readme = open('README.rst', 'r') 23 | README_TEXT = readme.read() 24 | readme.close() 25 | 26 | linapprox = Extension("linear_approx",['linear_approx.c'],\ 27 | define_macros = [('MAJOR_VERSION', '1'),\ 28 | ('MINOR_VERSION','0')]) 29 | 30 | 31 | 32 | 33 | if on_rtd: 34 | try: 35 | from unittest.mock import MagicMock 36 | except ImportError: 37 | from mock import Mock as MagicMock 38 | 39 | 40 | extmos= [] 41 | 42 | # class Mock(MagicMock): 43 | # @classmethod 44 | # def __getattr__(cls, name): 45 | # return Mock() 46 | 47 | MOCK_MODULES = ['liblinapprox'] 48 | sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES) 49 | 50 | else: 51 | extmos= [linapprox] 52 | #setup() 53 | setup(name='pyatomdb', 54 | # version=get_version('pyatomdb/__init__.py'), 55 | # description='AtomDB python library.', 56 | # url='http://www.atomdb.org', 57 | # author='Adam Foster', 58 | # author_email='afoster@cfa.harvard.edu', 59 | # license='Smithsonian', 60 | packages=['pyatomdb','tests'], 61 | # classifiers=['Development Status :: 4 - Beta',\ 62 | # 'Environment :: Console',\ 63 | # 'Intended Audience :: Developers',\ 64 | # 'Intended Audience :: Education',\ 65 | # 'Intended Audience :: End Users/Desktop',\ 66 | # 'Intended Audience :: Science/Research',\ 67 | # 'Topic :: Scientific/Engineering :: Astronomy',\ 68 | # 'Topic :: Scientific/Engineering :: Physics',\ 69 | # 'Programming Language :: Python :: 3',\ 70 | # 'Operating System :: POSIX'], 71 | # zip_safe=False, 72 | # long_description = README_TEXT,\ 73 | # install_requires=[ 74 | # "numpydoc",\ 75 | # "requests",\ 76 | # "wget",\ 77 | # "numpy>=1.9.0",\ 78 | # "scipy>=1.9.0",\ 79 | # "joblib",\ 80 | # "mock",\ 81 | # "astropy",\ 82 | # "pycurl"], 83 | ext_modules = extmos) 84 | # 85 | # 86 | -------------------------------------------------------------------------------- /pyatomdb/tests/__init__.py: -------------------------------------------------------------------------------- 1 | import pyatomdb 2 | -------------------------------------------------------------------------------- /pyatomdb/tests/test1.py: -------------------------------------------------------------------------------- 1 | import unittest, warnings 2 | import pyatomdb 3 | 4 | ATOMDBVERSION='309' 5 | 6 | 7 | 8 | class TestSpectrum(unittest.TestCase): 9 | 10 | 11 | def test_convert_temp(self): 12 | """ Test temperature conversion in test_convert_temp""" 13 | T={} 14 | T['keV'] = 2.0 15 | 16 | Unitsin=['K','keV','eV'] 17 | Unitsout=['K','keV','eV'] 18 | T['K'] = T['keV']/pyatomdb.const.KBOLTZ 19 | T['eV'] = T['keV']*1000 20 | for Uin in Unitsin: 21 | for Uout in Unitsout: 22 | c = T[Uout] 23 | i = T[Uin] 24 | pyatomdb.numpy.testing.assert_allclose(c, pyatomdb.spectrum.convert_temp(i,Uin,Uout)) 25 | 26 | 27 | self.assertRaises(pyatomdb.util.UnitsError, pyatomdb.spectrum.convert_temp, 1.0,'krf','kev') 28 | 29 | self.assertRaises(pyatomdb.util.UnitsError, pyatomdb.spectrum.convert_temp, 1.0,'kev','krh') 30 | 31 | 32 | 33 | class TestSpectrumCIESession(unittest.TestCase): 34 | 35 | def setUp(self): 36 | warnings.simplefilter("ignore", ResourceWarning) 37 | 38 | self.s = pyatomdb.spectrum.CIESession() 39 | 40 | def test_init(self): 41 | """ Testing initialization of the CIESession""" 42 | self.assertEqual(self.s.broaden_limit, 1e-18) 43 | 44 | 45 | def test_set_raw_response(self): 46 | """ Testing dummy (raw) responses""" 47 | 48 | self.assertRaises(pyatomdb.util.ReadyError, self.s.return_spectrum,1.0) 49 | 50 | ebins=pyatomdb.numpy.linspace(0.1,10,1000) 51 | self.s.set_response(ebins*1.0, raw=True) 52 | pyatomdb.numpy.testing.assert_allclose(self.s.specbins, ebins) 53 | 54 | # now test spectrum calculation 55 | 56 | # load the correct result 57 | testdat = pyatomdb.numpy.load("tests/testdata/test_set_response_spec1_%s.npy"%(ATOMDBVERSION)) 58 | 59 | t = self.s.return_spectrum(1.0) 60 | pyatomdb.numpy.testing.assert_allclose(t, testdat) 61 | 62 | 63 | def test_set_response(self): 64 | """ Testing real responses and spectral broadening""" 65 | # test with real response 66 | self.s.set_response('tests/testdata/aciss_heg1_cy19.grmf',\ 67 | arf='tests/testdata/aciss_heg1_cy19.garf') 68 | 69 | # load the correct result 70 | testdat = pyatomdb.numpy.load("tests/testdata/test_set_response_spec2_%s.npz"%(ATOMDBVERSION)) 71 | 72 | # calc spectrum 73 | t = self.s.return_spectrum(1.0) 74 | pyatomdb.numpy.testing.assert_allclose(t, testdat['spec']) 75 | 76 | 77 | # turn on thermal broadening 78 | self.s.set_broadening(True) 79 | t = self.s.return_spectrum(1.0) 80 | pyatomdb.numpy.testing.assert_allclose(t, testdat['tbroadspec']) 81 | 82 | def test_nearest_spectrum(self): 83 | """ Testing real responses with the nearest spectrum""" 84 | # test with real response 85 | self.s.set_response('tests/testdata/aciss_heg1_cy19.grmf',\ 86 | arf='tests/testdata/aciss_heg1_cy19.garf') 87 | 88 | # load the correct result 89 | testdat = pyatomdb.numpy.load("tests/testdata/test_set_response_spec2_%s.npz"%(ATOMDBVERSION)) 90 | 91 | # calc spectrum 92 | t = self.s.return_spectrum(1.0) 93 | pyatomdb.numpy.testing.assert_allclose(t, testdat['spec']) 94 | 95 | 96 | # turn on thermal broadening 97 | self.s.set_broadening(True) 98 | t = self.s.return_spectrum(1.0) 99 | pyatomdb.numpy.testing.assert_allclose(t, testdat['tbroadspec']) 100 | 101 | 102 | if __name__ == '__main__': 103 | print("WHEE") 104 | unittest.main() 105 | print("WHOO") 106 | -------------------------------------------------------------------------------- /pyatomdb/tests/testdata/aciss_heg1_cy19.garf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/tests/testdata/aciss_heg1_cy19.garf -------------------------------------------------------------------------------- /pyatomdb/tests/testdata/aciss_heg1_cy19.grmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/tests/testdata/aciss_heg1_cy19.grmf -------------------------------------------------------------------------------- /pyatomdb/tests/testdata/test_set_response_spec1.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/tests/testdata/test_set_response_spec1.npy -------------------------------------------------------------------------------- /pyatomdb/tests/testdata/test_set_response_spec1_309.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/tests/testdata/test_set_response_spec1_309.npy -------------------------------------------------------------------------------- /pyatomdb/tests/testdata/test_set_response_spec2_309.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtomDB/pyatomdb/314f3cbd809a7a1fd99cd0cb814f6f04db6990f5/pyatomdb/tests/testdata/test_set_response_spec2_309.npz -------------------------------------------------------------------------------- /pyatomdb/wrappers/IonE_apec_xspec.py: -------------------------------------------------------------------------------- 1 | import numpy, xspec 2 | import pyatomdb 3 | 4 | # This wrapper is for using a separate temperature for defining line broadening 5 | # in the spectrum, instead of just Te. kTlwidth is the temperature used for this 6 | # There are many things out there called ion temperature. Strictly, this 7 | # would be the correct use of that term. However I am loathe to use it because 8 | # it is misused so ofter elsewhere. Instead the parameter is named kTlwidth. 9 | 10 | # To use this, import this file within the python session you have XSPEC running 11 | # in. e.g. 12 | 13 | # 14 | # python 15 | # python> import xspec 16 | # python> import IonE_apec_xspec 17 | # python> m1 = xspec.Model('pyibapec') 18 | 19 | #initialize CX object 20 | cie = pyatomdb.spectrum.CIESession() 21 | cie.set_broadening(True) 22 | # These are the definitions XSPEC uses for the inputs 23 | 24 | pyibapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 25 | "Abundanc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 26 | "kTlwidth \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01",\ 27 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6", 28 | "*Redshift \"\" 0.0") 29 | 30 | pyibvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 31 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 32 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 33 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 34 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 35 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 36 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 37 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 38 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 39 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 40 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 41 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 42 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 43 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 44 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 45 | "kTlwidth \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01",\ 46 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6", 47 | "*Redshift \"\" 0.0") 48 | 49 | 50 | pyibvvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 51 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 52 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 53 | "Li \"\" 1.0 0.01 0.2 100. 1000. 0.01", 54 | "Be \"\" 1.0 0.01 0.2 100. 1000. 0.01", 55 | "B \"\" 1.0 0.01 0.2 100. 1000. 0.01", 56 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 57 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 58 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 59 | "F \"\" 1.0 0.01 0.2 100. 1000. 0.01", 60 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 61 | "Na \"\" 1.0 0.01 0.2 100. 1000. 0.01", 62 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 63 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 64 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 65 | "P \"\" 1.0 0.01 0.2 100. 1000. 0.01", 66 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 67 | "Cl \"\" 1.0 0.01 0.2 100. 1000. 0.01", 68 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 69 | "K \"\" 1.0 0.01 0.2 100. 1000. 0.01", 70 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 71 | "Sc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 72 | "Ti \"\" 1.0 0.01 0.2 100. 1000. 0.01", 73 | "V \"\" 1.0 0.01 0.2 100. 1000. 0.01", 74 | "Cr \"\" 1.0 0.01 0.2 100. 1000. 0.01", 75 | "Mn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 76 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 77 | "Co \"\" 1.0 0.01 0.2 100. 1000. 0.01", 78 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 79 | "Cu \"\" 1.0 0.01 0.2 100. 1000. 0.01", 80 | "Zn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 81 | "kTlwidth \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01",\ 82 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6", 83 | "*Redshift \"\" 0.0") 84 | 85 | 86 | 87 | def pyibapec(engs, params, flux): 88 | 89 | """ 90 | CIE model for data 91 | 92 | PARAMETERS 93 | ---------- 94 | engs : list[float] 95 | The energy bin edges (from xspec) 96 | params : list[float] 97 | The parameter list. See acx2Info for definition 98 | flux : list[float] 99 | The array to fill with return values 100 | 101 | RETURNS 102 | ------- 103 | None 104 | Fills out the flux array with photon cm3 s-1 bin-1, x10^14 105 | 106 | USAGE 107 | ----- 108 | # load the model into XSPEC 109 | xspec.AllModels.addPyMod(pyapec, pyapecInfo, 'add') 110 | # make a model 111 | m = xspec.Model('pyapec') 112 | """ 113 | 114 | # This is the call that will return everything. So set everything! 115 | ebins = numpy.array(engs) 116 | 117 | elements = [] 118 | for i in range(1,31): elements.append(i) 119 | 120 | if len(params)==6: 121 | # apec model 122 | abund=numpy.array(params[1]) 123 | elements=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 124 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 125 | eloffset = 2 126 | elif len(params)==19: 127 | # apec model 128 | elements=[1,2,6,7,8,10,12,13,14,16,18,20,26,28] 129 | abund=params[1:15] 130 | eloffset = 15 131 | elif len(params)==35: 132 | # apec model 133 | elements=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 134 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 135 | abund=params[1:31] 136 | eloffset = 31 137 | 138 | thermal_broaden_temperature=float(params[eloffset]) 139 | 140 | vel_broadening = float(params[eloffset+1]) 141 | # get redshift 142 | redshift = float(params[eloffset+2]) 143 | 144 | # set energy bins, accounting for redshift 145 | cie.set_response(ebins*(1.0+redshift), raw=True) 146 | 147 | 148 | # set abundance vector 149 | # abund = numpy.array(params[1]) 150 | cie.set_abund(elements, abund) 151 | cie.set_eebrems(False) 152 | cie.set_broadening(True, velocity_broadening=vel_broadening,\ 153 | thermal_broaden_temperature=thermal_broaden_temperature) 154 | # get the spectrum 155 | spec = cie.return_spectrum(params[0], log_interp=False) 156 | 157 | # return the flux. 158 | flux[:] = spec*1e14 159 | 160 | def pyibvapec(engs, params, flux): 161 | pyibapec(engs, params, flux) 162 | 163 | def pyibvvapec(engs, params, flux): 164 | pyibapec(engs, params, flux) 165 | 166 | 167 | 168 | # this is how to import the models into pyxspec. 169 | xspec.AllModels.addPyMod(pyibapec, pyibapecInfo, 'add') 170 | xspec.AllModels.addPyMod(pyibvapec, pyibvapecInfo, 'add') 171 | xspec.AllModels.addPyMod(pyibvvapec, pyibvvapecInfo, 'add') 172 | 173 | -------------------------------------------------------------------------------- /pyatomdb/wrappers/apec_xspec.py: -------------------------------------------------------------------------------- 1 | import numpy, xspec 2 | import pyatomdb 3 | 4 | #initialize CX object 5 | cie = pyatomdb.spectrum.CIESession() 6 | 7 | # These are the definitions XSPEC uses for the inputs 8 | 9 | pyapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 10 | "Abundanc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 11 | "*Redshift \"\" 0.0") 12 | 13 | pyvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 14 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 15 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 16 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 17 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 18 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 19 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 20 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 21 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 22 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 23 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 24 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 25 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 26 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 27 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 28 | "*Redshift \"\" 0.0") 29 | 30 | 31 | pyvvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 32 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 33 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 34 | "Li \"\" 1.0 0.01 0.2 100. 1000. 0.01", 35 | "Be \"\" 1.0 0.01 0.2 100. 1000. 0.01", 36 | "B \"\" 1.0 0.01 0.2 100. 1000. 0.01", 37 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 38 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 39 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 40 | "F \"\" 1.0 0.01 0.2 100. 1000. 0.01", 41 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 42 | "Na \"\" 1.0 0.01 0.2 100. 1000. 0.01", 43 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 44 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 45 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 46 | "P \"\" 1.0 0.01 0.2 100. 1000. 0.01", 47 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 48 | "Cl \"\" 1.0 0.01 0.2 100. 1000. 0.01", 49 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 50 | "K \"\" 1.0 0.01 0.2 100. 1000. 0.01", 51 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 52 | "Sc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 53 | "Ti \"\" 1.0 0.01 0.2 100. 1000. 0.01", 54 | "V \"\" 1.0 0.01 0.2 100. 1000. 0.01", 55 | "Cr \"\" 1.0 0.01 0.2 100. 1000. 0.01", 56 | "Mn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 57 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 58 | "Co \"\" 1.0 0.01 0.2 100. 1000. 0.01", 59 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 60 | "Cu \"\" 1.0 0.01 0.2 100. 1000. 0.01", 61 | "Zn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 62 | "*Redshift \"\" 0.0") 63 | 64 | 65 | 66 | def pyapec(engs, params, flux): 67 | 68 | """ 69 | ACX2 model for data 70 | 71 | PARAMETERS 72 | ---------- 73 | engs : list[float] 74 | The energy bin edges (from xspec) 75 | params : list[float] 76 | The parameter list. See acx2Info for definition 77 | flux : list[float] 78 | The array to fill with return values 79 | 80 | RETURNS 81 | ------- 82 | None 83 | Fills out the flux array with photon cm3 s-1 bin-1, x1e10 84 | 85 | USAGE 86 | ----- 87 | # load the model into XSPEC 88 | xspec.AllModels.addPyMod(pyapec, pyapecInfo, 'add') 89 | # make a model 90 | m = xspec.Model('pyapec') 91 | """ 92 | 93 | # This is the call that will return everything. So set everything! 94 | ebins = numpy.array(engs) 95 | 96 | elements = [] 97 | for i in range(1,31): elements.append(i) 98 | 99 | if len(params)==4: 100 | # apec model 101 | abund=numpy.array(params[1]) 102 | elements=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 103 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 104 | eloffset = 2 105 | elif len(params)==17: 106 | # apec model 107 | elements=[1,2,6,7,8,10,12,13,14,16,18,20,26,28] 108 | abund=params[1:15] 109 | eloffset = 15 110 | elif len(params)==33: 111 | # apec model 112 | elements=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 113 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 114 | abund=params[1:31] 115 | eloffset = 31 116 | 117 | # get redshift 118 | redshift = float(params[eloffset+0]) 119 | 120 | # set energy bins, accounting for redshift 121 | cie.set_response(ebins*(1.0+redshift), raw=True) 122 | 123 | 124 | # set abundance vector 125 | # abund = numpy.array(params[1]) 126 | cie.set_abund(elements, abund) 127 | cie.set_eebrems(False) 128 | # get the spectrum 129 | spec = cie.return_spectrum(params[0], log_interp=False) 130 | 131 | # return the flux. 132 | flux[:] = spec*1e14 133 | 134 | def pyvapec(engs, params, flux): 135 | pyapec(engs, params, flux) 136 | 137 | def pyvvapec(engs, params, flux): 138 | pyapec(engs, params, flux) 139 | 140 | 141 | 142 | # this is how to import the models into pyxspec. 143 | xspec.AllModels.addPyMod(pyapec, pyapecInfo, 'add') 144 | xspec.AllModels.addPyMod(pyvapec, pyvapecInfo, 'add') 145 | xspec.AllModels.addPyMod(pyvvapec, pyvvapecInfo, 'add') 146 | 147 | -------------------------------------------------------------------------------- /pyatomdb/wrappers/bapec_xspec.py: -------------------------------------------------------------------------------- 1 | import numpy, xspec 2 | import pyatomdb 3 | 4 | #initialize CX object 5 | cie = pyatomdb.spectrum.CIESession() 6 | cie.set_broadening(True) 7 | 8 | # These are the definitions XSPEC uses for the inputs 9 | 10 | pybapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 11 | "Abundanc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 12 | "*Redshift \"\" 0.0",\ 13 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6") 14 | 15 | pybvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 16 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 17 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 18 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 19 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 20 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 21 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 22 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 23 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 24 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 25 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 26 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 27 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 28 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 29 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 30 | "*Redshift \"\" 0.0",\ 31 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6") 32 | 33 | 34 | pybvvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 35 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 36 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 37 | "Li \"\" 1.0 0.01 0.2 100. 1000. 0.01", 38 | "Be \"\" 1.0 0.01 0.2 100. 1000. 0.01", 39 | "B \"\" 1.0 0.01 0.2 100. 1000. 0.01", 40 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 41 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 42 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 43 | "F \"\" 1.0 0.01 0.2 100. 1000. 0.01", 44 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 45 | "Na \"\" 1.0 0.01 0.2 100. 1000. 0.01", 46 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 47 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 48 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 49 | "P \"\" 1.0 0.01 0.2 100. 1000. 0.01", 50 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 51 | "Cl \"\" 1.0 0.01 0.2 100. 1000. 0.01", 52 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 53 | "K \"\" 1.0 0.01 0.2 100. 1000. 0.01", 54 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 55 | "Sc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 56 | "Ti \"\" 1.0 0.01 0.2 100. 1000. 0.01", 57 | "V \"\" 1.0 0.01 0.2 100. 1000. 0.01", 58 | "Cr \"\" 1.0 0.01 0.2 100. 1000. 0.01", 59 | "Mn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 60 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 61 | "Co \"\" 1.0 0.01 0.2 100. 1000. 0.01", 62 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 63 | "Cu \"\" 1.0 0.01 0.2 100. 1000. 0.01", 64 | "Zn \"\" 1.0 0.01 0.2 100. 1000. 0.01",\ 65 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6", 66 | "*Redshift \"\" 0.0") 67 | 68 | 69 | 70 | def pybapec(engs, params, flux): 71 | 72 | """ 73 | ACX2 model for data 74 | 75 | PARAMETERS 76 | ---------- 77 | engs : list[float] 78 | The energy bin edges (from xspec) 79 | params : list[float] 80 | The parameter list. See acx2Info for definition 81 | flux : list[float] 82 | The array to fill with return values 83 | 84 | RETURNS 85 | ------- 86 | None 87 | Fills out the flux array with photon cm3 s-1 bin-1, x1e10 88 | 89 | USAGE 90 | ----- 91 | # load the model into XSPEC 92 | xspec.AllModels.addPyMod(pyapec, pyapecInfo, 'add') 93 | # make a model 94 | m = xspec.Model('pyapec') 95 | """ 96 | 97 | # This is the call that will return everything. So set everything! 98 | ebins = numpy.array(engs) 99 | 100 | elements = [] 101 | for i in range(1,31): elements.append(i) 102 | 103 | if len(params)==5: 104 | # apec model 105 | abund=numpy.array(params[1]) 106 | elements=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 107 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 108 | eloffset = 2 109 | elif len(params)==18: 110 | # apec model 111 | elements=[1,2,6,7,8,10,12,13,14,16,18,20,26,28] 112 | abund=params[1:15] 113 | eloffset = 15 114 | elif len(params)==34: 115 | # apec model 116 | elements=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 117 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 118 | abund=params[1:31] 119 | eloffset = 31 120 | 121 | # get redshift 122 | redshift = float(params[eloffset+0]) 123 | 124 | broadening = float(params[eloffset+1]) 125 | 126 | # set energy bins, accounting for redshift 127 | cie.set_response(ebins*(1.0+redshift), raw=True) 128 | 129 | 130 | # set abundance vector 131 | # abund = numpy.array(params[1]) 132 | cie.set_abund(elements, abund) 133 | cie.set_eebrems(False) 134 | 135 | # set the response 136 | cie.set_broadening(True, velocity_broadening=broadening) 137 | 138 | # get the spectrum 139 | spec = cie.return_spectrum(params[0], log_interp=False) 140 | 141 | # return the flux. 142 | flux[:] = spec*1e14 143 | 144 | def pybvapec(engs, params, flux): 145 | pybapec(engs, params, flux) 146 | 147 | def pybvvapec(engs, params, flux): 148 | pybapec(engs, params, flux) 149 | 150 | 151 | 152 | # this is how to import the models into pyxspec. 153 | xspec.AllModels.addPyMod(pybapec, pybapecInfo, 'add') 154 | xspec.AllModels.addPyMod(pybvapec, pybvapecInfo, 'add') 155 | xspec.AllModels.addPyMod(pybvvapec, pybvvapecInfo, 'add') 156 | 157 | -------------------------------------------------------------------------------- /pyatomdb/wrappers/rsapec_xspec.py: -------------------------------------------------------------------------------- 1 | import numpy, xspec 2 | import pyatomdb 3 | 4 | 5 | #initialize CX object 6 | cie_rs = pyatomdb.spectrum.CIESession_RS() 7 | cie_rs.set_broadening(True) 8 | 9 | # These are the definitions XSPEC uses for the inputs 10 | 11 | 12 | 13 | pyrsapecInfo = ("kT \"keV\" 4.0 0.00862 0.00862 86. 86. 0.01", 14 | "Abundanc \"\" 0.6 0.01 0.2 100. 1000. 0.01", 15 | "*Redshift \"\" 0.0",\ 16 | "Velocity \"km/s\" 150.0 -10.0 0. 0. 1e6 1e6", 17 | "nL \"cm^-2\" 1e21 1e20 1e20 1e23 1e23 1e18") 18 | 19 | 20 | 21 | pyrsvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 22 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 23 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 24 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 25 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 26 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 27 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 28 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 29 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 30 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 31 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 32 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 33 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 34 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 35 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 36 | "*Redshift \"\" 0.0",\ 37 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6", 38 | "nL \"cm^-2\" 1e21 1e20 1e20 1e23 1e23 1e18") 39 | 40 | 41 | pyrsvvapecInfo = ("kT \"keV\" 1.0 0.00862 0.00862 86. 86. 0.01", 42 | "H \"\" 1.0 0.01 0.2 100. 1000. 0.01", 43 | "He \"\" 1.0 0.01 0.2 100. 1000. 0.01", 44 | "Li \"\" 1.0 0.01 0.2 100. 1000. 0.01", 45 | "Be \"\" 1.0 0.01 0.2 100. 1000. 0.01", 46 | "B \"\" 1.0 0.01 0.2 100. 1000. 0.01", 47 | "C \"\" 1.0 0.01 0.2 100. 1000. 0.01", 48 | "N \"\" 1.0 0.01 0.2 100. 1000. 0.01", 49 | "O \"\" 1.0 0.01 0.2 100. 1000. 0.01", 50 | "F \"\" 1.0 0.01 0.2 100. 1000. 0.01", 51 | "Ne \"\" 1.0 0.01 0.2 100. 1000. 0.01", 52 | "Na \"\" 1.0 0.01 0.2 100. 1000. 0.01", 53 | "Mg \"\" 1.0 0.01 0.2 100. 1000. 0.01", 54 | "Al \"\" 1.0 0.01 0.2 100. 1000. 0.01", 55 | "Si \"\" 1.0 0.01 0.2 100. 1000. 0.01", 56 | "P \"\" 1.0 0.01 0.2 100. 1000. 0.01", 57 | "S \"\" 1.0 0.01 0.2 100. 1000. 0.01", 58 | "Cl \"\" 1.0 0.01 0.2 100. 1000. 0.01", 59 | "Ar \"\" 1.0 0.01 0.2 100. 1000. 0.01", 60 | "K \"\" 1.0 0.01 0.2 100. 1000. 0.01", 61 | "Ca \"\" 1.0 0.01 0.2 100. 1000. 0.01", 62 | "Sc \"\" 1.0 0.01 0.2 100. 1000. 0.01", 63 | "Ti \"\" 1.0 0.01 0.2 100. 1000. 0.01", 64 | "V \"\" 1.0 0.01 0.2 100. 1000. 0.01", 65 | "Cr \"\" 1.0 0.01 0.2 100. 1000. 0.01", 66 | "Mn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 67 | "Fe \"\" 1.0 0.01 0.2 100. 1000. 0.01", 68 | "Co \"\" 1.0 0.01 0.2 100. 1000. 0.01", 69 | "Ni \"\" 1.0 0.01 0.2 100. 1000. 0.01", 70 | "Cu \"\" 1.0 0.01 0.2 100. 1000. 0.01", 71 | "Zn \"\" 1.0 0.01 0.2 100. 1000. 0.01", 72 | "*Redshift \"\" 0.0",\ 73 | "Velocity \"km/s\" 0.0 -10.0 0. 0. 1e6 1e6",\ 74 | "nL \"cm^-2\" 1e21 1e20 1e20 1e23 1e23 1e18") 75 | 76 | 77 | #"Density \"cm^-3\" 0.03 1e-3 1e-3 0.05 0.05 1e-3") 78 | 79 | def pyapecrs(engs, params, flux): 80 | 81 | """ 82 | ACX2 model for data 83 | 84 | PARAMETERS 85 | ---------- 86 | engs : list[float] 87 | The energy bin edges (from xspec) 88 | params : list[float] 89 | The parameter list. See acx2Info for definition 90 | flux : list[float] 91 | The array to fill with return values 92 | 93 | RETURNS 94 | ------- 95 | None 96 | Fills out the flux array with photon cm3 s-1 bin-1, x1e10 97 | 98 | USAGE 99 | ----- 100 | # load the model into XSPEC 101 | xspec.AllModels.addPyMod(pyapec, pyapecInfo, 'add') 102 | # make a model 103 | m = xspec.Model('pyapec') 104 | """ 105 | 106 | # This is the call that will return everything. So set everything! 107 | ebins = numpy.array(engs) 108 | #print(ebins) 109 | #ebins = numpy.linspace(6.0,7.0,10000) 110 | 111 | elements = [] 112 | for i in range(1,31): elements.append(i) 113 | 114 | if len(params)==6: 115 | # apec model 116 | abund=numpy.array(params[1]) 117 | elements=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 118 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 119 | eloffset = 2 120 | 121 | elif len(params)==19: 122 | # apec model 123 | elements=[1,2,6,7,8,10,12,13,14,16,18,20,26,28] 124 | abund=params[1:15] 125 | eloffset = 15 126 | 127 | elif len(params)==35: 128 | # apec model 129 | elements=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\ 130 | 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] 131 | abund=params[1:31] 132 | eloffset = 31 133 | 134 | 135 | redshift = float(params[eloffset+0]) 136 | 137 | broadening = float(params[eloffset+1]) 138 | 139 | nL_integral = float(params[eloffset+2]) 140 | 141 | 142 | # set energy bins, accounting for redshift 143 | cie_rs.set_response(ebins*(1.0+redshift), raw=True) 144 | 145 | 146 | # set abundance vector 147 | # abund = numpy.array(params[1]) 148 | cie_rs.set_abund(elements, abund) 149 | cie_rs.set_eebrems(False) 150 | 151 | # set the response 152 | cie_rs.set_broadening(True, velocity_broadening=broadening) 153 | 154 | 155 | 156 | # get the spectrum 157 | spec = cie_rs.return_spectrum(params[0], N_e= nL_integral, Ab=abund, log_interp=False) 158 | 159 | # return the flux. 160 | flux[:] = spec*1e14 161 | 162 | 163 | def pyvapecrs(engs, params, flux): 164 | pyapecrs(engs, params, flux) 165 | 166 | 167 | def pyvvapecrs(engs, params, flux): 168 | pyapecrs(engs, params, flux) 169 | 170 | 171 | 172 | 173 | # this is how to import the models into pyxspec. 174 | xspec.AllModels.addPyMod(pyapecrs, pyrsapecInfo, 'add') 175 | xspec.AllModels.addPyMod(pyvapecrs, pyrsvapecInfo, 'add') 176 | xspec.AllModels.addPyMod(pyvvapecrs, pyrsvvapecInfo, 'add') --------------------------------------------------------------------------------