├── .editorconfig ├── .gitignore ├── .gitmodules ├── .readthedocs.yaml ├── .travis.yml ├── ChiantiPy ├── Gui │ ├── __init__.py │ ├── gui_cl │ │ ├── __init__.py │ │ └── gui.py │ └── gui_qt5 │ │ ├── __init__.py │ │ ├── gui.py │ │ └── ui.py ├── __init__.py ├── __init__gh.py ├── __init__kpd.py ├── __init_kpd__.py ├── base │ ├── _IonTrails.py │ ├── _IoneqOne.py │ ├── _SpecTrails.py │ └── __init__.py ├── core │ ├── Bunch.py │ ├── Continuum.py │ ├── Ion.py │ ├── Ioneq.py │ ├── IpyMspectrum.py │ ├── MradLoss.py │ ├── Mspectrum.py │ ├── RadLoss.py │ ├── Redux.py │ ├── Spectrum.py │ ├── __init__.py │ └── tests │ │ ├── __init__.py │ │ ├── test_Continuum.py │ │ ├── test_Ion.py │ │ ├── test_Ioneq.py │ │ ├── test_Spectrum.py │ │ └── test_spectrum_api.py ├── fortranformat │ ├── COPYING.txt │ ├── FortranRecordReader.py │ ├── FortranRecordWriter.py │ ├── __init__.py │ ├── _edit_descriptors.py │ ├── _exceptions.py │ ├── _input.py │ ├── _lexer.py │ ├── _misc.py │ ├── _output.py │ ├── _parser.py │ └── config.py ├── model │ ├── Maker.py │ └── __init__.py ├── tests │ ├── __init__.py │ ├── coveragerc │ └── setup_package.py ├── tools │ ├── __init__.py │ ├── archival.py │ ├── constants.py │ ├── data.py │ ├── filters.py │ ├── io.py │ ├── mputil.py │ ├── sources.py │ └── util.py └── version.py ├── MANIFEST.in ├── README.md ├── README.rst ├── chiantirc ├── docs ├── 0-notes.txt ├── Makefile └── source │ ├── IDL_intro.rst │ ├── _static │ ├── 2.selector.png │ ├── bunch_399_404_label.png │ ├── bunch_intensityPlot.png │ ├── bunch_selector.png │ ├── bunch_spectrumPlot.png │ ├── bunch_spectrum_integrated_mg6.png │ ├── chiantipy_logo.png │ ├── continuum_2e7_1_10.png │ ├── continuum_flare_dem_1_10.png │ ├── fe14.gofnt.png │ ├── fe14.gofnt.selector.png │ ├── fe14.gofnt_alternate.png │ ├── fe14.int.ratio.vs.d.png │ ├── fe14.int.ratio.vs.t.png │ ├── fe14.int.vs.d.png │ ├── fe14.int.vs.t.png │ ├── fe14.popplot.png │ ├── fe14.rel.emiss.png │ ├── fe14.spectrum.png │ ├── fe14.spectrum2.png │ ├── fe14.spectrum_label.png │ ├── fe14_gofnt.png │ ├── fe14_gofnt_alternate.png │ ├── fe14_integrated_spectrum_label.png │ ├── fe14_intensity_plot_lin.png │ ├── fe14_intensity_plot_lin_index10.png │ ├── fe14_intensity_plot_lin_index10_rel_notitle.png │ ├── fe14_pop_vs_dens.png │ ├── fe14_spectrum.png │ ├── fe14_spectrum2.png │ ├── fe14_spectrumPlot.png │ ├── fe14_spectrum_label.png │ ├── fe_12_wvlranges_ratio.png │ ├── fe_13_14_15_ioneq.png │ ├── fe_25_ff_fb_tp_2e7_1_10.png │ ├── fe_ioneq.png │ ├── mspectrum_1_10.png │ ├── mspectrum_spectrumPlot_10_13.png │ ├── mspectrum_spectrumPlot_1_10.png │ ├── mspectrum_spectrumPlot_4_9.png │ ├── mspectrum_spectrumPlot_6_7.png │ ├── mspectrum_spectrumPlot_fe.png │ ├── myioneq.png │ ├── ne6_mg6_spectrum.png │ ├── ne6_mg6_t_ratio.png │ ├── ne6_mg6_t_ratio_top7.png │ ├── o_8_ff_fb_tp_3e6_1_100.png │ ├── o_8_ff_fb_tp_total_3e6_1_100.png │ ├── radloss.png │ ├── radloss_hhe.png │ ├── rl_coronal_1m5.png │ ├── rl_phot_1m5.png │ ├── rl_phot_coronal_1m5.png │ ├── rl_phot_tot_bb_fb_ff_2ph.png │ ├── spectrum_10_20.png │ ├── spectrum_1_10.png │ ├── spectrum_200_300_3panel.png │ ├── spectrum_200_300_integrated.png │ ├── spectrum_200_300_w_si_9.png │ ├── spectrum_2e7_1.84_1.90.png │ ├── spectrum_spectrumPlot.png │ ├── sphinxdoc.css │ └── theme.conf │ ├── _templates │ └── layout.html │ ├── api │ ├── ChiantiPy.Gui.gui_cl.rst │ ├── ChiantiPy.Gui.gui_qt5.rst │ ├── ChiantiPy.Gui.rst │ ├── ChiantiPy.base.rst │ ├── ChiantiPy.core.rst │ ├── ChiantiPy.core.tests.rst │ ├── ChiantiPy.fortranformat.rst │ ├── ChiantiPy.model.rst │ ├── ChiantiPy.rst │ ├── ChiantiPy.tests.rst │ ├── ChiantiPy.tools.rst │ ├── _static │ │ └── chiantipy_logo.png │ ├── _templates │ │ └── layout.html │ └── index.rst │ ├── bugs.rst │ ├── changelog.rst │ ├── conf.py │ ├── getting_started.rst │ ├── index.rst │ ├── notes.rst │ ├── quick_start.rst │ ├── resources.rst │ └── tutorial.rst ├── jupyter_notebooks ├── 1_fe_13_demo_make_match.ipynb ├── 2_fe_13_demo_check_model.ipynb ├── 3_fe_13_demo_chi2_search.ipynb ├── 4_fe_13_demo_mcmc.ipynb ├── 5_fe_13_demo_mcmc_trace_analyze.ipynb ├── QuickStart.html ├── QuickStart.ipynb ├── README.txt ├── bunch_demo.ipynb ├── spectrum_demo.ipynb ├── spectrum_demo_2.ipynb └── tab2_1993_qs_fe_13.json ├── licenses ├── LICENSE └── LICENSE.fortranformat ├── pyproject.toml ├── pytest.ini ├── requirements.txt ├── rtd_environment.yml ├── setup.cfg └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | # utf, UNIX-style new line 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.{py,rst,md}] 13 | indent_style = space 14 | indent_size = 4 15 | 16 | [*.yml] 17 | indent_style = space 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.py[cod] 3 | *.a 4 | *.o 5 | *.so 6 | __pycache__ 7 | 8 | # Ignore .c files by default to avoid including generated code. If you want to 9 | # add a non-generated .c extension, use `git add -f filename.c`. 10 | *.c 11 | 12 | # Other generated files 13 | */cython_version.py 14 | htmlcov 15 | .coverage 16 | MANIFEST 17 | 18 | # Sphinx 19 | # kpd commented out the api stuff 20 | #docs/source/api 21 | docs/_build 22 | 23 | # Eclipse editor project files 24 | .project 25 | .pydevproject 26 | .settings 27 | 28 | # Pycharm editor project files 29 | .idea 30 | 31 | # Eric IDE 32 | .eric6project 33 | .eric6project/ChiantiPy.e4q 34 | .eric6project/ChiantiPy.e6t 35 | 36 | # VSCode editor project files 37 | .vscode 38 | 39 | # Packages/installer info 40 | *.egg[s] 41 | *.egg-info 42 | dist 43 | build 44 | eggs 45 | parts 46 | bin 47 | var 48 | sdist 49 | develop-eggs 50 | .installed.cfg 51 | distribute-*.tar.gz 52 | 53 | # Other 54 | .cache 55 | .tox 56 | .*.sw[op] 57 | *~ 58 | 59 | # Mac OSX 60 | .DS_Store 61 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/.gitmodules -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3.10" 7 | 8 | sphinx: 9 | configuration: docs/source/conf.py 10 | 11 | # Optionally declare the Python requirements required to build your docs 12 | python: 13 | install: 14 | - requirements: docs/requirements.txt 15 | - method: pip 16 | path: . 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "3.6" 5 | 6 | install: 7 | - pip install -e . 8 | - pip install -r requirements.txt 9 | 10 | script: pytest 11 | 12 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Select GUI package 3 | """ 4 | 5 | # 6 | import os 7 | import configparser 8 | 9 | #check chiantirc for gui selection 10 | rcfile=os.path.join(os.environ['HOME'],'.chianti/chiantirc') 11 | rcparse=configparser.ConfigParser() 12 | rcparse.read(rcfile) 13 | try: 14 | if rcparse.get('chianti','gui').lower() == 'true': 15 | use_gui=True 16 | else: 17 | use_gui=False 18 | except (KeyError,configparser.NoSectionError) as e: 19 | #default to true if section/field don't exist 20 | use_gui=True 21 | 22 | #check for available gui 23 | hasPyQt5=False 24 | try: 25 | import PyQt5 26 | hasPyQt5 = True 27 | print(' found PyQt5 widgets') 28 | del PyQt5 29 | except ImportError: 30 | print(' using cli') 31 | 32 | #set gui 33 | if hasPyQt5 and use_gui: 34 | from .gui_qt5 import gui 35 | print(' using PyQt5 widgets') 36 | else: 37 | from .gui_cl import gui 38 | print(' using CLI for selections') 39 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/gui_cl/__init__.py: -------------------------------------------------------------------------------- 1 | ''' command-line selection dialogs''' 2 | from .gui import (chpicker,selectorDialog,choice2Dialog) 3 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/gui_cl/gui.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Command line selection dialogs. 3 | ''' 4 | import os 5 | import fnmatch 6 | 7 | 'command-line selection dialogs' 8 | 9 | 10 | def chpicker(path, filter='*.*', label=None): 11 | '''Select a filename from using a command line dialog. 12 | 13 | the label keyword is included for consistency but does nothing''' 14 | if not os.path.isdir(path): 15 | path=os.curdir 16 | # if pattern is None: 17 | # pattern="All files (*.*)" 18 | allNames=os.listdir(path) 19 | names = fnmatch.filter(allNames, filter) 20 | print(' - make a selection from one of these - ') 21 | for i, one in enumerate(names): 22 | print('%6i %s '%(i, one)) 23 | raw = input(' type the index of your selection >>. ') 24 | fileName = os.path.join(path, names[int(raw)]) 25 | return fileName 26 | 27 | 28 | # 29 | # 30 | class selectorDialog: 31 | '''Make a single or multiple selection from a list of items. 32 | 33 | expects the input of an array of items, will select one or more 34 | the label and parent keywords are for consistency with other modules but do nothing''' 35 | def __init__(self, items, label=None , parent=None, multiChoice=False): 36 | # 37 | print(' - make a selection from these - ') 38 | for i, one in enumerate(items): 39 | print('%6i %s '%( i, one)) 40 | if multiChoice: 41 | print(' type the comma-separated index/indices of your selection and hit return') 42 | else: 43 | print(' type the index of your selection and hit return') 44 | raw = input('>>> ') 45 | # 46 | sraw = list(raw.split(',')) 47 | self.selectedIndex = [] 48 | self.selectedText = [] 49 | for one in sraw: 50 | self.selectedIndex.append(int(one)) 51 | self.selectedText.append(items[int(one)]) 52 | # 53 | class choice2Dialog: 54 | '''Make a single or multiplee selection from a list of items and another 55 | single or multiple selection from the same list. 56 | 57 | Useful for picking numerators and denominators. 58 | 59 | expects the input of an array of items, will select one or more from both widgets 60 | the keywords label and parent are there for consistency with real gui dialogs''' 61 | def __init__(self, items, label=None , parent=None): 62 | # 63 | print(' - select the numerator line(s) from these - ') 64 | for i, one in enumerate(items): 65 | print('%6i %s ' %( i, one)) 66 | print(' type the comma-separated index/indices of your selection') 67 | raw = input('>>> ') 68 | # 69 | sraw = list(raw.split(',')) 70 | self.numIndex = [] 71 | self.numText = [] 72 | for one in sraw: 73 | self.numIndex.append(int(one)) 74 | self.numText.append(items[int(one)]) 75 | # 76 | print(' - select the denominator line(s) from these - ') 77 | for i, one in enumerate(items): 78 | print('%6i %s ' %( i, one)) 79 | print(' type the comma-separated index/indices of your selection') 80 | raw = input('>>> ') 81 | # 82 | sraw = list(raw.split(',')) 83 | self.denIndex = [] 84 | self.denText = [] 85 | for one in sraw: 86 | self.denIndex.append(int(one)) 87 | self.denText.append(items[int(one)]) 88 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/gui_qt5/__init__.py: -------------------------------------------------------------------------------- 1 | ''' PyQt5 selection dialog widgets''' 2 | from .gui import (chpicker,selectorDialog,choice2Dialog) 3 | from .ui import (Ui_selectorDialogForm,Ui_choice2DialogForm) 4 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/gui_qt5/gui.py: -------------------------------------------------------------------------------- 1 | ''' 2 | PyQt5 widget selection dialogs 3 | ''' 4 | import os 5 | from PyQt5 import QtGui, QtWidgets 6 | 7 | 8 | import ChiantiPy 9 | from ChiantiPy.Gui.gui_qt5.ui import * 10 | ''' qt5 selection dialogs 11 | ''' 12 | 13 | class chpicker(QtWidgets.QWidget): 14 | ''' dialog to select a single file name under the directory 15 | code largely taken from pythonspot.com 16 | ''' 17 | def __init__(self, dir, label): 18 | super().__init__() 19 | self.title = 'PyQt5 file dialogs - pythonspot.com' 20 | self.left = 10 21 | self.top = 10 22 | self.width = 740 # was 640 23 | self.height = 480 24 | self.dir = dir 25 | self.label = label 26 | self.fileName = None 27 | self.initUI() 28 | 29 | def initUI(self): 30 | self.setWindowTitle(self.title) 31 | self.setGeometry(self.left, self.top, self.width, self.height) 32 | 33 | self.openFileNameDialog() 34 | # self.openFileNamesDialog() 35 | # self.saveFileDialog() 36 | 37 | self.show() 38 | self.close() 39 | 40 | def openFileNameDialog(self): 41 | options = QtWidgets.QFileDialog.Options() 42 | options |= QtWidgets.QFileDialog.DontUseNativeDialog 43 | fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, self.label, self.dir,"All Files (*);;Python Files (*.py)", options=options) 44 | # fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", self.dir,"All Files (*);;Python Files (*.py)", options=options) 45 | if fileName: 46 | print(fileName) 47 | self.fileName = fileName 48 | self.baseName = os.path.split(fileName)[1] 49 | self.rootName = os.path.splitext(self.baseName)[0] 50 | 51 | class selectorDialog(QtWidgets.QDialog): 52 | '''Make a single or multiple selection from a list of items. 53 | 54 | expects the input of an array of items, will select one or more''' 55 | def __init__(self, items, label=None , parent=None, multiChoice=False): 56 | QtWidgets.QDialog.__init__(self) 57 | self.ui = Ui_selectorDialogForm() 58 | self.ui.setupUi(self) 59 | if multiChoice: 60 | self.ui.listWidget.setSelectionMode(QtWidgets.QListWidget.MultiSelection) 61 | else: 62 | self.ui.listWidget.setSelectionMode(QtWidgets.QListWidget.SingleSelection) 63 | if label is None: 64 | self.setWindowTitle('ChiantiPy') 65 | else: 66 | self.setWindowTitle('ChiantiPy - '+label) 67 | imagefile = os.path.join(ChiantiPy.__path__[0], "images/chianti2.png") 68 | self.setWindowIcon(QtGui.QIcon(imagefile)) 69 | for anitem in items: 70 | self.ui.listWidget.addItem(str(anitem)) 71 | self.exec_() 72 | 73 | def accept(self): 74 | nitems = self.ui.listWidget.count() 75 | self.selectedIndex=[] 76 | self.selectedText=[] 77 | for i in range(nitems): 78 | anitem = self.ui.listWidget.item(i) 79 | if anitem.isSelected(): 80 | self.selectedText.append(str(anitem.text())) 81 | self.selectedIndex.append(i) 82 | self.done(1) 83 | 84 | def reject(self): 85 | self.selectedIndex = None 86 | self.selectedText = None 87 | self.done(1) 88 | 89 | class choice2Dialog(QtWidgets.QDialog): 90 | '''Make a single or multiple selection from a list of items and another 91 | single or multiple selection from the same list. 92 | 93 | Useful for picking numerators and denominators. 94 | 95 | expects the input of an array of items, will select one or more from both widgets.''' 96 | def __init__(self, items, label=None , parent=None, multi=True): 97 | # if using the Qt5Agg backend for matplotlib, the following line needs to be comment out 98 | # app=QtGui.QApplication(sys.argv) 99 | QtWidgets.QDialog.__init__(self) 100 | # app=QtGui.QApplication(sys.argv) 101 | self.ui = Ui_choice2DialogForm() 102 | self.ui.setupUi(self) 103 | if label is None: 104 | self.setWindowTitle('ChiantiPy') 105 | else: 106 | self.setWindowTitle('ChiantiPy - '+label) 107 | self.setWindowIcon(QtGui.QIcon('images/chianti2.png')) 108 | if multi: 109 | self.ui.numListWidget.setSelectionMode(QtWidgets.QListWidget.MultiSelection) 110 | self.ui.denListWidget.setSelectionMode(QtWidgets.QListWidget.MultiSelection) 111 | for anitem in items: 112 | self.ui.numListWidget.addItem(str(anitem)) 113 | self.ui.denListWidget.addItem(str(anitem)) 114 | self.exec_() 115 | # 116 | def accept(self): 117 | nitems = self.ui.numListWidget.count() 118 | self.numIndex=[] 119 | self.numText=[] 120 | for i in range(nitems): 121 | anitem = self.ui.numListWidget.item(i) 122 | if anitem.isSelected(): 123 | self.numText.append(str(anitem.text())) 124 | self.numIndex.append(i) 125 | self.denIndex=[] 126 | self.denText=[] 127 | for i in range(nitems): 128 | anitem = self.ui.denListWidget.item(i) 129 | if anitem.isSelected(): 130 | self.denText.append(str(anitem.text())) 131 | self.denIndex.append(i) 132 | self.done(1) 133 | 134 | def reject(self): 135 | print(' cancel button pushed') 136 | self.done(1) 137 | -------------------------------------------------------------------------------- /ChiantiPy/Gui/gui_qt5/ui.py: -------------------------------------------------------------------------------- 1 | # Form implementation generated from reading ui file 'choice2DialogForm.ui' 2 | # 3 | # Created: Tue Mar 17 13:52:16 2009 4 | # by: PyQt4 UI code generator 4.4.2 5 | # 6 | # WARNING! All changes made in this file will be lost! 7 | 8 | from PyQt5 import QtCore, QtGui, QtWidgets 9 | # 10 | class Ui_selectorDialogForm(object): 11 | def setupUi(self, selectorDialogForm): 12 | selectorDialogForm.setObjectName("selectorDialogForm") 13 | selectorDialogForm.setWindowModality(QtCore.Qt.WindowModal) 14 | selectorDialogForm.setModal(False) 15 | # selectorDialogForm.setWindowModality(QtCore.Qt.ApplicationModal) 16 | selectorDialogForm.resize(500,300) 17 | self.buttonBox = QtWidgets.QDialogButtonBox(selectorDialogForm) 18 | self.buttonBox.setGeometry(QtCore.QRect(30,240,341,32)) 19 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 20 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 21 | self.buttonBox.setObjectName("buttonBox") 22 | self.listWidget = QtWidgets.QListWidget(selectorDialogForm) 23 | self.listWidget.setGeometry(QtCore.QRect(70,20,400,200)) 24 | font = QtGui.QFont() 25 | font.setPointSize(14) 26 | self.listWidget.setFont(font) 27 | self.listWidget.setObjectName("listWidget") 28 | self.retranslateUi(selectorDialogForm) 29 | self.buttonBox.accepted.connect(selectorDialogForm.accept) 30 | self.buttonBox.rejected.connect(selectorDialogForm.reject) 31 | # QtCore.QMetaObject.connectSlotsByName(selectorDialogForm) 32 | 33 | def retranslateUi(self, selectorDialogForm): 34 | selectorDialogForm.setWindowTitle(QtWidgets.QApplication.translate("selectorDialogForm", "Dialog", None)) 35 | 36 | # 37 | class Ui_choice2DialogForm(object): 38 | def setupUi(self, choice2DialogForm): 39 | choice2DialogForm.setObjectName("choice2DialogForm") 40 | choice2DialogForm.setWindowModality(QtCore.Qt.WindowModal) 41 | choice2DialogForm.resize(543,368) 42 | font = QtGui.QFont() 43 | font.setPointSize(14) 44 | font.setWeight(75) 45 | font.setBold(True) 46 | choice2DialogForm.setFont(font) 47 | choice2DialogForm.setModal(False) 48 | self.widget = QtWidgets.QWidget(choice2DialogForm) 49 | self.widget.setGeometry(QtCore.QRect(10,10,522,341)) 50 | self.widget.setObjectName("widget") 51 | self.gridLayout = QtWidgets.QGridLayout(self.widget) 52 | self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) 53 | # self.gridLayout.setMargin(10) 54 | self.gridLayout.setObjectName("gridLayout") 55 | self.numLabel = QtWidgets.QLabel(self.widget) 56 | self.numLabel.setAlignment(QtCore.Qt.AlignCenter) 57 | self.numLabel.setObjectName("numLabel") 58 | self.gridLayout.addWidget(self.numLabel,0,0,1,1) 59 | self.denLabel = QtWidgets.QLabel(self.widget) 60 | self.denLabel.setAlignment(QtCore.Qt.AlignCenter) 61 | self.denLabel.setObjectName("denLabel") 62 | self.gridLayout.addWidget(self.denLabel,0,1,1,1) 63 | self.horizontalLayout = QtWidgets.QHBoxLayout() 64 | self.horizontalLayout.setObjectName("horizontalLayout") 65 | self.numListWidget = QtWidgets.QListWidget(self.widget) 66 | # self.numListWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) 67 | self.numListWidget.setObjectName("numListWidget") 68 | self.horizontalLayout.addWidget(self.numListWidget) 69 | self.denListWidget = QtWidgets.QListWidget(self.widget) 70 | # self.denListWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) 71 | self.denListWidget.setObjectName("denListWidget") 72 | self.horizontalLayout.addWidget(self.denListWidget) 73 | self.gridLayout.addLayout(self.horizontalLayout,1,0,1,2) 74 | spacerItem = QtWidgets.QSpacerItem(168,20,QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Minimum) 75 | self.gridLayout.addItem(spacerItem,2,0,1,1) 76 | self.buttonBox = QtWidgets.QDialogButtonBox(self.widget) 77 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 78 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 79 | self.buttonBox.setObjectName("buttonBox") 80 | self.gridLayout.addWidget(self.buttonBox,2,1,1,1) 81 | 82 | self.retranslateUi(choice2DialogForm) 83 | self.buttonBox.rejected.connect(choice2DialogForm.reject) 84 | self.buttonBox.accepted.connect(choice2DialogForm.accept) 85 | # QtCore.QMetaObject.connectSlotsByName(choice2DialogForm) 86 | 87 | def retranslateUi(self, choice2DialogForm): 88 | choice2DialogForm.setWindowTitle(QtWidgets.QApplication.translate("choice2DialogForm", "Pick numerators and denominators", None)) 89 | self.numLabel.setText(QtWidgets.QApplication.translate("choice2DialogForm", "Numerator", None)) 90 | self.denLabel.setText(QtWidgets.QApplication.translate("choice2DialogForm", "Denominator", None)) 91 | 92 | -------------------------------------------------------------------------------- /ChiantiPy/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ChiantiPy - CHIANTI Python package Calculates various aspects of emission lines 3 | and continua from the CHIANTI atomic database for astrophysical spectroscopy. 4 | """ 5 | 6 | from . import version 7 | __version_info__ = version.__version_info__ 8 | __version__ = version.__version__ 9 | print(' ChiantiPy version %s '%(__version__)) 10 | -------------------------------------------------------------------------------- /ChiantiPy/__init__gh.py: -------------------------------------------------------------------------------- 1 | """ 2 | ChiantiPy - CHIANTI Python package Calculates various aspects of emission lines 3 | and continua from the CHIANTI atomic database for astrophysical spectroscopy. 4 | """ 5 | # This is not yet an Astropy affiliated package, but it makes use of the Astropy 6 | # package template 7 | 8 | # this indicates whether or not we are in the package's setup.py 9 | try: 10 | _ASTROPY_SETUP_ 11 | except NameError: 12 | from sys import version_info 13 | if version_info[0] >= 3: 14 | import builtins 15 | else: 16 | import __builtin__ as builtins 17 | builtins._ASTROPY_SETUP_ = False 18 | 19 | try: 20 | from .version import version as __version__ 21 | except ImportError: 22 | __version__ = '' 23 | try: 24 | from .version import githash as __githash__ 25 | except ImportError: 26 | __githash__ = '' 27 | 28 | # Import astropy test runner if we can and dummy it if we can't 29 | import os 30 | try: 31 | from astropy.tests.helper import TestRunner 32 | test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) 33 | except ImportError: 34 | def test(*args, **kwargs): 35 | raise ImportError("astropy is needed to run the tests") 36 | 37 | # Actual package imports here: 38 | # Note this if statement is only here to allow chiantipy to be imported before 39 | # it's compiled. 40 | if not _ASTROPY_SETUP_: 41 | ## For ChiantiPy 42 | from . import version 43 | Version = version._last_generated_version 44 | -------------------------------------------------------------------------------- /ChiantiPy/__init__kpd.py: -------------------------------------------------------------------------------- 1 | """ 2 | ChiantiPy - CHIANTI Python package Calculates various aspects of emission lines 3 | and continua from the CHIANTI atomic database for astrophysical spectroscopy. 4 | """ 5 | # This is not yet an Astropy affiliated package, but it makes use of the Astropy 6 | # package template 7 | 8 | # this indicates whether or not we are in the package's setup.py 9 | try: 10 | _ASTROPY_SETUP_ 11 | except NameError: 12 | from sys import version_info 13 | if version_info[0] >= 3: 14 | import builtins 15 | else: 16 | import __builtin__ as builtins 17 | builtins._ASTROPY_SETUP_ = False 18 | 19 | try: 20 | from .version import version as __version__ 21 | except ImportError: 22 | __version__ = '' 23 | try: 24 | from .version import githash as __githash__ 25 | except ImportError: 26 | __githash__ = '' 27 | 28 | # Import astropy test runner if we can and dummy it if we can't 29 | import os 30 | try: 31 | from astropy.tests.helper import TestRunner 32 | test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) 33 | except ImportError: 34 | def test(*args, **kwargs): 35 | raise ImportError("astropy is needed to run the tests") 36 | 37 | # Actual package imports here: 38 | # Note this if statement is only here to allow chiantipy to be imported before 39 | # it's compiled. 40 | if not _ASTROPY_SETUP_: 41 | ## For ChiantiPy 42 | #from . import version 43 | #Version = version._last_generated_version 44 | ## For ChiantiPy 45 | from . import version 46 | #Version = version._last_generated_version 47 | __version__ = version.__version__ 48 | __version_info__ = version.__version_info__ 49 | -------------------------------------------------------------------------------- /ChiantiPy/__init_kpd__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ChiantiPy - CHIANTI Python package Calculates various aspects of emission lines 3 | and continua from the CHIANTI atomic database for astrophysical spectroscopy. 4 | """ 5 | # This is not yet an Astropy affiliated package, but it makes use of the Astropy 6 | # package template 7 | 8 | # this indicates whether or not we are in the package's setup.py 9 | try: 10 | _ASTROPY_SETUP_ 11 | except NameError: 12 | from sys import version_info 13 | if version_info[0] >= 3: 14 | import builtins 15 | else: 16 | import __builtin__ as builtins 17 | builtins._ASTROPY_SETUP_ = False 18 | 19 | try: 20 | from .version import version as __version__ 21 | except ImportError: 22 | __version__ = '' 23 | try: 24 | from .version import githash as __githash__ 25 | except ImportError: 26 | __githash__ = '' 27 | 28 | # Import astropy test runner if we can and dummy it if we can't 29 | import os 30 | try: 31 | from astropy.tests.helper import TestRunner 32 | test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) 33 | except ImportError: 34 | def test(*args, **kwargs): 35 | raise ImportError("astropy is needed to run the tests") 36 | 37 | # Actual package imports here: 38 | # Note this if statement is only here to allow chiantipy to be imported before 39 | # it's compiled. 40 | if not _ASTROPY_SETUP_: 41 | ## For ChiantiPy 42 | #from . import version 43 | #Version = version._last_generated_version 44 | ## For ChiantiPy 45 | from . import version 46 | #Version = version._last_generated_version 47 | __version__ = version.__version__ 48 | __version_info__ = version.__version_info__ 49 | -------------------------------------------------------------------------------- /ChiantiPy/base/_IoneqOne.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import ChiantiPy.tools.data as chdata 3 | from scipy.interpolate import splev, splrep 4 | 5 | class ioneqOne(object): 6 | """ 7 | Base class for `ChiantiPy.core.ion` and `ChiantiPy.core.continuum` 8 | """ 9 | def ioneqOne(self): 10 | ''' 11 | Provide the ionization equilibrium for the selected ion as a function of temperature. 12 | 13 | returned in self.IoneqOne 14 | ''' 15 | # 16 | if hasattr(self, 'Temperature'): 17 | temperature = self.Temperature 18 | else: 19 | return 20 | # 21 | if hasattr(self, 'IoneqAll'): 22 | ioneqAll = self.IoneqAll 23 | else: 24 | self.IoneqAll = chdata.IoneqAll 25 | ioneqAll = self.IoneqAll 26 | # 27 | ioneqTemperature = self.IoneqAll['ioneqTemperature'] 28 | Z = self.Z 29 | stage = self.Ion 30 | Dielectronic = self.Dielectronic 31 | ioneqOne = np.zeros_like(temperature) 32 | # 33 | thisIoneq = ioneqAll['ioneqAll'][Z-1,stage-1 + Dielectronic].squeeze() 34 | gioneq = thisIoneq > 0. 35 | goodt1 = self.Temperature >= ioneqTemperature[gioneq].min() 36 | goodt2 = self.Temperature <= ioneqTemperature[gioneq].max() 37 | goodt = np.logical_and(goodt1,goodt2) 38 | y2 = splrep(np.log(ioneqTemperature[gioneq]),np.log(thisIoneq[gioneq]),s=0) 39 | # 40 | if goodt.sum() > 0: 41 | if self.Temperature.size > 1: 42 | gIoneq = splev(np.log(self.Temperature[goodt]),y2) #,der=0) 43 | ioneqOne[goodt] = np.exp(gIoneq) 44 | else: 45 | gIoneq = splev(np.log(self.Temperature),y2) 46 | ioneqOne = np.exp(gIoneq)*np.ones(self.NTempDens, np.float64) 47 | self.IoneqOne = ioneqOne 48 | else: 49 | self.IoneqOne = np.zeros_like(self.Temperature) 50 | -------------------------------------------------------------------------------- /ChiantiPy/base/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base classes for ion- and spectrum-related objects. 3 | """ 4 | 5 | from ._IonTrails import ionTrails 6 | from ._SpecTrails import specTrails 7 | from ._IoneqOne import ioneqOne 8 | -------------------------------------------------------------------------------- /ChiantiPy/core/RadLoss.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | np.seterr(over='ignore') 6 | 7 | from .Continuum import continuum 8 | from .Ion import ion 9 | import ChiantiPy.tools.data as chdata 10 | import ChiantiPy.tools.constants as const 11 | import ChiantiPy.tools.util as util 12 | import ChiantiPy.tools.io as chio 13 | from ChiantiPy.base import specTrails 14 | from ChiantiPy.base import ionTrails 15 | 16 | 17 | class radLoss(ionTrails, specTrails): 18 | ''' 19 | Calculate the radiative emission loss rate as a function of temperature and density. 20 | 21 | includes elemental abundances or ionization equilibria 22 | 23 | temperature and density can be arrays but, unless the size of either is one (1), 24 | the two must have the same size 25 | 26 | 27 | A selection of ions can be make with ionList containing the names of 28 | the desired lines in Chianti notation, i.e. C VI = c_6 29 | 30 | a minimum abundance can be specified so that the calculation can be speeded up by excluding 31 | elements with a low abundance. With solar photospheric abundances - 32 | 33 | setting minAbund = 1.e-4 will include H, He, C, O, Ne 34 | setting minAbund = 2.e-5 adds N, Mg, Si, S, Fe 35 | setting minAbund = 1.e-6 adds Na, Al, Ar, Ca, Ni 36 | 37 | Setting em will multiply the spectrum at each temperature by the value of em. 38 | 39 | em [for emission measure], can be a float or an array of the same length as the 40 | temperature/density. 41 | 42 | abundance: to select a particular set of abundances, set abundance to the name of a CHIANTI abundance file, 43 | without the '.abund' suffix, e.g. 'sun_photospheric_1998_grevesse' 44 | If set to a blank (''), a gui selection menu will popup and allow the 45 | selection of an set of abundances 46 | ''' 47 | def __init__(self, temperature, eDensity, elementList=None, ionList = None, minAbund=None, 48 | doContinuum=True, doLines=True, abundance=None, verbose=0, allLines=1): 49 | t1 = datetime.now() 50 | masterlist = chdata.MasterList 51 | # use the ionList but make sure the ions are in the database 52 | if ionList: 53 | alist=[] 54 | for one in ionList: 55 | if masterlist.count(one): 56 | alist.append(one) 57 | else: 58 | if verbose: 59 | pstring = ' %s not in CHIANTI database'%(one) 60 | print(pstring) 61 | masterlist = alist 62 | self.Defaults=chdata.Defaults 63 | self.argCheck(temperature=temperature, eDensity=eDensity, pDensity=None, em=None) 64 | self.Labels = util.units(chdata.Defaults) 65 | 66 | # 67 | if abundance is not None: 68 | ab = chio.abundanceRead(abundance) 69 | abundAll = ab['abundance'] 70 | self.AbundanceName = abundance 71 | else: 72 | self.AbundanceName = self.Defaults['abundfile'] 73 | # 74 | abundAll = chdata.Abundance[self.AbundanceName]['abundance'] 75 | # 76 | # abundAll = chdata.Abundance[self.AbundanceName]['abundance'] 77 | # # needed by ionGate 78 | self.AbundAll = abundAll 79 | self.Abundance = abundAll 80 | # 81 | # nonzed = self.Abundance > 0. 82 | # minAbundAll = self.Abundance[nonzed].min() 83 | # if minAbund is even set 84 | # if minAbund: 85 | # if minAbund < minAbundAll: 86 | # minAbund = minAbundAll 87 | # self.MinAbund = minAbund 88 | # ionInfo = util.masterListInfo() 89 | # 90 | 91 | freeFreeLoss = np.zeros_like(self.Temperature) 92 | freeBoundLoss = np.zeros_like(self.Temperature) 93 | twoPhotonLoss = np.zeros_like(self.Temperature) 94 | boundBoundLoss = np.zeros_like(self.Temperature) 95 | twoPhotonLoss = np.zeros_like(self.Temperature) 96 | # 97 | self.IonsCalculated = [] 98 | 99 | self.Finished = [] 100 | # 101 | self.WvlRange = [0., 1.e+30] 102 | # 103 | self.ionGate(elementList = elementList, ionList = ionList, minAbund=minAbund, doLines=doLines, 104 | doContinuum=doContinuum, doWvlTest=0, verbose=False) 105 | # 106 | # 107 | for akey in sorted(self.Todo.keys()): 108 | zStuff = util.convertName(akey) 109 | Z = zStuff['Z'] 110 | ionstage = zStuff['Ion'] 111 | dielectronic = zStuff['Dielectronic'] 112 | abundanceZ = self.Abundance[Z - 1] 113 | if verbose: 114 | print(' %5i %5s abundance = %10.2e '%(Z, const.El[Z-1], abundanceZ)) 115 | if verbose: 116 | print(' doing ion %s for the following processes %s'%(akey, self.Todo[akey])) 117 | if ionstage != 1: 118 | if verbose: 119 | print(' calculating ff continuum for : %s'%(akey)) 120 | if 'ff' in self.Todo[akey]: 121 | # need to skip the neutral 122 | cont = continuum(akey, temperature, abundance=abundanceZ) 123 | cont.freeFreeLoss() 124 | freeFreeLoss += cont.FreeFreeLoss['rate'] 125 | if 'fb' in self.Todo[akey]: 126 | if verbose: 127 | print(' calculating fb continuum for : %s'%(akey)) 128 | cont = continuum(akey, temperature, abundance=abundanceZ) 129 | cont.freeBoundLoss(verbose=verbose) 130 | if 'errorMessage' not in cont.FreeBoundLoss.keys(): 131 | freeBoundLoss += cont.FreeBoundLoss['rate'] 132 | if 'line' in self.Todo[akey]: 133 | if verbose: 134 | print(' calculating spectrum for : %s'%(akey)) 135 | thisIon = ion(akey, temperature, eDensity, abundance=abundanceZ) 136 | thisIon.intensity(allLines=allLines) 137 | self.IonsCalculated.append(akey) 138 | if 'errorMessage' not in thisIon.Intensity.keys(): 139 | self.Finished.append(akey) 140 | thisIon.boundBoundLoss() 141 | boundBoundLoss += thisIon.BoundBoundLoss['rate'] 142 | else: 143 | if verbose: 144 | print(thisIon.Intensity['errorMessage']) 145 | # get 2 photon emission for H and He sequences 146 | if (Z - ionstage) in [0, 1] and not dielectronic: 147 | thisIon.twoPhotonLoss() 148 | twoPhotonLoss += thisIon.TwoPhotonLoss['rate'] 149 | self.FreeFreeLoss = freeFreeLoss 150 | self.FreeBoundLoss = freeBoundLoss 151 | self.BoundBoundLoss = boundBoundLoss 152 | self.TwoPhotonLoss = twoPhotonLoss 153 | # 154 | total = freeFreeLoss + freeBoundLoss + boundBoundLoss + twoPhotonLoss 155 | t2 = datetime.now() 156 | dt=t2-t1 157 | print(' elapsed seconds = %10.2e'%(dt.seconds)) 158 | xlabel = self.Labels['radlossTlabel'] 159 | ylabel = self.Labels['radlossYlabel'] 160 | self.RadLoss = {'rate':total, 'temperature':self.Temperature, 'density':self.EDensity, 161 | 'minAbund':minAbund, 'abundance':self.AbundanceName, 'ylabel':ylabel, 'xlabel':xlabel} 162 | # 163 | # ------------------------------------------------------------------- 164 | # 165 | def radLossPlot(self, doTitle=False): 166 | ''' 167 | to plot the radiative losses vs temperature 168 | 169 | Parameters 170 | ---------- 171 | 172 | doTitle: `bool` 173 | 174 | if True, a title is applied to the plot. The default is for no title 175 | 176 | ''' 177 | fontsize = 16 178 | temp = self.RadLoss['temperature'] 179 | rate = self.RadLoss['rate'] 180 | plt.loglog(temp, rate, 'k', lw=2) 181 | plt.xlabel(self.RadLoss['xlabel'],fontsize=fontsize) 182 | plt.ylabel(self.RadLoss['ylabel'],fontsize=fontsize) 183 | plt.xlim(left = temp.min(), right = temp.max()) 184 | if doTitle: 185 | if hasattr(self, 'AbundanceName'): 186 | title = 'Radiative loss rate, %s'%(self.AbundanceName) 187 | if hasattr(self, 'MinAbund'): 188 | title += ' minAbund = %10.2e'%(self.MinAbund) 189 | if self.EDensity.size == 1: 190 | title += ', density = %10.2e'%(self.EDensity) 191 | plt.title(title, fontsize=fontsize) 192 | plt.tight_layout() 193 | -------------------------------------------------------------------------------- /ChiantiPy/core/Redux.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from ChiantiPy.base import ionTrails 3 | from ChiantiPy.base import specTrails 4 | 5 | 6 | class redux(ionTrails, specTrails): 7 | """ a class for restoring save multi-ion saveData files 8 | """ 9 | def __init__(self, filename, verbose=False): 10 | """ 11 | 12 | :param filename: filename of a file saved by the saveData method 13 | :type filename: str 14 | 15 | :param verbose: if true, prints additional informations 16 | :type verbose: bool 17 | 18 | the redux class inherets the following useful methods: 19 | intensityList 20 | intensityPlot 21 | intensityRatio 22 | intensityRatioSave 23 | 24 | convolve 25 | lineSpectrumPlot 26 | restoreData 27 | spectrumPlot 28 | 29 | """ 30 | if not os.path.isfile(filename): 31 | print(' print restore must be set to a valid filename') 32 | return 33 | elif os.path.isfile(filename): 34 | self.restoreData(filename) 35 | 36 | if verbose: 37 | for aname in self.__dict__.keys(): 38 | print(' restored attribute %s'%(aname)) 39 | -------------------------------------------------------------------------------- /ChiantiPy/core/Spectrum.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from datetime import datetime 3 | import numpy as np 4 | import ChiantiPy 5 | import ChiantiPy.tools.data as chdata 6 | import ChiantiPy.tools.constants as const 7 | import ChiantiPy.tools.filters as chfilters 8 | import ChiantiPy.tools.util as util 9 | import ChiantiPy.tools.io as chio 10 | 11 | from ChiantiPy.base import ionTrails 12 | from ChiantiPy.base import specTrails 13 | 14 | 15 | class spectrum(ionTrails, specTrails): 16 | ''' 17 | Calculate the emission spectrum as a function of temperature and density. 18 | 19 | one of the convenient things is that all of the instantiated ion classes, determined 20 | through such keywords as 'elementList', 'ionList', and 'minAbund' are kept in a 21 | dictionary self.IonInstances where self.IonInstances['mg_7'] is the class instance of 22 | ChiantiPy.core.ion for 'mg_7'. All its methods and attributes are available. 23 | 24 | includes elemental abundances and ionization equilibria 25 | 26 | the set of abundances, a file in $XUVTOP/abundance, can be set with the keyword argument 'abundanceName' 27 | 28 | temperature and density can be arrays but, unless the size of either is unity (1), 29 | the two must have the same size 30 | 31 | the returned spectrum will be convolved with a filter of the specified width on the 32 | specified wavelength array 33 | 34 | the default filter is gaussianR with a resolving power of 1000. Other filters, 35 | such as gaussian, box and lorentz, are available in ChiantiPy.tools.filters. When 36 | using the box filter, the width should equal the wavelength interval to keep the units 37 | of the continuum and line spectrum the same. 38 | 39 | Inherited methods include 'intensityList', 'intensityRatio' (between lines of different ions), 40 | 'intensityRatioSave' and 'convolve' 41 | 42 | A selection of elements can be make with elementList a list containing the names of elements 43 | that are desired to be included, e.g., ['fe','ni'] 44 | 45 | A selection of ions can be make with ionList containing the names of 46 | the desired lines in CHIANTI notation, i.e. C VI = c_6 47 | 48 | Both elementList and ionList can not be specified at the same time 49 | 50 | a minimum abundance can be specified so that the calculation can be speeded up 51 | by excluding elements with a low abundance. The default of minAbund is 1.e-6 52 | 53 | It is necessary to specify at least an elementList, an ionList, or a minAbund to select any ions 54 | for a spectrum calculation 55 | 56 | With solar photospheric abundances 57 | 58 | setting minAbund = 1.e-4 will include H, He, C, O, Ne 59 | 60 | setting minAbund = 2.e-5 adds N, Mg, Si, S, Fe 61 | 62 | setting minAbund = 1.e-6 adds Na, Al, Ar, Ca, Ni 63 | 64 | Setting doLines = 0 will skip the calculation of spectral lines. 65 | Setting doContinuum =0 will skip the continuum calculation. 66 | 67 | Setting em [for emission measure] will multiply the spectrum at each temperature 68 | by the value of em. 69 | 70 | em [for emission measure] can be a float or an array of the same length as the 71 | temperature/density 72 | 73 | keepIons set this to keep the ion instances that have been calculated in a dictionary 74 | self.IonInstances with the keywords being the CHIANTI-style ion names 75 | 76 | abundance - to select a particular set of abundances, set abundance to the name of a 77 | CHIANTI abundance file, without the '.abund' suffix, e.g. 'sun_photospheric_1998_grevesse' 78 | 79 | If set to a blank (''), a gui selection menu will popup and allow the selection of an 80 | set of abundances 81 | 82 | Parameters 83 | -------------- 84 | 85 | temperature: `float`, `list`, `ndarray` 86 | the temperature(s) in K 87 | 88 | eDensity: float, ndarray 89 | eDensity: electron density in :math:`\\mathrm{cm^{-3}}` 90 | 91 | wavelength: `list` or `ndarray` 92 | wavelength: array of wavelengths, generally in Angstroms 93 | 94 | elementList: `list` 95 | elementList: list of elements to include, such as 'fe', 'ne', 's' 96 | 97 | ionList: `list` 98 | ionList: list of ions to include, such as 'fe_16', 'ne_10' 99 | 100 | minAbund: `float` 101 | minAbund: minimum abundance (relative to H) to include 102 | 103 | doLines: `bool1 104 | doLines: if true, line intensities are calculated 105 | 106 | doContinuum: `bool` 107 | doContinuum: if true, continuum intensities are calculated only if wavelengths are in angstroms 108 | 109 | keepIons: `bool` 110 | keepIons: keep the ion instances used in the calculation 111 | should be used with caution otherwise the bunch instance 112 | can become quite large 113 | 114 | em: `float`, `list`, `ndarray` 115 | em: the emission measure 116 | 117 | abundance: `str` 118 | abuncance: the file name of the abuncance set to be used 119 | must be one in the $XUVTOP/abund directory 120 | 121 | allLInes: `bool` 122 | allLines: whether or not to include unobserved lines 123 | 124 | verbose: `bool` 125 | verbose: whether to allow certain print statements 126 | 127 | ''' 128 | def __init__(self, temperature, eDensity, wavelength, filter=(chfilters.gaussianR, 1000.), label=None, 129 | elementList = None, ionList = None, minAbund=None, doLines = True, doContinuum = True, em=None, keepIons=0, 130 | abundance=None, verbose=0, allLines=1): 131 | # 132 | self.Defaults=chdata.Defaults 133 | 134 | if doContinuum and self.Defaults['wavelength'] != 'angstrom': 135 | print(' the continuum can only be calculated for wavelengths in angstroms') 136 | print(' set doContuum = False to continue') 137 | return 138 | 139 | wavelength = np.atleast_1d(wavelength) 140 | 141 | if wavelength.size < 2: 142 | print(' wavelength must have at least two values, current length %3i'%(wavelength.size)) 143 | return 144 | 145 | t1 = datetime.now() 146 | # creates Intensity dict from first ion calculated 147 | setupIntensity = False 148 | # 149 | self.Wavelength = np.asarray(wavelength, np.float64) 150 | self.WvlRange = np.asarray([self.Wavelength.min(), self.Wavelength.max()], np.float64) 151 | # 152 | self.argCheck(temperature=temperature, eDensity=eDensity, pDensity=None, em=em) 153 | 154 | nTempDens = self.NTempDens 155 | 156 | self.Labels = util.units(chdata.Defaults) 157 | 158 | xlabel = self.Labels['xlabel'] 159 | ylabel = self.Labels['spectrumYlabel'] 160 | 161 | if np.array_equal(self.Em, np.ones_like(self.Em)): 162 | ylabel += '($\\int\\,$ N$_e\\,$N$_H\\,$d${\\it l}$)$^{-1}$' 163 | # 164 | if abundance is not None: 165 | ab = chio.abundanceRead(abundance) 166 | abundAll = ab['abundance'] 167 | self.AbundanceName = abundance 168 | else: 169 | self.AbundanceName = self.Defaults['abundfile'] 170 | abundAll = chdata.Abundance[self.AbundanceName]['abundance'] 171 | 172 | # needed by ionGate 173 | self.AbundAll = abundAll 174 | self.Abundance = abundAll 175 | # 176 | self.MinAbund = minAbund 177 | wavelength = np.asarray(wavelength) 178 | nWvl = wavelength.size 179 | self.Wavelength = wavelength 180 | # 181 | freeFree = np.zeros((nTempDens, nWvl), np.float64).squeeze() 182 | freeBound = np.zeros((nTempDens, nWvl), np.float64).squeeze() 183 | twoPhoton = np.zeros((nTempDens, nWvl), np.float64).squeeze() 184 | lineSpectrum = np.zeros((nTempDens, nWvl), np.float64).squeeze() 185 | # 186 | self.IonsCalculated = [] 187 | if keepIons: 188 | self.IonInstances = {} 189 | self.FfInstances = {} 190 | self.FbInstances = {} 191 | self.Finished = [] 192 | # 193 | self.ionGate(elementList = elementList, ionList = ionList, minAbund=minAbund, doLines=doLines, 194 | doContinuum=doContinuum) 195 | # 196 | for akey in sorted(self.Todo.keys()): 197 | zStuff = util.convertName(akey) 198 | Z = zStuff['Z'] 199 | ionstage = zStuff['Ion'] 200 | dielectronic = zStuff['Dielectronic'] 201 | abundance = self.Abundance[Z - 1] 202 | if verbose: 203 | print(' %5i %5s abundance = %10.2e '%(Z, const.El[Z-1], abundance)) 204 | print(' doing ion %s for the following processes %s'%(akey, self.Todo[akey])) 205 | if 'ff' in self.Todo[akey]: 206 | if verbose: 207 | print(' calculating ff continuum for : %s'%(akey)) 208 | FF = ChiantiPy.core.continuum(akey, temperature, abundance=abundance, em=em, verbose=verbose) 209 | FF.freeFree(wavelength) 210 | freeFree += FF.FreeFree['intensity'].squeeze() 211 | if keepIons: 212 | self.FfInstances[akey] = copy.deepcopy(FF) 213 | 214 | if 'fb' in self.Todo[akey]: 215 | if verbose: 216 | print(' calculating fb continuum for : %s'%(akey)) 217 | FB = ChiantiPy.core.continuum(akey, temperature, abundance=abundance, em=em, verbose=verbose) 218 | FB.freeBound(wavelength) 219 | if 'errorMessage' not in FB.FreeBound.keys(): 220 | freeBound += FB.FreeBound['intensity'].squeeze() 221 | if keepIons: 222 | self.FbInstances[akey] = copy.deepcopy(FB) 223 | else: 224 | if verbose: 225 | print(FB.FreeBound['errorMessage']) 226 | if 'line' in self.Todo[akey]: 227 | if verbose: 228 | print(' calculating spectrum for : %s'%(akey)) 229 | thisIon = ChiantiPy.core.ion(akey, temperature, eDensity, pDensity='default', abundance=abundance, em=em, verbose=verbose) 230 | thisIon.intensity(allLines=allLines) 231 | self.IonsCalculated.append(akey) 232 | if 'errorMessage' not in list(thisIon.Intensity.keys()): 233 | self.Finished.append(akey) 234 | thisIon.spectrum(wavelength, filter=filter, allLines=allLines) 235 | if keepIons: 236 | self.IonInstances[akey] = copy.deepcopy(thisIon) 237 | if setupIntensity: 238 | for bkey in self.Intensity: 239 | self.Intensity[bkey] = np.hstack((copy.copy(self.Intensity[bkey]), 240 | thisIon.Intensity[bkey])) 241 | else: 242 | setupIntensity = True 243 | self.Intensity = thisIon.Intensity 244 | lineSpectrum += thisIon.Spectrum['intensity'].squeeze() 245 | else: 246 | if verbose: 247 | print(thisIon.Intensity['errorMessage']) 248 | # get 2 photon emission for H and He sequences 249 | if doContinuum: 250 | print(self.Todo[akey]) 251 | if (Z - ionstage) in [0, 1] and not dielectronic: 252 | thisIon.twoPhoton(wavelength) 253 | twoPhoton += thisIon.TwoPhoton['intensity'].squeeze() 254 | if verbose: 255 | print(' doing two photon') 256 | 257 | self.FreeFree = {'wavelength':wavelength, 'intensity':freeFree.squeeze()} 258 | self.FreeBound = {'wavelength':wavelength, 'intensity':freeBound.squeeze()} 259 | self.LineSpectrum = {'wavelength':wavelength, 'intensity':lineSpectrum.squeeze()} 260 | self.TwoPhoton = {'wavelength':wavelength, 'intensity':twoPhoton.squeeze()} 261 | cont = freeFree.squeeze() + freeBound.squeeze() + twoPhoton.squeeze() 262 | self.Continuum = {'wavelength':wavelength, 'intensity':cont} 263 | # 264 | # 265 | total = freeFree + freeBound + lineSpectrum + twoPhoton 266 | self.Total = total 267 | 268 | t2 = datetime.now() 269 | dt=t2-t1 270 | print(' elapsed seconds = %12.3f'%(dt.seconds)) 271 | if nTempDens == 1: 272 | integrated = total 273 | else: 274 | integrated = total.sum(axis=0) 275 | # 276 | if type(label) == type(''): 277 | if hasattr(self, 'Spectrum'): 278 | self.Spectrum[label] = {'wavelength':wavelength, 'intensity':total.squeeze(), 279 | 'filter':filter[0], 'filterWidth':filter[1], 'integrated':integrated, 'em':em, 280 | 'ions':self.IonsCalculated, 'Abundance':self.AbundanceName, 'xlabel':xlabel, 281 | 'ylabel':ylabel, 'minAbund':minAbund} 282 | 283 | else: 284 | self.Spectrum = {label:{'wavelength':wavelength, 'intensity':total.squeeze(), 285 | 'filter':filter[0], 'filterWidth':filter[1], 'integrated':integrated, 'em':em, 286 | 'ions':self.IonsCalculated, 'Abundance':self.AbundanceName, 'xlabel':xlabel, 287 | 'ylabel':ylabel, 'minAbund':minAbund}} 288 | 289 | else: 290 | self.Spectrum = {'wavelength':wavelength, 'intensity':total.squeeze(), 291 | 'filter':filter[0], 'filterWidth':filter[1], 'integrated':integrated, 292 | 'ions':self.IonsCalculated, 'Abundance':self.AbundanceName, 'xlabel':xlabel, 293 | 'ylabel':ylabel, 'minAbund':minAbund} 294 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /ChiantiPy/core/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | chianti.core - contains the main classes for ChiantiPy users. 3 | 4 | This software is distributed under the terms of the ISC Software License 5 | that is found in the LICENSE file 6 | 7 | """ 8 | from .Spectrum import spectrum 9 | from .Bunch import bunch 10 | from .Mspectrum import mspectrum 11 | from .IpyMspectrum import ipymspectrum 12 | from .Continuum import continuum 13 | from .RadLoss import radLoss 14 | from .MradLoss import mradLoss 15 | from .Ion import ion 16 | from .Ioneq import ioneq 17 | from .Redux import redux 18 | -------------------------------------------------------------------------------- /ChiantiPy/core/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/ChiantiPy/core/tests/__init__.py -------------------------------------------------------------------------------- /ChiantiPy/core/tests/test_Continuum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for the continuum class 3 | """ 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | from ChiantiPy.core import Continuum 9 | 10 | # test ion 11 | test_ion = 'fe_15' 12 | # set some wavelength and temperature arrays 13 | temperature_scalar = 1e+6 14 | temperature_array = np.logspace(5,8,10) 15 | wavelength_array = np.linspace(10,100,100) 16 | # create continuum object for testing 17 | tmp_cont_scalar = Continuum.continuum(test_ion, temperature_scalar) 18 | tmp_cont_array = Continuum.continuum(test_ion, temperature_array) 19 | # create continuum object for which there is no free-bound information available 20 | tmp_cont_no_fb = Continuum.continuum('fe_3', temperature_array) 21 | 22 | 23 | def test_temperature(): 24 | _tmp_cont = Continuum.continuum(test_ion, temperature_scalar) 25 | assert np.all(np.atleast_1d(temperature_scalar) == _tmp_cont.Temperature) 26 | _tmp_cont = Continuum.continuum(test_ion, temperature_array) 27 | assert np.all(temperature_array == _tmp_cont.Temperature) 28 | 29 | 30 | def test_free_free_scalar(): 31 | # call free-free emission and loss rate methods for scalar temperature 32 | # emission--wavelength array 33 | tmp_cont_scalar.freeFree(wavelength_array) 34 | assert hasattr(tmp_cont_scalar, 'FreeFree') 35 | assert tmp_cont_scalar.FreeFree['intensity'].shape == wavelength_array.shape 36 | # loss 37 | tmp_cont_scalar.freeFreeLoss() 38 | assert hasattr(tmp_cont_scalar, 'FreeFreeLoss') 39 | assert tmp_cont_scalar.FreeFreeLoss['rate'].shape == (1,) 40 | 41 | 42 | def test_free_free_array(): 43 | # call free-free emission and loss rate methods for scalar temperature 44 | # emission--wavelength array 45 | tmp_cont_array.freeFree(wavelength_array) 46 | assert hasattr(tmp_cont_array, 'FreeFree') 47 | assert tmp_cont_array.FreeFree['intensity'].shape == temperature_array.shape+wavelength_array.shape 48 | # loss 49 | tmp_cont_array.freeFreeLoss() 50 | assert hasattr(tmp_cont_array, 'FreeFreeLoss') 51 | assert tmp_cont_array.FreeFreeLoss['rate'].shape == temperature_array.shape 52 | 53 | 54 | def test_free_bound_scalar(): 55 | # free-bound emission and loss rate methods for scalar temperature 56 | # emiss--wavelength array 57 | tmp_cont_scalar.freeBound(wavelength_array) 58 | assert hasattr(tmp_cont_scalar,'FreeBound') 59 | assert tmp_cont_scalar.FreeBound['intensity'].shape == wavelength_array.shape 60 | # loss 61 | tmp_cont_scalar.freeBoundLoss() 62 | assert hasattr(tmp_cont_scalar, 'FreeBoundLoss') 63 | assert tmp_cont_scalar.FreeBoundLoss['rate'].shape == (1,) 64 | 65 | 66 | def test_free_bound_array(): 67 | # free-bound emission and loss rate methods for temperature array 68 | # emiss--wavelength array 69 | tmp_cont_array.freeBound(wavelength_array) 70 | assert hasattr(tmp_cont_array,'FreeBound') 71 | assert tmp_cont_array.FreeBound['intensity'].shape == temperature_array.shape+wavelength_array.shape 72 | # loss 73 | tmp_cont_array.freeBoundLoss() 74 | assert hasattr(tmp_cont_array, 'FreeBoundLoss') 75 | assert tmp_cont_array.FreeBoundLoss['rate'].shape == temperature_array.shape 76 | 77 | 78 | def test_free_bound_no_info(): 79 | # raise error if no free-bound information is available 80 | tmp_cont_no_fb.freeBound(wavelength_array) 81 | assert 'errorMessage' in tmp_cont_no_fb.FreeBound.keys() 82 | -------------------------------------------------------------------------------- /ChiantiPy/core/tests/test_Ion.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for the ion class. 3 | """ 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | from ChiantiPy.core import ion 9 | import ChiantiPy.tools as ch_tools 10 | 11 | # use an ion with relatively small chianti files 12 | #test_ion = 'fe_15' 13 | # want an ion with auto-ionization rates 14 | test_ion = 'o_6' 15 | # TODO: probably should check a few different ions, i.e. dielectronic, some without certain kinds 16 | # files, etc. 17 | # set a few temperature and density arrays 18 | temperature_1 = 1e+6 19 | temperature_2 = np.logspace(5,8,20) 20 | density_1 = 1e+9 21 | density_2 = np.logspace(5,8,20) 22 | density_3 = np.logspace(5,8,21) 23 | # setup an ion object to reuse in several tests 24 | tmp_ion = ion(test_ion, temperature=temperature_2, eDensity=density_2) 25 | 26 | 27 | # Check various ways to specify the temperature and density 28 | def test_temperature_density(): 29 | # TODO: test case where neither are set/ one or the other is not set 30 | # Two single values 31 | _tmp_ion = ion(test_ion, temperature=temperature_1, eDensity=density_1, setup=True) 32 | assert _tmp_ion.Temperature == np.array(temperature_1) 33 | assert _tmp_ion.EDensity == np.array(density_1) 34 | # Multiple temperatures, one density 35 | _tmp_ion = ion(test_ion, temperature=temperature_2, eDensity=density_1, setup=True) 36 | assert np.all(_tmp_ion.Temperature == temperature_2) 37 | assert np.all(_tmp_ion.EDensity == np.array(temperature_2.size*[density_1])) 38 | # One temperature, multiple densities 39 | _tmp_ion = ion(test_ion, temperature=temperature_1, eDensity=density_2, setup=True) 40 | assert np.all(_tmp_ion.Temperature == np.array(density_2.size*[temperature_1])) 41 | assert np.all(_tmp_ion.EDensity == density_2) 42 | # Two equal-sized temperature and density arrays 43 | _tmp_ion = ion(test_ion, temperature=temperature_2, eDensity=density_2, setup=True) 44 | assert np.all(_tmp_ion.Temperature == temperature_2) 45 | assert np.all(_tmp_ion.EDensity == density_2) 46 | # Two unequal sized temperature and density arrays 47 | with pytest.raises(ValueError, 48 | message='''Expecting ValueError when temperature and density are not of 49 | equal size.'''): 50 | _tmp_ion = ion(test_ion, temperature=temperature_2, eDensity=density_3, setup=True) 51 | 52 | 53 | # Check how abundance is set 54 | def test_abundance(): 55 | # Float value 56 | _tmp_ion = ion(test_ion, temperature = temperature_1, eDensity = density_1, abundance=0.01, setup=False) 57 | assert _tmp_ion.Abundance == 0.01 58 | # FIXME: if setting custom abundance, AbundanceName should not be set, but right 59 | # now it is by the proton/electron density ratio calculation. 60 | # Custom filename 61 | _tmp_ion = ion(test_ion, temperature = temperature_1, eDensity = density_1, abundance='sun_coronal_2012_schmelz', setup=False) 62 | assert _tmp_ion.AbundanceName == 'sun_coronal_2012_schmelz' 63 | abundance = ch_tools.io.abundanceRead(abundancename='sun_coronal_2012_schmelz') 64 | assert _tmp_ion.Abundance == abundance['abundance'][_tmp_ion.Z-1] 65 | 66 | 67 | # Check CHIANTI file imports 68 | def test_chianti_files(): 69 | assert hasattr(tmp_ion, 'Elvlc') 70 | assert hasattr(tmp_ion, 'Wgfa') 71 | if tmp_ion.Nscups > 0: 72 | assert hasattr(tmp_ion, 'Scups') 73 | if tmp_ion.Ncilvl > 0: 74 | assert hasattr(tmp_ion, 'Cilvl') 75 | if tmp_ion.Nreclvl > 0: 76 | assert hasattr(tmp_ion, 'Reclvl') 77 | if tmp_ion.Npsplups > 0: 78 | assert hasattr(tmp_ion, 'Psplups') 79 | -------------------------------------------------------------------------------- /ChiantiPy/core/tests/test_Ioneq.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for ioneq class 3 | """ 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | import ChiantiPy.tools.util as util 9 | from ChiantiPy.core import ioneq 10 | 11 | temperature = np.logspace(4,9,50) 12 | # Element and Z should represent the same element 13 | el = 'Fe' 14 | z = 26 15 | 16 | # TODO: test temperatures out of valid extrapolation range 17 | 18 | 19 | def test_el_input(): 20 | el_ioneq_input = ioneq(el) 21 | assert el_ioneq_input.Z == util.el2z(el) 22 | 23 | 24 | def test_z_input(): 25 | z_ioneq_input = ioneq(z) 26 | 27 | 28 | def test_el_z_inputs_same(): 29 | el_ioneq_input = ioneq(el) 30 | z_ioneq_input = ioneq(z) 31 | el_ioneq_input.load() 32 | z_ioneq_input.load() 33 | assert np.all(el_ioneq_input.Temperature == z_ioneq_input.Temperature) 34 | assert np.all(el_ioneq_input.Ioneq == z_ioneq_input.Ioneq) 35 | 36 | 37 | def test_calculate_ioneq(): 38 | calc_ioneq = ioneq(el) 39 | calc_ioneq.calculate(temperature) 40 | assert hasattr(calc_ioneq, 'Temperature') 41 | assert hasattr(calc_ioneq, 'Ioneq') 42 | assert np.all(calc_ioneq.Temperature == temperature) 43 | 44 | 45 | def test_load_ioneq(): 46 | load_ioneq = ioneq(el) 47 | load_ioneq.load() 48 | assert hasattr(load_ioneq, 'Temperature') 49 | assert hasattr(load_ioneq, 'Ioneq') 50 | 51 | 52 | def test_load_ioneq_alternate_file(): 53 | load_ioneq = ioneq(el) 54 | load_ioneq.load(ioneqName='chianti') 55 | assert hasattr(load_ioneq, 'Temperature') 56 | assert hasattr(load_ioneq, 'Ioneq') 57 | -------------------------------------------------------------------------------- /ChiantiPy/core/tests/test_Spectrum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for the spectrum and bunch classes 3 | """ 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | from ChiantiPy.core import spectrum, bunch 9 | 10 | # set temperature, density, wavelength 11 | temperature_scalar = 2e6 12 | temperature_array_1d = np.array([temperature_scalar]) 13 | temperature_array = np.array([1e+6,4e+6,1e+7]) 14 | temperature_array_long = np.logspace(5,8,10) 15 | density = 1e+9 16 | em = 1.e+27 17 | wavelength = np.linspace(200,400,1000) 18 | wavelength_range = [wavelength[0], wavelength[-1]] 19 | min_abund = 1.e-4 20 | ion_list = ['fe_15', 'fe_16'] 21 | 22 | 23 | def test_spectrum_scalar(): 24 | _tmp_spec = spectrum(temperature_scalar, density, wavelength, minAbund=min_abund) 25 | assert _tmp_spec.Spectrum['intensity'].shape == wavelength.shape 26 | 27 | 28 | def test_spectrum_array(): 29 | _tmp_spec = spectrum(temperature_array_1d, density, wavelength, minAbund=min_abund) 30 | assert _tmp_spec.Spectrum['intensity'].shape == wavelength.shape 31 | _tmp_spec = spectrum(temperature_array, density, wavelength, minAbund=min_abund) 32 | assert _tmp_spec.Spectrum['intensity'].shape == temperature_array.shape+wavelength.shape 33 | 34 | 35 | def test_bunch(): 36 | _tmp_bunch = bunch(temperature_array_long, density, wvlRange=wavelength_range, ionList=ion_list) 37 | # TODO: need to assert something here, not clear what exactly to test yet 38 | -------------------------------------------------------------------------------- /ChiantiPy/core/tests/test_spectrum_api.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import warnings 3 | 4 | import numpy as np 5 | import pytest 6 | 7 | from ChiantiPy.core import spectrum, bunch, mspectrum, radLoss 8 | 9 | try: 10 | from ChiantiPy.core import ipymspectrum 11 | except ImportError as error: 12 | warnings.warn("Could not import IpyMspectrum; you may be missing ipyparellel.") 13 | ipymspectrum = error 14 | 15 | # These tests verify that the spectrum classes (Spectrum, Mspectrum, and IpyMspectrum) and the Bunch class accept the 16 | # same kind of basic array/container arguments for temperature, density, emission measure and minimum abundance. 17 | 18 | _spectrum_like_type = (spectrum, bunch, mspectrum) 19 | _container_type = (np.array,) # tuple, list, np.atleast_2d) 20 | _array_lengths = (1, 5) 21 | 22 | 23 | # Test that scalar temperature and container works together. 24 | @pytest.mark.parametrize("container_type", _container_type) 25 | @pytest.mark.parametrize("density_length", _array_lengths) 26 | def test_radloss_scalar_container_compatibility(container_type, density_length): 27 | temperature = 1e6 28 | density = container_type(np.linspace(1e9, 2e9, density_length)) 29 | _tmp_spec = radLoss(temperature, density, minAbund=1e-3) 30 | 31 | 32 | # Test that container and scalar density works together. 33 | @pytest.mark.parametrize("container_type", _container_type) 34 | @pytest.mark.parametrize("temperature_length", _array_lengths) 35 | def test_radloss_container_scalar_compatibility(container_type, temperature_length): 36 | temperature = container_type(np.linspace(1e6, 2e6, temperature_length)) 37 | density = 1e9 38 | _tmp_spec = radLoss(temperature, density, minAbund=1e-3) 39 | 40 | 41 | # Test that the shape of the arguments are compatible. All arguments have to have length 1 on length N. 42 | @pytest.mark.parametrize("container_type", _container_type) 43 | @pytest.mark.parametrize("temperature_length", _array_lengths) 44 | @pytest.mark.parametrize("density_length", _array_lengths) 45 | def test_radloss_numpy_length_compatibility(container_type, temperature_length, density_length): 46 | temperature = container_type(np.linspace(1e6, 2e6, temperature_length)) 47 | density = container_type(np.linspace(1e9, 2e9, density_length)) 48 | _tmp_spec = radLoss(temperature, density, minAbund=1e-3) 49 | 50 | 51 | # Save test as above but for the spectrum classes and bunch. 52 | # The emission spectrum can also be None so that is also tested. 53 | # Same test as above but also tests when all arguments are tuples or lists. Most likely these tests will succeed if 54 | # the corresponding test_spectrum_numpy_length_compatibility succeeds. 55 | @pytest.mark.parametrize("spectrum_like_type", _spectrum_like_type) 56 | @pytest.mark.parametrize("container_type", _container_type) 57 | @pytest.mark.parametrize("temperature_length", _array_lengths) 58 | @pytest.mark.parametrize("density_length", _array_lengths) 59 | #@pytest.mark.parametrize("em_length", _array_lengths + (None,)) 60 | # edit by kpd 2020-feb-1 61 | @pytest.mark.parametrize("em_length", _array_lengths) 62 | def test_spectrum_container_length_compatibility(spectrum_like_type, container_type, 63 | temperature_length, density_length, em_length): 64 | if spectrum_like_type is mspectrum and platform.system() == 'Darwin': 65 | pytest.xfail("The %s class fails when running on MacOS." % str(spectrum_like_type)) 66 | 67 | if type(spectrum_like_type) is ImportError: 68 | pytest.xfail("The %s class could not be imported; you may be missing ipyparallel." % str(spectrum_like_type)) 69 | 70 | if em_length is not None: 71 | emission_measure = container_type(np.linspace(1e16, 2e16, temperature_length)) 72 | else: 73 | emission_measure = None 74 | 75 | temperature = container_type(np.linspace(1e6, 2e6, temperature_length)) 76 | density = container_type(np.linspace(1e9, 2e9, density_length)) 77 | 78 | wavelength = np.linspace(200, 400) # Just a few wavelengths. 79 | 80 | _tmp_spec = spectrum_like_type(temperature, density, wavelength, em=emission_measure, minAbund=1e-4) 81 | 82 | 83 | # This tests that scalar values are also acceptable for density, temperature, and emission measure. 84 | @pytest.mark.parametrize("spectrum_like_type", _spectrum_like_type) 85 | @pytest.mark.parametrize("container_type", _container_type) 86 | @pytest.mark.parametrize("temperature_length", _array_lengths) 87 | @pytest.mark.parametrize("density_length", _array_lengths) 88 | #@pytest.mark.parametrize("em_length", _array_lengths + (None,)) 89 | # change by kpd 2020-feb-1 90 | @pytest.mark.parametrize("em_length", _array_lengths) 91 | def test_spectrum_container_scalar_compatibility(spectrum_like_type, container_type, 92 | temperature_length, density_length, em_length): 93 | if spectrum_like_type is mspectrum and platform.system() == 'Darwin': 94 | pytest.xfail("The %s class fails when running on MacOS." % str(spectrum_like_type)) 95 | 96 | if type(spectrum_like_type) is ImportError: 97 | pytest.xfail("The %s class could not be imported; you may be missing ipyparallel." % str(spectrum_like_type)) 98 | 99 | # if em_length is not None: 100 | ## emission_measure = container_type(np.linspace(1e16, 2e16, density_length)) 101 | # # change by kpd 2020-feb-1 102 | # emission_measure = container_type(np.ones(density_length)) 103 | # else: 104 | # emission_measure = None 105 | 106 | temperature = container_type(np.linspace(1e6, 2e6, temperature_length)) 107 | density = container_type(np.linspace(1e9, 2e9, density_length)) 108 | wavelength = np.linspace(200, 400) # Just a few wavelengths.min(array_lengths) 109 | 110 | # Temperature is scalar 111 | # kpd 2020-feb-1 112 | emission_measure = np.ones(min(_array_lengths)) 113 | print('113 temperature_length %5i'%(temperature_length)) 114 | _tmp_spec = spectrum_like_type(1e6, density, wavelength, em=emission_measure, minAbund=1e-4) 115 | 116 | # Density is scalar 117 | # kpd 2020-feb-1 118 | emission_measure = np.ones(min(_array_lengths)) 119 | print('119 density_length %5i'%(density_length)) 120 | _tmp_spec = spectrum_like_type(temperature, 1e9, wavelength, em=emission_measure, minAbund=1e-4) 121 | 122 | # Emission measure is scalar 123 | _tmp_spec = spectrum_like_type(temperature, density, wavelength, em=1e16, minAbund=1e-4) 124 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/COPYING.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Brendan Arnold 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/FortranRecordReader.py: -------------------------------------------------------------------------------- 1 | import sys 2 | IS_PYTHON3 = sys.version_info[0] >= 3 3 | 4 | if IS_PYTHON3: 5 | exec('from ._input import input as _input') 6 | exec('from ._parser import parser as _parser') 7 | exec('from ._lexer import lexer as _lexer') 8 | else: 9 | exec('from _input import input as _input') 10 | exec('from _parser import parser as _parser') 11 | exec('from _lexer import lexer as _lexer') 12 | 13 | class FortranRecordReader(object): 14 | ''' 15 | Generate a reader object for FORTRAN format strings 16 | 17 | Typical use case ... 18 | 19 | >>> header_line = FortranRecordReader('(A15, A15, A15)') 20 | >>> header_line.read(' x y z') 21 | [' x', ' y', ' z'] 22 | >>> line = FortranRecordReader('(3F15.3)') 23 | >>> line.read(' 1.000 0.000 0.500') 24 | [1.0, 0.0, 0.5] 25 | >>> line.read(' 1.100 0.100 0.600') 26 | [1.1, 0.1, 0.6] 27 | 28 | Note: it is best to create a new object for each format, changing the format 29 | causes the parser to reevalute the format string which is costly in terms of 30 | performance 31 | ''' 32 | 33 | def __init__(self, format): 34 | self.format = format 35 | self._eds = [] 36 | self._rev_eds = [] 37 | self._parse_format() 38 | 39 | def __eq__(self, other): 40 | if isinstance(other, FortranRecordReader): 41 | return self.format == other.format 42 | else: 43 | return object.__eq__(self, other) 44 | 45 | def match(self, record): 46 | try: 47 | self.read(record) 48 | except RecordError: 49 | return False 50 | else: 51 | return True 52 | 53 | def read(self, record): 54 | ''' 55 | Pass a string representing a FORTRAN record to obtain the relevent 56 | values 57 | ''' 58 | return _input(self._eds, self._rev_eds, record) 59 | 60 | def get_format(self): 61 | return self._format 62 | def set_format(self, format): 63 | self._format = format 64 | self._parse_format() 65 | format = property(get_format, set_format) 66 | 67 | def _parse_format(self): 68 | self._eds, self._rev_eds = _parser(_lexer(self.format)) 69 | 70 | 71 | if __name__ == '__main__': 72 | import doctest 73 | doctest.testmod() 74 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/FortranRecordWriter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | IS_PYTHON3 = sys.version_info[0] >= 3 3 | 4 | if IS_PYTHON3: 5 | exec('from ._output import output as _output') 6 | exec('from ._lexer import lexer as _lexer') 7 | exec('from ._parser import parser as _parser') 8 | else: 9 | exec('from _output import output as _output') 10 | exec('from _lexer import lexer as _lexer') 11 | exec('from _parser import parser as _parser') 12 | 13 | class FortranRecordWriter(object): 14 | ''' 15 | Generate a writer object for FORTRAN format strings 16 | 17 | Typical use case ... 18 | 19 | >>> header_line = FortranRecordWriter('(A15, A15, A15)') 20 | >>> header_line.write(['x', 'y', 'z']) 21 | ' x y z' 22 | >>> line = FortranRecordWriter('(3F15.3)') 23 | >>> line.write([1.0, 0.0, 0.5]) 24 | ' 1.000 0.000 0.500' 25 | >>> line.write([1.1, 0.1, 0.6]) 26 | ' 1.100 0.100 0.600' 27 | 28 | Note: it is best to create a new object for each format, changing the format 29 | causes the parser to reevalute the format string which is costly in terms of 30 | performance 31 | ''' 32 | def __init__(self, format): 33 | self._eds = [] 34 | self._rev_eds = [] 35 | self.format = format 36 | 37 | def __eq__(self, other): 38 | if isinstance(other, FortranRecordWriter): 39 | return self.format == other.format 40 | else: 41 | return object.__eq__(self, other) 42 | 43 | def write(self, values): 44 | ''' 45 | Pass a list of values correspoding to the FORTRAN format specified 46 | to generate a string 47 | ''' 48 | return _output(self._eds, self._rev_eds, values) 49 | 50 | def get_format(self): 51 | return self._format 52 | 53 | def set_format(self, format): 54 | self._format = format 55 | self._parse_format() 56 | 57 | format = property(get_format, set_format) 58 | 59 | def _parse_format(self): 60 | self._eds, self._rev_eds = _parser(_lexer(self.format)) 61 | 62 | 63 | if __name__ == '__main__': 64 | import doctest 65 | doctest.testmod() 66 | 67 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.2.5' 2 | 3 | import sys 4 | IS_PYTHON3 = sys.version_info[0] >= 3 5 | 6 | if IS_PYTHON3: 7 | exec('from .FortranRecordReader import FortranRecordReader') 8 | exec('from .FortranRecordWriter import FortranRecordWriter') 9 | exec('from . import config') 10 | else: 11 | exec('from FortranRecordReader import FortranRecordReader') 12 | exec('from FortranRecordWriter import FortranRecordWriter') 13 | import config 14 | # exec('import config') 15 | # exec('from . import config') 16 | 17 | 18 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/_edit_descriptors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | IS_PYTHON3 = sys.version_info[0] >= 3 3 | 4 | if IS_PYTHON3: 5 | exec('from ._exceptions import *') 6 | else: 7 | exec('from _exceptions import *') 8 | 9 | 10 | def get_edit_descriptor_obj(name): 11 | '''Returns a new object instance from a string''' 12 | name = name.upper() 13 | if name == 'A': 14 | return A() 15 | elif name == 'B': 16 | return B() 17 | elif name == 'BN': 18 | return BN() 19 | elif name == 'BZ': 20 | return BZ() 21 | elif name == ':': 22 | return Colon() 23 | elif name == 'D': 24 | return D() 25 | elif name == 'E': 26 | return E() 27 | elif name == 'EN': 28 | return EN() 29 | elif name == 'ES': 30 | return ES() 31 | elif name == 'F': 32 | return F() 33 | elif name == 'G': 34 | return G() 35 | elif name == 'H': 36 | return H() 37 | elif name == 'I': 38 | return I() 39 | elif name == 'L': 40 | return L() 41 | elif name == 'O': 42 | return O() 43 | elif name == 'P': 44 | return P() 45 | elif name =='S': 46 | return S() 47 | elif name == '/': 48 | return Slash() 49 | elif name == 'SP': 50 | return SP() 51 | elif name == 'SS': 52 | return SS() 53 | elif name == 'T': 54 | return T() 55 | elif name == 'TL': 56 | return TL() 57 | elif name == 'TR': 58 | return TR() 59 | elif name == 'X': 60 | return X() 61 | elif name == 'Z': 62 | return Z() 63 | else: 64 | raise InvalidFormat('Expected an edit descriptor, got %s' % name) 65 | 66 | # All the tokens defined in the F77 specification unless specified 67 | 68 | class A(object): 69 | def __init__(self): 70 | self.repeat = None 71 | self.width = None 72 | def __repr__(self): 73 | return '' 75 | 76 | class QuotedString(object): 77 | def __init__(self, char_string=None): 78 | self.char_string = char_string 79 | def get_width(self): 80 | return len(self.char_string) 81 | width = property(get_width) 82 | def __repr__(self): 83 | return '' 84 | 85 | # Only in F95 86 | class B(object): 87 | def __init__(self): 88 | self.repeat = None 89 | self.width = None 90 | self.min_digits = None 91 | def __repr__(self): 92 | return '' 95 | 96 | class BN(object): 97 | def __init__(self): 98 | pass 99 | def __repr__(self): 100 | return '' 101 | 102 | class BZ(object): 103 | def __init__(self): 104 | pass 105 | def __repr__(self): 106 | return '' 107 | 108 | class Colon(object): 109 | def __init__(self): 110 | pass 111 | def __repr__(self): 112 | return '' 113 | 114 | class D(object): 115 | def __init__(self): 116 | self.repeat = None 117 | self.width = None 118 | self.decimal_places = None 119 | def __repr__(self): 120 | return '' 123 | 124 | class E(object): 125 | def __init__(self): 126 | self.repeat = None 127 | self.width = None 128 | self.decimal_places = None 129 | self.exponent = None 130 | def __repr__(self): 131 | return '' 135 | 136 | # Only in F95 137 | class EN(object): 138 | def __init__(self): 139 | self.repeat = None 140 | self.width = None 141 | self.decimal_places = None 142 | self.exponent = None 143 | def __repr__(self): 144 | return '' 148 | 149 | # Only in F95 150 | class ES(object): 151 | def __init__(self): 152 | self.repeat = None 153 | self.width = None 154 | self.decimal_places = None 155 | self.exponent = None 156 | def __repr__(self): 157 | return '' 161 | 162 | class F(object): 163 | def __init__(self): 164 | self.repeat = None 165 | self.width = None 166 | self.decimal_places = None 167 | def __repr__(self): 168 | return '' 171 | 172 | class FormatGroup(object): 173 | pass 174 | 175 | class G(object): 176 | def __init__(self): 177 | self.repeat = None 178 | self.width = None 179 | self.decimal_places = None 180 | self.exponent = None 181 | def __repr__(self): 182 | return '' 186 | 187 | # Only in F77 188 | class H(object): 189 | def __init__(self): 190 | self.num_chars = None 191 | self.char_string = None 192 | def __repr__(self): 193 | return '' 195 | 196 | class I(object): 197 | def __init__(self): 198 | self.repeat = None 199 | self.width = None 200 | self.min_digits = None 201 | def __repr__(self): 202 | return '' 205 | 206 | class L(object): 207 | def __init__(self): 208 | self.repeat = None 209 | self.width = None 210 | def __repr__(self): 211 | return '' 213 | 214 | # Only in F95 215 | class O(object): 216 | def __init__(self): 217 | self.repeat = None 218 | self.width = None 219 | self.min_digits = None 220 | def __repr__(self): 221 | return '' 224 | 225 | class P(object): 226 | def __init__(self): 227 | self.scale = None 228 | def __repr__(self): 229 | return '

' 230 | 231 | class S(object): 232 | def __init__(self): 233 | pass 234 | def __repr__(self): 235 | return '' 236 | 237 | class Slash(object): 238 | def __init__(self): 239 | self.repeat = None 240 | pass 241 | def __repr__(self): 242 | return '' 243 | 244 | class SP(object): 245 | def __init__(self): 246 | pass 247 | def __repr__(self): 248 | return '' 249 | 250 | class SS(object): 251 | def __init__(self): 252 | pass 253 | def __repr__(self): 254 | return '' 255 | 256 | class T(object): 257 | def __init__(self): 258 | self.num_chars = None 259 | def __repr__(self): 260 | return '' 261 | 262 | class TL(object): 263 | def __init__(self): 264 | self.num_chars = None 265 | def __repr__(self): 266 | return '' 267 | 268 | class TR(object): 269 | def __init__(self): 270 | self.num_chars = None 271 | def __repr__(self): 272 | return '' 273 | 274 | class X(object): 275 | def __init__(self): 276 | self.num_chars = None 277 | def __repr__(self): 278 | return '' 279 | 280 | # Only in F95 281 | class Z(object): 282 | def __init__(self): 283 | self.repeat = None 284 | self.width = None 285 | self.min_digits = None 286 | def __repr__(self): 287 | return '' 290 | 291 | # Categorise the edit descriptors depnding on how they should be parsed 292 | 293 | ED1 = ['BN', 'BZ', 'SP', 'SS', 'S'] # Of form X only 294 | ED2 = ['X'] # Of form nX only 295 | ED3 = ['T', 'TR', 'TL', 'L'] # Of form Xn only 296 | ED4 = ['A'] # Of form X or Xn 297 | ED5 = ['D', 'F'] # Of form Xn.m only 298 | ED6 = ['B', 'I', 'O', 'Z'] # Of form Xn or Xn.m 299 | ED7 = ['E', 'EN', 'ES', 'G'] # Of form Xn.m or Xn.mEe 300 | ED8 = ['P'] # Of form kX only, where k is a signed integer, may omit comma if followed by Type 5 or 7 edit descriptor 301 | ED9 = [':'] # Of form X only, may omit comma either side 302 | ED10 = ['/'] # Of form X only, may omit following comma and leading comma if no repeat 303 | REPEATABLE_EDS = ['L', 'A', 'D', 'F', 'B', 'I', 'O', 'Z', 'E', 'EN', 'ES', 'G', '/'] 304 | OUTPUT_EDS = (L, A, D, F, B, I, O, Z, E, EN, ES, G) 305 | CONTROL_EDS = (BN, BZ, P, SP, SS, S, X, T, TR, TL, Colon, Slash) 306 | NON_REVERSION_EDS = (P, S, SP, SS, BN, BZ) 307 | ALL_ED = ED1 + ED2 + ED3 + ED4 + ED5 + ED6 + ED7 + ED8 + ED9 + ED10 308 | 309 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/_exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | class InvalidFormat(Exception): 3 | pass 4 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/_lexer.py: -------------------------------------------------------------------------------- 1 | import sys 2 | IS_PYTHON3 = sys.version_info[0] >= 3 3 | 4 | if IS_PYTHON3: 5 | exec('from ._edit_descriptors import *') 6 | exec('from ._exceptions import *') 7 | else: 8 | exec('from _edit_descriptors import *') 9 | exec('from _exceptions import *') 10 | 11 | # Some lexer tokens to look out for 12 | DIGITS = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] 13 | SIGNS = ['+', '-'] 14 | COMMA = [','] 15 | DOT = ['.'] 16 | WHITESPACE = [' ', '\t', '\n'] 17 | QUOTE_CHARS = ['"', "'"] 18 | DOUBLE_EDIT_DESCRIPTORS = ['EN', 'ES', 'TR', 'TL', 'BN', 'BZ', 'SP', 'SS'] 19 | SINGLE_EDIT_DESCRIPTORS = ['A', 'B', 'D', 'E', 'F', 'G', 'I', 'L', 'O', 'P', 'S', 'T', 'X', 'Z', ':', '/'] 20 | H_EDIT_DESCRIPTOR = ['H'] 21 | LEFT_PARENS = ['('] 22 | RIGHT_PARENS = [')'] 23 | COLON = ':' 24 | SLASH = '/' 25 | 26 | 27 | def lexer(format): 28 | '''Lex the FORTRAN format statement into tokens''' 29 | tokens = [] 30 | s = -1 31 | h_chars = None 32 | while True: 33 | # Get the next set of characters 34 | s = s + 1 35 | c0, c1, c2 = _get_chars(format, s) 36 | # If at end of format, end it all - aieee! 37 | if c0 is None: 38 | break 39 | # Read in an H edit descriptor string 40 | elif h_chars is not None: 41 | buff = format[s:s+h_chars] 42 | tokens.append(Token('QUOTED_STRING', buff)) 43 | s = s + (h_chars - 1) 44 | h_chars = None 45 | # Skip whitespace 46 | elif c0 in WHITESPACE: 47 | continue 48 | # Read in a quoted string 49 | elif c0 in QUOTE_CHARS: 50 | buff = '' 51 | delim = c0 52 | while True: 53 | s = s + 1 54 | c0, c1, c2 = _get_chars(format, s) 55 | # Check if an escaped delimiter 56 | if (c0 == delim) and (c1 == delim): 57 | s = s + 1 58 | buff = buff + delim 59 | elif (c0 == delim): 60 | break 61 | elif c0 is None: 62 | # Premature end of format 63 | raise InvalidFormat('Premature end of quoted string in format') 64 | else: 65 | buff = buff + c0 66 | tokens.append(Token('QUOTED_STRING', buff)) 67 | # Read in an integer 68 | elif c0 in DIGITS + SIGNS: 69 | # Check sign followed by at least one digit 70 | if (c0 in SIGNS) and (c1 not in DIGITS): 71 | # TODO: Is whitesapce allowed between sign and digit? 72 | raise InvalidFormat("Orphaned sign '%s' with no digits at position %d" % (c0, s)) 73 | buff = c0 74 | while True: 75 | s = s + 1 76 | c0, c1, c2 = _get_chars(format, s) 77 | if (c0 not in DIGITS) or (c0 is None): 78 | break 79 | else: 80 | buff = buff + c0 81 | s = s - 1 82 | val = int(buff) 83 | if buff[0] in SIGNS: 84 | tokens.append(Token('INT', val)) 85 | elif val == 0: 86 | tokens.append(Token('UINT', val)) 87 | else: 88 | tokens.append(Token('NZUINT', val)) 89 | # Read in a comma 90 | elif c0 in COMMA: 91 | tokens.append(Token('COMMA', None)) 92 | # Read in a dot 93 | elif c0 in DOT: 94 | tokens.append(Token('DOT', None)) 95 | # Read in double lettered edit descriptors 96 | elif (c1 is not None) and ((c0 + c1).upper() in DOUBLE_EDIT_DESCRIPTORS): 97 | ed_type = _get_ed_type((c0 + c1).upper()) 98 | tokens.append(Token(ed_type, (c0 + c1).upper())) 99 | s = s + 1 100 | # Read in an H edit descriptor 101 | elif c0.upper() in H_EDIT_DESCRIPTOR: 102 | if (len(tokens) > 0) and (tokens[-1].type in ('NZUINT', 'UINT')): 103 | h_chars = tokens[-1].value 104 | tokens = tokens[:-1] 105 | else: 106 | raise InvalidFormat("Missing H descriptor number argument at position %d" % s) 107 | # Read in single lettered edit descriptors 108 | elif c0.upper() in SINGLE_EDIT_DESCRIPTORS: 109 | ed_type = _get_ed_type(c0.upper()) 110 | tokens.append(Token(ed_type, c0.upper())) 111 | # Read in left parens 112 | elif c0 in LEFT_PARENS: 113 | tokens.append(Token('LEFT_PARENS', None)) 114 | # Read in right parens 115 | elif c0 in RIGHT_PARENS: 116 | tokens.append(Token('RIGHT_PARENS', None)) 117 | else: 118 | raise InvalidFormat('Character %s not recognised at position %d' % (c0, s)) 119 | return tokens 120 | 121 | def _get_ed_type(ed_string): 122 | if ed_string in ED1: 123 | ed_type = 'ED1' 124 | elif ed_string in ED2: 125 | ed_type = 'ED2' 126 | elif ed_string in ED3: 127 | ed_type = 'ED3' 128 | elif ed_string in ED4: 129 | ed_type = 'ED4' 130 | elif ed_string in ED5: 131 | ed_type = 'ED5' 132 | elif ed_string in ED6: 133 | ed_type = 'ED6' 134 | elif ed_string in ED7: 135 | ed_type = 'ED7' 136 | elif ed_string in ED8: 137 | ed_type = 'ED8' 138 | elif ed_string in ED9: 139 | ed_type = 'ED9' 140 | elif ed_string in ED10: 141 | ed_type = 'ED10' 142 | else: 143 | ed_type = None 144 | return ed_type 145 | 146 | def _get_chars(format, s): 147 | try: 148 | c0 = format[s] 149 | except IndexError: 150 | c0 = None 151 | try: 152 | c1 = format[s+1] 153 | except IndexError: 154 | c1 = None 155 | try: 156 | c2 = format[s+2] 157 | except IndexError: 158 | c2 = None 159 | return (c0, c1, c2) 160 | 161 | 162 | class InvalidFormat(Exception): 163 | def __init__(self, value): 164 | self.value = value 165 | def __str__(self): 166 | return repr(self.value) 167 | 168 | 169 | class Token(object): 170 | def __init__(self, type, value): 171 | self.type = type 172 | self.value = value 173 | def __repr__(self): 174 | return "\n Token: type=%s,\tvalue=%s" % (self.type, str(self.value)) 175 | 176 | # Do some testing when run as a module 177 | 178 | #if __name__ == '__main__': 179 | # import doctest 180 | # import os 181 | # globs = {'lexer' : lexer} 182 | # # Need to normalize whitespace since pasting into VIM converts tabs to 183 | # # spaces 184 | # doctest.testfile(os.path.join('tests', 'lexer_test.txt'), \ 185 | # globs=globs, optionflags=doctest.NORMALIZE_WHITESPACE) 186 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/_misc.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Miscellaneous functions, classes etc 3 | ''' 4 | import sys 5 | IS_PYTHON3 = sys.version_info[0] >= 3 6 | 7 | class has_next_iterator(object): 8 | ''' 9 | A wrapper class for iterators so that the .has_next() method is implemented 10 | 11 | See - http://stackoverflow.com/questions/1966591/hasnext-in-python-iterators 12 | ''' 13 | def __init__(self, it): 14 | self.it = iter(it) 15 | self._has_next = None 16 | def __iter__(self): return self 17 | def __next__(self): 18 | if self._has_next: 19 | result = self._the_next 20 | else: 21 | if IS_PYTHON3: 22 | result = next(self.it) 23 | else: 24 | result = self.it.next() 25 | self._has_next = None 26 | return result 27 | def next(self): 28 | if self._has_next: 29 | result = self._the_next 30 | else: 31 | if IS_PYTHON3: 32 | result = next(self.it) 33 | else: 34 | result = self.it.next() 35 | self._has_next = None 36 | return result 37 | def has_next(self): 38 | if self._has_next is None: 39 | try: 40 | if IS_PYTHON3: 41 | self._the_next = next(self.it) 42 | else: 43 | self._the_next = self.it.next() 44 | except StopIteration: self._has_next = False 45 | else: self._has_next = True 46 | return self._has_next 47 | 48 | 49 | def expand_edit_descriptors(eds): 50 | expanded_eds = [] 51 | for ed in eds: 52 | if hasattr(ed, 'repeat') and (ed.repeat is not None): 53 | expanded_eds.extend(ed.repeat * [ed]) 54 | else: 55 | expanded_eds.append(ed) 56 | return expanded_eds 57 | -------------------------------------------------------------------------------- /ChiantiPy/fortranformat/config.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # Should all edit descriptor values be returned even if they were not 4 | # written to? 5 | RET_WRITTEN_VARS_ONLY = False 6 | # Should 'None' values be returned when no record is available to read 7 | # from or the FORTRAN 'default'? 8 | RET_UNWRITTEN_VARS_NONE = True 9 | # The order in which edit desciptors are tried by default when G edit 10 | # descriptor encountered on input 11 | G_INPUT_TRIAL_EDS = ['F', 'L', 'A'] 12 | # Contrary to specification, many compilers allow zero width edit 13 | # descriptors 14 | ALLOW_ZERO_WIDTH_EDS = True 15 | # Set the characters that separate the records 16 | RECORD_SEPARATOR = '\n' 17 | 18 | # The maximum size for an integer 19 | if sys.version_info[0] >= 3: 20 | PROC_MAXINT = sys.maxsize 21 | else: 22 | PROC_MAXINT = sys.maxint 23 | # Processor dependant default for including leading plus or not 24 | PROC_INCL_PLUS = False 25 | # Option to allow signed binary, octal and hex on input (not a FORTRAN feature) 26 | PROC_ALLOW_NEG_BOZ = False 27 | # Prcessor dependant padding character 28 | PROC_PAD_CHAR = ' ' 29 | # Interpret blanks or jsut a negative as a zero, as in ifort behaviour 30 | PROC_NEG_AS_ZERO = True 31 | # Show a sign for zero? 32 | PROC_SIGN_ZERO = False 33 | PROC_MIN_FIELD_WIDTH = 46 34 | PROC_DECIMAL_CHAR = '.' 35 | G0_NO_BLANKS = False 36 | PROC_NO_LEADING_BLANK = False 37 | # The default value if BN, BZ edit descriptors are not specified 38 | PROC_BLANKS_AS_ZEROS = False 39 | 40 | def reset(): 41 | global RET_WRITTEN_VARS_ONLY, RET_UNWRITTEN_VARS_NONE, PROC_INCL_PLUS, \ 42 | PROC_ALLOW_NEG_BOZ, PROC_PAD_CHAR, PROC_NEG_AS_ZERO, PROC_SIGN_ZERO, \ 43 | PROC_MIN_FIELD_WIDTH, PROC_DECIMAL_CHAR, G0_NO_BLANKS, \ 44 | PROC_NO_LEADING_BLANK, PROC_BLANKS_AS_ZEROS, PROC_MAXINT, G_INPUT_TRIAL_EDS, \ 45 | ALLOW_ZERO_WIDTH_EDS 46 | G_INPUT_TRIAL_EDS = ['F', 'L', 'A'] 47 | if sys.version_info[0] >= 3: 48 | PROC_MAXINT = sys.maxsize 49 | else: 50 | PROC_MAXINT = sys.maxint 51 | RET_WRITTEN_VARS_ONLY = False 52 | RET_UNWRITTEN_VARS_NONE = True 53 | PROC_INCL_PLUS = False 54 | PROC_ALLOW_NEG_BOZ = False 55 | PROC_PAD_CHAR = ' ' 56 | PROC_NEG_AS_ZERO = True 57 | PROC_SIGN_ZERO = False 58 | PROC_MIN_FIELD_WIDTH = 46 59 | PROC_DECIMAL_CHAR = '.' 60 | G0_NO_BLANKS = False 61 | PROC_NO_LEADING_BLANK = False 62 | PROC_BLANKS_AS_ZEROS = False 63 | ALLOW_ZERO_WIDTH_EDS = True 64 | -------------------------------------------------------------------------------- /ChiantiPy/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/ChiantiPy/model/__init__.py -------------------------------------------------------------------------------- /ChiantiPy/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | """ 3 | This packages contains affiliated package tests. 4 | """ 5 | -------------------------------------------------------------------------------- /ChiantiPy/tests/coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = ChiantiPy 3 | omit = 4 | ChiantiPy/_astropy_init* 5 | ChiantiPy/conftest* 6 | ChiantiPy/*setup_package* 7 | ChiantiPy/*tests/* 8 | ChiantiPy/version* 9 | 10 | [report] 11 | exclude_lines = 12 | # Have to re-enable the standard pragma 13 | pragma: no cover 14 | 15 | # Don't complain about packages we have installed 16 | except ImportError 17 | 18 | # Don't complain if tests don't hit assertions 19 | raise AssertionError 20 | raise NotImplementedError 21 | 22 | # Don't complain about script hooks 23 | def main\(.*\): 24 | 25 | # Ignore branches that don't pertain to this version of Python 26 | pragma: py{ignore_python_version} 27 | -------------------------------------------------------------------------------- /ChiantiPy/tests/setup_package.py: -------------------------------------------------------------------------------- 1 | def get_package_data(): 2 | return { 3 | _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} 4 | -------------------------------------------------------------------------------- /ChiantiPy/tools/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Basic tools and utilities used in ChiantiPy 3 | """ 4 | -------------------------------------------------------------------------------- /ChiantiPy/tools/archival.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions for reading pre-v8 CHIANTI files 3 | """ 4 | 5 | import os 6 | 7 | #from .FortranFormat import * 8 | from ChiantiPy.fortranformat import FortranRecordReader 9 | import ChiantiPy.tools.util as util 10 | # 11 | # ------------------------------------------------------------------------------------- 12 | # 13 | def elvlcRead(ions, filename = 0, verbose=0, useTh=0): 14 | """ 15 | read a chianti energy level file and returns 16 | {"lvl":lvl,"conf":conf,"term":term,"spin":spin,"l":l,"spd":spd,"j":j 17 | ,"mult":mult,"ecm":ecm,"eryd":eryd,"ecmth":ecmth,"erydth":erydth,"ref":ref,"pretty":pretty, 'ionS':ions} 18 | if a energy value for ecm or eryd is zero(=unknown), the theoretical values 19 | (ecmth and erydth) are inserted 20 | """ 21 | # 22 | # (i3,i6,a15,2i3,a3,f4.1,i3,f15.3,f15.6,f15.3,f15.6,f15.3,f15.6) 23 | # fstring='i3,i6,a15,i3,i3,a3,f4.1,i3,4f15.2' 24 | # elvlcFormat=FortranFormat(fstring) 25 | # header_line = FortranRecordReader('i3,i6,a15,i3,i3,a3,i3,f4.1,f15.3,f15.6,f15.3,f15.6') 26 | header_line = FortranRecordReader('i3,i6,a15,i3,i3,a3,f4.1,i3,f15.3,f15.6,f15.3,f15.6') #',f4.1') 27 | 28 | # 29 | if filename: 30 | elvlname = filename 31 | bname = os.path.basename(filename) 32 | ions = bname.split('.')[0] 33 | else: 34 | fname = util.ion2filename(ions) 35 | elvlname = fname+'.elvlc' 36 | if not os.path.isfile(elvlname): 37 | print((' elvlc file does not exist: %s'%(elvlname))) 38 | return {'status':0} 39 | status = 1 40 | input = open(elvlname,'r') 41 | s1 = input.readlines() 42 | input.close() 43 | nlvls = 0 44 | ndata = 2 45 | while ndata > 1: 46 | s1a = s1[nlvls][:-1] 47 | s2 = s1a.split() 48 | ndata = len(s2) 49 | nlvls = nlvls+1 50 | nlvls -= 1 51 | if verbose: 52 | print((' nlvls = %i'%(nlvls))) 53 | lvl = [0]*nlvls 54 | conf = [0]*nlvls 55 | term = [0]*nlvls 56 | spin = [0]*nlvls 57 | l = [0]*nlvls 58 | spd = [0]*nlvls 59 | j = [0]*nlvls 60 | mult = [0]*nlvls 61 | ecm = [0]*nlvls 62 | eryd = [0]*nlvls 63 | ecmth = [0]*nlvls 64 | erydth = [0]*nlvls 65 | pretty = [0]*nlvls 66 | label = [] 67 | for i in range(0,nlvls): 68 | if verbose: 69 | print((s1[i][0:115])) 70 | # inpt = FortranLine(s1[i][0:115],elvlcFormat) 71 | inpt = header_line.read(s1[i]) 72 | lvl[i] = inpt[0] 73 | conf[i] = inpt[1] 74 | label.append(str(inpt[1])) 75 | term[i] = inpt[2].strip() 76 | spin[i] = inpt[3] 77 | l[i] = inpt[4] 78 | spd[i] = inpt[5].strip() 79 | j[i] = inpt[6] 80 | mult[i] = inpt[7] 81 | ecm[i] = inpt[8] 82 | eryd[i] = inpt[9] 83 | ecmth[i] = inpt[10] 84 | erydth[i] = inpt[11] 85 | if ecm[i] == 0.: 86 | if useTh: 87 | ecm[i] = ecmth[i] 88 | eryd[i] = erydth[i] 89 | stuff = term[i].strip() + ' %1i%1s%3.1f'%( spin[i], spd[i], j[i]) 90 | pretty[i] = stuff.strip() 91 | ref = [] 92 | for i in range(nlvls+1,len(s1)-1): 93 | s1a = s1[i][:-1] 94 | ref.append(s1a.strip()) 95 | # self.const.Elvlc = {"lvl":lvl,"conf":conf,"term":term,"spin":spin,"l":l,"spd":spd,"j":j 96 | # ,"mult":mult,"ecm":ecm,"eryd":eryd,"ecmth":ecmth,"erydth":erydth,"ref":ref} 97 | return {"lvl":lvl,"conf":conf,"label":label,"term":term,"spin":spin,"l":l,"spd":spd,"j":j 98 | ,"mult":mult,"ecm":ecm,"eryd":eryd,"ecmth":ecmth,"erydth":erydth,"ref":ref,"pretty":pretty, 'ionS':ions, 'status':status} 99 | # 100 | # ------------------------------------------------------------------------------------- 101 | # 102 | def elvlcWrite(info, outfile=None, addLvl=0): 103 | ''' 104 | Write Chianti data to .elvlc file. 105 | 106 | Parameters 107 | ---------- 108 | info : `dict` 109 | Information about the Chianti data to write. Should contain 110 | the following keys: ionS, the Chianti style name of the ion such as c_4 111 | conf, an integer denoting the configuration - not too essential 112 | term, a string showing the configuration 113 | spin, an integer of the spin of the state in LS coupling 114 | l, an integer of the angular momentum quantum number 115 | spd, an string for the alphabetic symbol of the angular momemtum, S, P, D, etc 116 | j, a floating point number, the total angular momentum 117 | ecm, the observed energy in inverse cm, if unknown, the value is 0. 118 | eryd, the observed energy in Rydbergs, if unknown, the value is 0. 119 | ecmth, the calculated energy from the scattering calculation, in inverse cm 120 | erydth, the calculated energy from the scattering calculation in Rydbergs 121 | ref, the references in the literature to the data in the input info 122 | outfile : `str` 123 | Output filename. ionS+'.elvlc' (in current directory) if None 124 | addLvl : `int` 125 | Add a constant value to the index of all levels 126 | 127 | Notes 128 | ----- 129 | For use with files created before elvlc format change in November 2012 130 | 131 | See Also 132 | -------- 133 | ChiantiPy.tools.io.elvlcWrite : Write .elvlc file using the new format. 134 | ''' 135 | if outfile: 136 | elvlcName = outfile 137 | else: 138 | elvlcName = info['ionS'] + '.elvlc' 139 | print((' elvlc file name = %s'%(elvlcName))) 140 | out = open(elvlcName, 'w') 141 | for i, conf in enumerate(info['conf']): 142 | mult = int(2.*info['j'][i]+1.) 143 | thisTerm = info['term'][i].ljust(14) 144 | pstring = '%3i%6s%15s%3i%3i%2s%5.1f%3i%15.3f%15.6f%15.3f%15.6f \n'%(i+1+addLvl, conf, thisTerm, info['spin'][i], info['l'][i], info['spd'][i], info['j'][i], mult, info['ecm'][i], info['eryd'][i], info['ecmth'][i], info['erydth'][i]) 145 | #i3,a6,a15,2i3,a2,f5.1,i3,f15.3,f15.6,f15.3,f15.6 146 | out.write(pstring) 147 | out.write(' -1\n') 148 | out.write('%filename: ' + elvlcName + '\n') 149 | for one in info['ref']: 150 | out.write(one+'\n') 151 | out.write(' -1\n') 152 | out.close() 153 | 154 | def wgfaRead(ions, filename=None, elvlcname=-1, total=False, verbose=False): 155 | """ 156 | Read CHIANTI data from a .wgfa file. 157 | 158 | Parameters 159 | ---------- 160 | ions : `str` 161 | Ion, e.g. 'c_5' for C V 162 | filename : `str` 163 | Custom filename, will override that specified by `ions` 164 | elvlcname : `str` 165 | If specified, the lsj term labels are returned in the `pretty1` and `pretty2` keys of `Wgfa` 166 | total : `bool` 167 | Return the level 2 avalue data in `Wgfa` 168 | verbose : `bool` 169 | 170 | Returns 171 | ------- 172 | Wgfa : `dict` 173 | Information read from the .wgfa file. The dictionary structure is {"lvl1","lvl2","wvl","gf","avalue","ref","ionS","filename"} 174 | 175 | Notes 176 | ----- 177 | This is text-wise not different than the v8 version except that it uses the 178 | archival elvlcRead in `~ChiantiPy.tools.archival` though this has now been commented out. Can this routine be removed? Should the elvlcRead routine be uncommented? 179 | 180 | See Also 181 | -------- 182 | ChiantiPy.tools.io.wgfaRead : Read .wgfa file with the new format. 183 | """ 184 | # 185 | if filename: 186 | wgfaname = filename 187 | if elvlcname < 0: 188 | elvlcname = 0 189 | elvlc = 0 190 | elif not elvlcname: 191 | elvlcname = os.path.splitext(wgfaname)[0] + '.elvlc' 192 | if os.path.isfile(elvlcname): 193 | elvlc = elvlcRead('', elvlcname) 194 | else: 195 | elvlc = 0 196 | else: 197 | elvlc = elvlcRead('',elvlcname) 198 | 199 | else: 200 | fname=util.ion2filename(ions) 201 | wgfaname=fname+'.wgfa' 202 | elvlcname = fname + '.elvlc' 203 | if os.path.isfile(elvlcname): 204 | elvlc = elvlcRead('', elvlcname) 205 | else: 206 | elvlc = 0 207 | if verbose: 208 | if elvlc: 209 | print(' have elvlc data') 210 | else: 211 | print(' do not have elvlc data') 212 | # 213 | input=open(wgfaname,'r') 214 | s1=input.readlines() 215 | input.close() 216 | nwvl=0 217 | ndata=2 218 | while ndata > 1: 219 | s1a=s1[nwvl] 220 | s2=s1a.split() 221 | ndata=len(s2) 222 | nwvl += 1 223 | nwvl -= 1 224 | if verbose: 225 | print(' nwvl = %10i ndata = %4i'%(nwvl, ndata)) 226 | lvl1=[0]*nwvl 227 | lvl2=[0]*nwvl 228 | wvl=[0.]*nwvl 229 | gf=[0.]*nwvl 230 | avalue=[0.]*nwvl 231 | if elvlc: 232 | pretty1 = ['']*nwvl 233 | pretty2 = ['']*nwvl 234 | # 235 | if verbose: 236 | print(' nwvl = %10i'%(nwvl)) 237 | # 238 | wgfaFormat='(2i5,f15.3,2e15.3)' 239 | for ivl in range(nwvl): 240 | inpt=FortranLine(s1[ivl],wgfaFormat) 241 | lvl1[ivl]=inpt[0] 242 | lvl2[ivl]=inpt[1] 243 | wvl[ivl]=inpt[2] 244 | gf[ivl]=inpt[3] 245 | avalue[ivl]=inpt[4] 246 | if elvlc: 247 | pretty1[ivl] = elvlc['pretty'][inpt[0] - 1] 248 | pretty2[ivl] = elvlc['pretty'][inpt[1] - 1] 249 | 250 | ref=[] 251 | # should skip the last '-1' in the file 252 | for i in range(nwvl+1,len(s1) -1): 253 | s1a=s1[i][:-1] 254 | ref.append(s1a.strip()) 255 | Wgfa={"lvl1":lvl1,"lvl2":lvl2,"wvl":wvl,"gf":gf,"avalue":avalue,"ref":ref, 'ionS':ions, 'filename':wgfaname} 256 | if total: 257 | avalueLvl = [0.]*max(lvl2) 258 | for iwvl in range(nwvl): 259 | avalueLvl[lvl2[iwvl] -1] += avalue[iwvl] 260 | Wgfa['avalueLvl'] = avalueLvl 261 | 262 | if elvlc: 263 | Wgfa['pretty1'] = pretty1 264 | Wgfa['pretty2'] = pretty2 265 | # 266 | return Wgfa 267 | # 268 | # -------------------------------------- 269 | # 270 | -------------------------------------------------------------------------------- /ChiantiPy/tools/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | A set of physical constants, in (mostly) cgs unit system. Most are from [11]_. 3 | 4 | 5 | References 6 | ---------- 7 | .. [11] NIST Reference on Constants, Units and Uncertainty (`link `_) 8 | 9 | Notes 10 | ----- 11 | Many of these can be replaced by the `~astropy.constants` module. Elemental symbols can be removed 12 | in favor of the periodictable module. Spectroscopic roman numerals can be removed in favor of roman 13 | module. The Gauss-Laguerre weights can be calculated by `~numpy.polynomial.laguerre.laggauss`. 14 | """ 15 | 16 | import numpy as np 17 | from scipy import special 18 | 19 | planck = 6.6260693e-27 #erg s 20 | planckEv = 4.13566743e-15 # ev s 21 | hbar = planck/(2.*np.pi) 22 | light = 29979245800. # cm/s 23 | q = 4.80320425e-10 # the units of charge 24 | ev2Ang = 12.39841875e+3 25 | kev2Ang = 1.e-3*12.39841875e+3 26 | ev2Erg = 1.602176487e-12 27 | pi = 3.1415926535897931 28 | boltzmann = 1.3806504e-16 # cgs 29 | stefanBoltzmann = 5.670373e-5 # cgs - ergs cm^-2 K^-4 s^-1 30 | boltzmannEv = 8.617343e-5 31 | invCm2Ev = 1./8.06554465e+3 32 | invCm2ryd = 1./109737.32 33 | rydberg = 109737.31568 # cm^-1 34 | rydbergErg = 2.1798723611035e-11 # erg 35 | rydbergEv = 13.6056923 # eV 36 | ryd2Ev = 13.6056923 # 1 rydberg = 13.604 eV 37 | ryd2erg = 2.17987197e-11 #erg 38 | fine = 7.2973525376e-3 # fine structure constant ~ 1./137 = e^2/(h_bar*c) h_bar = h/(2*pi) 39 | emass = 9.10938215e-28 # electron mass in gram 40 | bohr = 0.52917720859e-8 # bohr radius in cm 41 | hartree = 4.35974434e-11 # erg 42 | hartreeEv = 27.21138505 43 | # 44 | # derived constants 45 | hc = planck*light 46 | # 47 | # area of bohr orbit 48 | bohrCross = pi*bohr**2 49 | # 50 | std2fwhm = 2.*np.sqrt(2.*np.log(2.)) 51 | # 52 | invCm2Erg = planck*light 53 | # 54 | boltzmannRyd = boltzmannEv/ryd2Ev 55 | # 56 | # collision produces the 8.63e-6 factor 57 | collision = planck**2/((2.*pi*emass)**1.5*np.sqrt(boltzmann)) 58 | # 59 | # 60 | freeFree = 1.e+8*(light/(3.*emass))*(fine*planck/pi)**3*np.sqrt((2.*pi)/(3.*emass*boltzmann)) 61 | # 62 | sutherland = (2./(3.*np.sqrt(3.)))*np.sqrt(pi/(2.*boltzmann*emass**3))*(planck*fine/pi)**3 63 | # 64 | freeBound = 1.e+8*(8.*fine*(planck**3))/(3.*np.sqrt(3.)*np.pi*(emass**4)*light)*(emass/(2.*np.pi*boltzmann))**1.5 65 | # 66 | freeBounde = 2./(4.*np.pi*planck*boltzmann*light**3*emass*np.sqrt(2.*np.pi*boltzmann*emass)) 67 | # 68 | verner = (1.e-8/(planck*light**3*emass**3))*(emass/(2.*pi*boltzmann))**1.5 69 | 70 | karzas = (2.**4)*planck*q**2/(3.*np.sqrt(3.)*emass*light) 71 | # 72 | freeFreeLoss = (8./3.)*np.sqrt(pi*boltzmann/(6.*emass**3))*(planck/pi)**2*fine**3 73 | # 74 | freeBoundLoss = ((16.*fine*(planck**2))/(3.*pi*np.sqrt(3.)*(emass**3)*(light**2)))*np.sqrt(emass/(2.*pi*boltzmann)) 75 | # 76 | # astronomical 77 | luminositySun = 3.86e+33 # ergs/s 78 | radiusSun = 6.955e+10 # mean radius of Sun in cm 79 | parsec = 3.08568025e+18 # cm 80 | # 81 | El = ['h','he','li','be','b','c','n','o','f','ne','na', \ 82 | 'mg','al','si','p','s','cl','ar','k','ca','sc','ti', \ 83 | 'v','cr','mn','fe','co','ni','cu','zn',\ 84 | 'ga','ge','as','se','br','kr'] 85 | Ionstage = ['I','II','III','IV','V','VI','VII','VIII','IX','X','XI','XII','XIII', \ 86 | 'XIV','XV','XVI','XVII','XVIII','XIX','XX','XXI','XXII','XXIII','XXIV', \ 87 | 'XXV','XXVI','XXVII','XXVIII','XXIX','XXX','XXXI','XXXII','XXXIII','XXXIV', \ 88 | 'XXXV','XXXVI','XXXVII'] 89 | Spd = ['S', 'P', 'D', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'O', 'Q', 'R', 'T', 'U', 'V', 'W', \ 90 | 'X','Y', 'Z', 'A','B', 'C', 'S1', 'P1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'K1', 'L1', \ 91 | 'M1', 'N1', 'O1', 'Q1', 'R1', 'T1', 'U1', 'V1', 'W1','X1','Y1', 'Z1', 'A1','B1', 'C1'] 92 | # 93 | # data for Gauss-Laguerre integration 94 | # 95 | ngl = 12 96 | zgl = special.roots_laguerre(ngl) 97 | xgl = zgl[0] 98 | wgl = zgl[1] 99 | 100 | #ngl = 12 101 | #xgl = np.asarray([0.115722117358021,0.611757484515131,1.512610269776419,2.833751337743509 102 | # ,4.599227639418353,6.844525453115181,9.621316842456871,13.006054993306350 103 | # ,17.116855187462260,22.151090379396983,28.487967250983992,37.099121044466926], 'float64') 104 | # 105 | # 106 | #wgl = np.asarray([2.647313710554435e-01,3.777592758731382e-01,2.440820113198774e-01,9.044922221168074e-02 107 | # ,2.010238115463406e-02,2.663973541865321e-03,2.032315926629993e-04,8.365055856819753e-06 108 | # ,1.668493876540914e-07,1.342391030515027e-09,3.061601635035012e-12,8.148077467426124e-16], 'float64') 109 | -------------------------------------------------------------------------------- /ChiantiPy/tools/data.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Module for collecting various top-level Chianti data 3 | 4 | Descriptions for `keywordArgs`: 5 | 6 | - `temperature` : temperature (in K) 7 | - `eDensity` : electron density (in :math:r`\\mathrm{cm}^{-3}`) 8 | - `hDensity` : hydrogen density (in :math:r`\\mathrm{cm}^{-3}`) 9 | - `pDensity` : proton density (in :math:r`\\mathrm{cm}^{-3}`) 10 | - `radTemperature` : radiation temperature of central source (in K) 11 | - `rStar` : distance of the plasma from the source (in units of the source's radius) 12 | - `distance` : distance from the central source 13 | 14 | Parameters 15 | ---------- 16 | 17 | XUVTOP : str 18 | the root of the CHIANTI database 19 | Defaults : dict 20 | default values used by ChiantiPy, can also be set by an optional HOME/.chianti/chiantirc file 21 | Ip : np.ndarray 22 | the ionization potentials for all ionization stages up to Zn, in eV 23 | MasterList : list 24 | the CHIANTI style names of all ions in the CHIANTI database 25 | IoneqAll : dict 26 | a dict containing the ionization equilibrium values for the default ionization file 27 | ChiantiVersion : str 28 | the version of the CHIANTI database 29 | AbundanceDefault : dict 30 | the elemental abundances in the default abundance file 31 | AbundanceList : list 32 | the names of all abundance files included in the CHIANTI database 33 | GrndLevels : list 34 | the number of levels that should be considered in an ionization calculation 35 | ''' 36 | import os 37 | import glob 38 | import traceback 39 | import warnings 40 | 41 | import ChiantiPy.tools.io as chio 42 | 43 | klnames = ['klgfb_1.dat','klgfb_2.dat', 'klgfb_3.dat', 'klgfb_4.dat', 'klgfb_5.dat', 'klgfb_6.dat'] 44 | try: 45 | Xuvtop = os.environ['XUVTOP'] 46 | Defaults = chio.defaultsRead() 47 | Ip = chio.ipRead() 48 | MasterList = chio.masterListRead() 49 | IoneqAll = chio.ioneqRead(ioneqName=Defaults['ioneqfile']) 50 | ChiantiVersion = chio.versionRead() 51 | keywordArgs = ['temperature', 'eDensity', 'hDensity', 'pDensity', 'radTemperature', 52 | 'rStar', 'distance'] 53 | AbundanceDefault = chio.abundanceRead(abundancename=Defaults['abundfile']) 54 | 55 | AbundanceList = [] 56 | for fname in glob.glob(os.path.join(Xuvtop, 'abundance', '*.abund')): 57 | AbundanceList.append(os.path.splitext(os.path.basename(fname))[0]) 58 | Abundance = {abundance: chio.abundanceRead(abundancename=abundance) 59 | for abundance in AbundanceList} 60 | GrndLevels = chio.grndLevelsRead() 61 | Verner_info = chio.vernerRead() 62 | 63 | # klfileName = os.path.join(Xuvtop, 'continuum', klnames[0]) 64 | try: 65 | # if os.path.isfile(klfileName): 66 | Klgbfn = [] 67 | for aname in klnames: 68 | filename = os.path.join(Xuvtop, 'continuum', aname) 69 | kl = chio.klgbfnRead(filename) 70 | Klgbfn.append(kl) 71 | except(IOError): 72 | warnings.warn('klgfb files are not present: \n it will not be possible to use the freeBound continuum method') 73 | 74 | 75 | except (KeyError, IOError) as e: 76 | print(traceback.format_exc()) 77 | if isinstance(e, KeyError): 78 | warnings.warn( 79 | 'XUVTOP environment variable not set. You will not be able to access any data from the CHIANTI database.') 80 | else: 81 | warnings.warn( 82 | 'Cannot find the CHIANTI atomic database at {}. You will not be able to access any data from the CHIANTI database.'.format(Xuvtop)) 83 | -------------------------------------------------------------------------------- /ChiantiPy/tools/filters.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line profile filters for creating synthetic spectra. 3 | """ 4 | 5 | import numpy as np 6 | from scipy.special import voigt_profile 7 | 8 | 9 | def gaussianR(wvl, wvl0, factor=1000.): 10 | """ 11 | A gaussian filter where the gaussian width is given by `wvl0`/`factor`. 12 | 13 | Parameters 14 | ----------- 15 | wvl : `~numpy.ndarray` 16 | Wavelength array 17 | wvl0 : `~numpy.float64` 18 | Wavelength filter should be centered on. 19 | factor : `~numpy.float64` 20 | Resolving power 21 | """ 22 | std = wvl0/factor 23 | wvl = np.asarray(wvl) 24 | return np.exp(-0.5*((wvl - wvl0)/std)**2)/(np.sqrt(2.*np.pi)*std) 25 | 26 | 27 | def gaussian(wvl, wvl0, factor = 1.): 28 | """ 29 | A gaussian filter 30 | 31 | Parameters 32 | ----------- 33 | wvl : `~numpy.ndarray` 34 | Wavelength array 35 | wvl0 : `~numpy.float64` 36 | Wavelength filter should be centered on. 37 | factor : `~numpy.float64` 38 | Gaussian width 39 | 40 | integrated value is unity 41 | """ 42 | wvl = np.asarray(wvl, np.float64) 43 | return np.exp(-0.5*((wvl - wvl0)/factor)**2)/(np.sqrt(2.*np.pi)*factor) 44 | 45 | 46 | def boxcar(wvl, wvl0, factor = None): 47 | """ 48 | Box-car filter 49 | 50 | Parameters 51 | ----------- 52 | wvl : `~numpy.ndarray` 53 | Wavelength array 54 | wvl0 : `~numpy.float64` 55 | Wavelength filter should be centered on. 56 | factor : `~numpy.float64` 57 | Full width of the box-car filter 58 | """ 59 | wvl = np.asarray(wvl, np.float64) 60 | dwvl = wvl - np.roll(wvl, 1) 61 | dwvl[0] = dwvl[1] 62 | one = np.ones_like(wvl) 63 | zed = np.zeros_like(wvl) 64 | if factor is None: 65 | factor = dwvl.min() 66 | if factor < dwvl.min(): 67 | raise ValueError('Width must be at least equal to the wavelength step') 68 | good1 = (wvl > wvl0 - factor/2.) 69 | good2 = (wvl < wvl0 + factor/2.) 70 | realgood = np.logical_and(good1, good2) 71 | return np.where(realgood, one, zed)/(factor) 72 | 73 | 74 | 75 | def lorentz(wvl, wvl0, factor = 1.): 76 | """ 77 | Lorentz profile filter with the exception that all factors are in wavelength units 78 | rather than frequency as the lorentz profile is usually defined. 79 | 80 | Parameters 81 | ----------- 82 | wvl : `~numpy.ndarray` 83 | Wavelength array 84 | wvl0 : `~numpy.float64` 85 | Wavelength filter should be centered on. 86 | factor : `~numpy.float64` 87 | Value of the so-called constant gamma 88 | 89 | integrated value is unity 90 | the FWHM is 2*gamma 91 | 92 | .. math:: 93 | L = \\frac{1}{\\pi \\gamma} \\frac{ \\gamma^2}{(\\lambda - \\lambda_0)^2 + \\gamma^2} 94 | 95 | """ 96 | wvl = np.asarray(wvl) 97 | sigma = factor 98 | gamma = sigma*np.sqrt(2.*np.log(2.)) 99 | ltz = (gamma/(np.pi))/((wvl - wvl0)**2 + (gamma)**2) 100 | return ltz 101 | 102 | def moffat(wvl, wvl0, factor=2.5): 103 | """ 104 | Moffat profile with parameters suited to Chandra Letg spectra 105 | 106 | Parameters 107 | ---------- 108 | wvl : `~numpy.ndarray` 109 | Wavelength array 110 | wvl0 : `~numpy.float64` 111 | Wavelength the filter is centered on. 112 | factor : `~numpy.float64` 113 | Resolving power (TODO: correct description) 114 | """ 115 | wvl = np.asarray(wvl) 116 | dwvl = np.abs(wvl[1] - wvl[0]) 117 | moffat = 1./(1.+((wvl - wvl0)/0.0275)**2)**factor 118 | return moffat/(dwvl*moffat.sum()) 119 | 120 | def psvoigt(wvl, wvl0, factor=(0.5, 1.)): 121 | ''' pseudo-Voigt filter 122 | the sum of a Gaussian and a Lorentzian 123 | 124 | Parameters 125 | ---------- 126 | wvl : `~numpy.ndarray` 127 | Wavelength array 128 | wvl0 : `~numpy.float64` 129 | Wavelength the filter is centered on. 130 | factor: array-type 131 | contains the following 2 parameters 132 | A : `~numpy.float64` 133 | relative size of gaussian and lorentz components 134 | must be between 0. and 1. but this is not currently checked 135 | sigma: `~numpy.float64` 136 | the gaussian width of the gaussian profile (the standard deviation) 137 | also creates the lorentz component with the same fwhm 138 | ''' 139 | A = factor[0] 140 | sigma = factor[1] 141 | return A*gaussian(wvl, wvl0, sigma) + (1.-A)*lorentz(wvl, wvl0, sigma) 142 | 143 | def voigt(wvl, wvl0, factor = (None, None)): 144 | ''' 145 | voigt profile from scipy.special.voigt_profile 146 | 147 | Parameters 148 | ---------- 149 | wvl : `~numpy.ndarray` 150 | Wavelength array 151 | wvl0 : `~numpy.float64` 152 | Wavelength the filter is centered on. 153 | factor: array-type 154 | contains the following 3 parameters 155 | sigma: `~numpy.ndarray` of same shape as wvl, default value is 2.e-4 156 | the gaussian width of the gaussian component 157 | gamma: `~numpy.ndarray` of the same shape as wvl, default value is 5.e-4 158 | the fwhm of the Lorentz profile 159 | ''' 160 | 161 | # dispersion = factor[0] 162 | sigma = factor[0] 163 | gamma = factor[1] 164 | 165 | return voigt_profile(wvl - wvl0, sigma, gamma) 166 | -------------------------------------------------------------------------------- /ChiantiPy/tools/mputil.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions needed for standard Python multiprocessing module mspectrum 3 | """ 4 | import numpy as np 5 | import ChiantiPy 6 | 7 | def doFfQ(inQ, outQ): 8 | """ 9 | Multiprocessing helper for `ChiantiPy.core.continuum.freeFree` 10 | 11 | Parameters 12 | ----------- 13 | inQ : `~multiprocessing.Queue` 14 | Ion free-free emission jobs queued up by multiprocessing module 15 | outQ : `~multiprocessing.Queue` 16 | Finished free-free emission jobs 17 | """ 18 | for inputs in iter(inQ.get, 'STOP'): 19 | ionS = inputs[0] 20 | temperature = inputs[1] 21 | wavelength = inputs[2] 22 | abund = inputs[3] 23 | em = inputs[4] 24 | ff = ChiantiPy.core.continuum(ionS, temperature, abundance=abund, em=em) 25 | ff.freeFree(wavelength) 26 | outQ.put(ff.FreeFree) 27 | return 28 | 29 | def doFfLossQ(inQ, outQ): 30 | """ 31 | Multiprocessing helper for `ChiantiPy.core.continuum.freeFreeLoss` 32 | 33 | Parameters 34 | ----------- 35 | inQ : `~multiprocessing.Queue` 36 | Ion free-free emission jobs queued up by multiprocessing module 37 | outQ : `~multiprocessing.Queue` 38 | Finished free-free emission jobs 39 | """ 40 | for inputs in iter(inQ.get, 'STOP'): 41 | ionS = inputs[0] 42 | temperature = inputs[1] 43 | abund = inputs[2] 44 | ffL = ChiantiPy.core.continuum(ionS, temperature, abundance=abund) 45 | ffL.freeFreeLoss() 46 | outQ.put(ffL.FreeFreeLoss) 47 | return 48 | 49 | def doFbQ(inQ, outQ): 50 | """ 51 | Multiprocessing helper for `ChiantiPy.core.continuum.freeBound` 52 | 53 | Parameters 54 | ----------- 55 | inQ : `~multiprocessing.Queue` 56 | Ion free-bound emission jobs queued up by multiprocessing module 57 | outQ : `~multiprocessing.Queue` 58 | Finished free-bound emission jobs 59 | """ 60 | for inputs in iter(inQ.get, 'STOP'): 61 | ionS = inputs[0] 62 | temperature = inputs[1] 63 | wavelength = inputs[2] 64 | abund = inputs[3] 65 | em = inputs[4] 66 | fb = ChiantiPy.core.continuum(ionS, temperature, abundance=abund, em=em) 67 | try: 68 | fb.freeBound(wavelength) 69 | # fb_emiss = fb.FreeBound['intensity'] 70 | except ValueError: 71 | fb.FreeBound = {'intensity':np.zeros((len(temperature),len(wavelength)))} 72 | outQ.put(fb.FreeBound) 73 | return 74 | 75 | 76 | def doFbLossQ(inQ, outQ): 77 | """ 78 | Multiprocessing helper for `ChiantiPy.core.continuum.freeBound` 79 | 80 | Parameters 81 | ----------- 82 | inQ : `~multiprocessing.Queue` 83 | Ion free-bound emission jobs queued up by multiprocessing module 84 | outQ : `~multiprocessing.Queue` 85 | Finished free-bound emission jobs 86 | """ 87 | for inputs in iter(inQ.get, 'STOP'): 88 | ionS = inputs[0] 89 | temperature = inputs[1] 90 | abund = inputs[2] 91 | fbL = ChiantiPy.core.continuum(ionS, temperature, abundance=abund) 92 | try: 93 | fbL.freeBoundLoss() 94 | # fb_emiss = fb.FreeBound['intensity'] 95 | except ValueError: 96 | fbL.FreeBoundLoss = {'intensity':np.zeros_like(temperature)} 97 | outQ.put(fbL.FreeBoundLoss) 98 | return 99 | 100 | 101 | def doIonQ(inQueue, outQueue): 102 | """ 103 | Multiprocessing helper for `ChiantiPy.core.ion` and `ChiantiPy.core.ion.twoPhoton` 104 | 105 | Parameters 106 | ----------- 107 | inQueue : `~multiprocessing.Queue` 108 | Jobs queued up by multiprocessing module 109 | outQueue : `~multiprocessing.Queue` 110 | Finished jobs 111 | """ 112 | for inpts in iter(inQueue.get, 'STOP'): 113 | ionS = inpts[0] 114 | temperature = inpts[1] 115 | density = inpts[2] 116 | wavelength = inpts[3] 117 | # wvlRange = [wavelength.min(), wavelength.max()] 118 | filter = inpts[4] 119 | allLines = inpts[5] 120 | abund = inpts[6] 121 | em = inpts[7] 122 | doContinuum = inpts[8] 123 | thisIon = ChiantiPy.core.Ion.ion(ionS, temperature, density, pDensity='default', 124 | abundance=abund, em=em) 125 | thisIon.intensity(allLines = allLines) 126 | if 'errorMessage' not in sorted(thisIon.Intensity.keys()): 127 | thisIon.spectrum(wavelength, filter=filter) 128 | outList = [ionS, thisIon] 129 | if not thisIon.Dielectronic and doContinuum: 130 | if (thisIon.Z - thisIon.Ion) in [0, 1]: 131 | thisIon.twoPhoton(wavelength) 132 | outList.append(thisIon.TwoPhoton) 133 | outQueue.put(outList) 134 | return 135 | 136 | def doIonLossQ(inQueue, outQueue): 137 | """ 138 | Multiprocessing helper for `ChiantiPy.core.ion` and `ChiantiPy.core.ion.twoPhoton` 139 | 140 | Parameters 141 | ----------- 142 | inQueue : `~multiprocessing.Queue` 143 | Jobs queued up by multiprocessing module 144 | outQueue : `~multiprocessing.Queue` 145 | Finished jobs 146 | """ 147 | for inpts in iter(inQueue.get, 'STOP'): 148 | ionS = inpts[0] 149 | temperature = inpts[1] 150 | density = inpts[2] 151 | allLines = inpts[3] 152 | abund = inpts[4] 153 | doContinuum = inpts[5] 154 | thisIonLoss = ChiantiPy.core.Ion.ion(ionS, temperature, density, pDensity='default', 155 | abundance=abund) 156 | thisIonLoss.boundBoundLoss(allLines = allLines) 157 | # if 'errorMessage' not in sorted(thisIonLoss.Intensity.keys()): 158 | # thisIonLoss.radloss() 159 | outList = [ionS, thisIonLoss] 160 | if not thisIonLoss.Dielectronic and doContinuum: 161 | if (thisIonLoss.Z - thisIonLoss.Ion) in [0, 1]: 162 | thisIonLoss.twoPhotonLoss() 163 | outList.append(thisIonLoss.TwoPhotonLoss) 164 | outQueue.put(outList) 165 | return 166 | -------------------------------------------------------------------------------- /ChiantiPy/tools/sources.py: -------------------------------------------------------------------------------- 1 | """ 2 | Blackbody temperature calculations 3 | """ 4 | 5 | import numpy as np 6 | 7 | from ChiantiPy.tools import constants as const 8 | 9 | class blackStar: 10 | """ 11 | Calculate blackbody radiation 12 | 13 | Parameters 14 | ---------- 15 | temperature : `~numpy.ndarray` 16 | Temperature in Kelvin 17 | radius : `~numpy.ndarray` 18 | Stellar radius in cm 19 | 20 | Attributes 21 | ---------- 22 | Temperature : `~numpy.ndarray` 23 | Temperature in Kelvin 24 | Radius : `~numpy.ndarray` 25 | Stellar radius in cm 26 | Incident : `~numpy.ndarray` 27 | Blackbody photon distribution 28 | """ 29 | 30 | def __init__(self, temperature, radius): 31 | self.Temperature = temperature 32 | self.Radius = radius 33 | 34 | def incident(self, distance, energy): 35 | """ 36 | Calculate photon distribution times the visible cross-sectional area. 37 | 38 | Parameters 39 | ---------- 40 | distance : `~numpy.ndarray` 41 | Distance to the stellar object in cm 42 | energy : `~numpy.ndarray` 43 | Energy range in erg 44 | 45 | Notes 46 | ----- 47 | This function returns the photon distribution instead of the distribution times the 48 | cross-sectional area. Is this correct? Why is the incident photon distribution calculated at all? 49 | """ 50 | print((' distance %10.2e energy '%(energy))) 51 | bb = blackbody(self.Temperature, energy) 52 | # out = const.pi*(self.Radius/distance)**2*bb['photons'] 53 | self.Incident = bb 54 | 55 | 56 | def blackbody(temperature, variable, hnu=1): 57 | """ 58 | Calculate the blackbody photon distribution as a function of energy (`hnu` = 1) or\ 59 | as a function of wavelength (`hnu` = 0) in units of 60 | :math:`\mathrm{photons}\,\mathrm{cm}^{-2}\,\mathrm{s}^{-1}\,\mathrm{str}^{-1}\,\mathrm{erg}^{-1}` 61 | 62 | Parameters 63 | ---------- 64 | temperature : `~numpy.float64` 65 | Temperature at which to calculate the blackbody photon distribution 66 | variable : `~numpy.ndarray` 67 | Either energy (in erg) or wavelength (in angstrom) 68 | hnu : `int` 69 | If 1, calculate distribution as a function of energy. Otherwise, calculate it as 70 | a function of wavelength 71 | 72 | Returns 73 | ------- 74 | {'photons', 'temperature', 'energy'} or {'photons', 'temperature', 'wvl'} : `dict` 75 | """ 76 | if hnu: 77 | energy = variable 78 | bb =(2./(const.planck*(const.hc**2)))*energy**2/(np.exp(energy/(const.boltzmann*temperature)) - 1.) 79 | return {'photons':bb, 'temperature':temperature, 'energy':energy} 80 | else: 81 | wvl = 1.e-8*variable 82 | bb = ((2.*const.pi*const.light)/wvl**4)/(np.exp(const.hc/(wvl*const.boltzmann*temperature)) - 1.) 83 | return {'photons':bb, 'temperature':temperature, 'wvl':wvl} 84 | -------------------------------------------------------------------------------- /ChiantiPy/version.py: -------------------------------------------------------------------------------- 1 | ''' 2 | the current version of the ChiantiPy package 3 | ''' 4 | __version_info__ = ('0','15', '2') 5 | __version__ = '.'.join(__version_info__) 6 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include CHANGES.rst 3 | 4 | include ez_setup.py 5 | include ah_bootstrap.py 6 | include setup.cfg 7 | 8 | include images/*.png 9 | include chiantirc 10 | include LICENSE 11 | include LICENSE.fortranformat 12 | include README 13 | include VERSION 14 | include ipython_notebooks/QuickStart.* 15 | exclude core/PNe.py 16 | 17 | recursive-include *.pyx *.c *.pxd 18 | recursive-include docs * 19 | recursive-include licenses * 20 | recursive-include cextern * 21 | recursive-include scripts * 22 | 23 | prune build 24 | prune docs/_build 25 | prune docs/api 26 | 27 | 28 | # the next few stanzas are for astropy_helpers. It's derived from the 29 | # astropy_helpers/MANIFEST.in, but requires additional includes for the actual 30 | # package directory and egg-info. 31 | 32 | include astropy_helpers/README.rst 33 | include astropy_helpers/CHANGES.rst 34 | include astropy_helpers/LICENSE.rst 35 | recursive-include astropy_helpers/licenses * 36 | 37 | include astropy_helpers/ez_setup.py 38 | include astropy_helpers/ah_bootstrap.py 39 | 40 | recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h 41 | recursive-include astropy_helpers/astropy_helpers.egg-info * 42 | # include the sphinx stuff with "*" because there are css/html/rst/etc. 43 | recursive-include astropy_helpers/astropy_helpers/sphinx * 44 | 45 | prune astropy_helpers/build 46 | prune astropy_helpers/astropy_helpers/tests 47 | 48 | 49 | global-exclude *.pyc *.o 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChiantiPy - Version 0.15.2 2 | [![Documentation Status](http://readthedocs.org/projects/chiantipy/badge/?version=latest)](http://chiantipy.readthedocs.io/en/latest/?badge=latest) 3 | [![Coverage Status](https://coveralls.io/repos/github/chianti-atomic/ChiantiPy/badge.svg?branch=master)](https://coveralls.io/github/chianti-atomic/ChiantiPy?branch=master) 4 | [![ascl:1308.017](https://img.shields.io/badge/ascl-1308.017-blue.svg?colorB=262255)](http://ascl.net/1308.017) 5 | 6 | ChiantiPy is the Python interface to the [CHIANTI atomic database](http://www.chiantidatabase.org) for astrophysical spectroscopy. It provides the capability to calculate the emission line and continuum spectrum of an optically thin plasma based on the data in the CHIANTI database. 7 | 8 | ## What is CHIANTI? 9 | CHIANTI provides a database of atomic data that can be used to interpret the emission of spectral lines and continua emitted from high-temperature, optically-thin astrophysical sources. The CHIANTI project provides a suite of routines written in Interactive Data Language (IDL) to access the database and calculate various quantities for use in interpreting observed spectra or producing synthetic spectra. As of ChiantiPy 0.10.0, the CHIANTI database version 10 or later is required 10 | 11 | ## Installation 12 | The following dependencies are required to run ChiantiPy, 13 | 14 | * [Python3](https://www.python.org/) (Python 3 is now required as of version 0.8.0) 15 | * [Numpy](http://www.numpy.org/) 16 | * [Scipy](https://www.scipy.org/) 17 | * [Matplotlib](http://matplotlib.org/) 18 | * [ipyparallel](https://github.com/ipython/ipyparallel) 19 | 20 | The following two are extremely useful for running Python programs 21 | * [IPython](http://ipython.org) 22 | * [Jupyter](http://jupyter.org/) 23 | 24 | 25 | Optionally, if you'd like to use the GUI dialogs, 26 | 27 | * [PyQt5](https://riverbankcomputing.com/software/pyqt/intro) 28 | 29 | If you are not familiar with installing Python and the needed dependencies, we recommend the [Anaconda platform](https://www.continuum.io/downloads). Next, download the [CHIANTI database](http://www.chiantidatabase.org/chianti_download.html), version 10.0 or later. Assuming you've placed the CHIANTI tree in `$HOME`, set the environment variable in your `.bashrc` file, 30 | ```Shell 31 | export XUVTOP=$HOME/MY_CHIANTI_DIRECTORY 32 | ``` 33 | should point to the top directory of your CHIANTI distribution 34 | 35 | The release is also available on [PyPI](https://pypi.org/project/ChiantiPy/) 36 | 37 | ```Shell 38 | $ python3 -m pip install ChiantiPy 39 | ``` 40 | 41 | Or, clone and install the source from GitHub, 42 | ```Shell 43 | $ git clone --recursive https://github.com/chianti-atomic/ChiantiPy.git 44 | $ cd ChiantiPy 45 | $ python setup.py install 46 | ``` 47 | 48 | ## Usage 49 | As a quick example, we'll calculate the populations of the top 10 levels of Fe XIV as a function of temperature at constant density and plot them: 50 | ```Python 51 | >>> import ChiantiPy.core as ch 52 | >>> import numpy as np 53 | >>> import matplotlib.pyplot as plt 54 | >>> temperature = np.logspace(5.8,6.8,21) 55 | >>> fe14 = ch.ion('fe_14',temperature=temperature,eDensity=1.e+9,em=1.e+27) 56 | >>> fe14.popPlot() 57 | >>> plt.show() 58 | ``` 59 | 60 | ## Help 61 | For more information about installing and using either ChiantiPy or the CHIANTI atomic database, check out the following links: 62 | 63 | * [ChiantiPy Documentation on ReadTheDocs](https://chiantipy.readthedocs.io/) 64 | * [ChiantiPy Documentation on ChiantiPy.github.io](https://chianti-atomic.github.io/) 65 | * [Chianti Google Mailing List](https://groups.google.com/forum/#!forum/chianti) 66 | * [CHIANTI Atomic Database Webpage](http://www.chiantidatabase.org/) 67 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. _chiantipy---version-0151: 2 | 3 | ChiantiPy - Version 0.15.1 4 | ========================== 5 | 6 | |Documentation Status| |Coverage Status| |ascl:1308.017| 7 | 8 | ChiantiPy is the Python interface to the `CHIANTI atomic 9 | database `__ for astrophysical 10 | spectroscopy. It provides the capability to calculate the emission line 11 | and continuum spectrum of an optically thin plasma based on the data in 12 | the CHIANTI database. 13 | 14 | What is CHIANTI? 15 | ---------------- 16 | 17 | CHIANTI provides a database of atomic data that can be used to interpret 18 | the emission of spectral lines and continua emitted from 19 | high-temperature, optically-thin astrophysical sources. The CHIANTI 20 | project provides a suite of routines written in Interactive Data 21 | Language (IDL) to access the database and calculate various quantities 22 | for use in interpreting observed spectra or producing synthetic spectra. 23 | As of ChiantiPy 0.10.0, the CHIANTI database version 10 or later is 24 | required 25 | 26 | Installation 27 | ------------ 28 | 29 | The following dependencies are required to run ChiantiPy, 30 | 31 | - `Python3 `__ (Python 3 is now required as of 32 | version 0.8.0) 33 | - `Numpy `__ 34 | - `Scipy `__ 35 | - `Matplotlib `__ 36 | - `ipyparallel `__ 37 | 38 | The following two are extremely useful for running Python programs 39 | 40 | - `IPython `__ 41 | - `Jupyter `__ 42 | 43 | Optionally, if you'd like to use the GUI dialogs, 44 | 45 | - `PyQt5 `__ 46 | 47 | If you are not familiar with installing Python and the needed 48 | dependencies, we recommend the `Anaconda 49 | platform `__. Next, download the 50 | `CHIANTI 51 | database `__, 52 | version 10.0 or later. Assuming you've placed the CHIANTI tree in 53 | ``$HOME``, set the environment variable in your ``.bashrc`` file, 54 | 55 | .. code:: Shell 56 | 57 | export XUVTOP=$HOME/MY_CHIANTI_DIRECTORY 58 | 59 | should point to the top directory of your CHIANTI distribution 60 | 61 | Finally, clone and install the source from GitHub, 62 | 63 | .. code:: Shell 64 | 65 | $ git clone --recursive https://github.com/chianti-atomic/ChiantiPy.git 66 | $ cd ChiantiPy 67 | $ python setup.py install 68 | 69 | The release is also available on 70 | `PyPI `__ 71 | 72 | Usage 73 | ----- 74 | 75 | As a quick example, we'll calculate the populations of the top 10 levels 76 | of Fe XIV as a function of temperature at constant density and plot 77 | them: 78 | 79 | .. code:: Python 80 | 81 | >>> import ChiantiPy.core as ch 82 | >>> import numpy as np 83 | >>> import matplotlib.pyplot as plt 84 | >>> temperature = np.logspace(5.8,6.8,21) 85 | >>> fe14 = ch.ion('fe_14',temperature=temperature,eDensity=1.e+9,em=1.e+27) 86 | >>> fe14.popPlot() 87 | >>> plt.show() 88 | 89 | Help 90 | ---- 91 | 92 | For more information about installing and using either ChiantiPy or the 93 | CHIANTI atomic database, check out the following links: 94 | 95 | - `ChiantiPy Documentation on 96 | ReadTheDocs `__ 97 | - `Chianti Google Mailing 98 | List `__ 99 | - `CHIANTI Atomic Database Webpage `__ 100 | 101 | .. |Documentation Status| image:: http://readthedocs.org/projects/chiantipy/badge/?version=latest 102 | :target: http://chiantipy.readthedocs.io/en/latest/?badge=latest 103 | .. |Coverage Status| image:: https://coveralls.io/repos/github/chianti-atomic/ChiantiPy/badge.svg?branch=master 104 | :target: https://coveralls.io/github/chianti-atomic/ChiantiPy?branch=master 105 | .. |ascl:1308.017| image:: https://img.shields.io/badge/ascl-1308.017-blue.svg?colorB=262255 106 | :target: http://ascl.net/1308.017 107 | -------------------------------------------------------------------------------- /chiantirc: -------------------------------------------------------------------------------- 1 | [chianti] 2 | # wavelength - angstrom, nm, kev 3 | wavelength: angstrom 4 | # flux - energy, photon 5 | flux: energy 6 | # abundfile - any file in $XUVTOP/abundance 7 | abundfile: sun_photospheric_2015_scott 8 | # ioneqfile - any file in $XUVTOP/ioneq 9 | ioneqfile: chianti 10 | # to use use gui dialogs to make selection, set to true, 11 | # to make selections from the shell set to false 12 | gui: false 13 | -------------------------------------------------------------------------------- /docs/0-notes.txt: -------------------------------------------------------------------------------- 1 | in /docs 2 | sphinx quick-start 3 | this creates build and source directories + Makefile 4 | in the source directory, an conf.py and index.rst 5 | move the usual document .rst files into source 6 | move _templates/layout.rst into _templates 7 | move all the _static files (mostly png) into the new _static 8 | 9 | in /docs 10 | 11 | sphinx-apidoc -o source/api ../ChiantiPy 12 | 13 | then need to edit stuff in api ChiantiPy.base.rst to include the methods 14 | 15 | sphinxdoc.css - line 20 14px -> 16px 16 | 17 | in api/index need to make link to ChiantiPy_logo to read ../_static/... 18 | however, this only works for one more level down 19 | can do this with text_replace 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = ChiantiPy 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/source/IDL_intro.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Intro for CHIANTI IDL Users 3 | =========================== 4 | 5 | ChiantiPy was not developed to be a clone of the CHIANTI IDL code. The IDL code largely consists of functions that can be used to calculate or plot a variety of properties. Structures are often used to carry the results of one function to be used by another. 6 | 7 | ChiantiPy is object oriented. For example, the building block of ChiantiPy is the **ion** class. It carries with it all the methods that are needed as well as various calculated properties that are kept as attributes. By following the Quick Start guide, you will become familiar with how ChiantiPy works. Because one can always inquire, for example with `dir`, as to the methods and attributes of a an object, such as an ion, it is easy to remember what you might want to calculate next. For example, you have created an object *myion*. It is possible to then invoke 8 | 9 | :: 10 | 11 | myion.popPlot() 12 | 13 | to plot the level populations of *myion*. If you have not already calculated the levels populations, the **ion** class knows to calculate the level populations (*myion.populate()*) and save them for later use as the dictionary attribute *myion.Population* and then plot the specified level populations. The level populations are then available as a 2 dimensional `numpy` array 14 | 15 | :: 16 | 17 | myion.Population['population'] 18 | 19 | Python and IPython provide many tools for examining any give object (everything in Python is an object of some sort) 20 | 21 | :: 22 | 23 | mg4 = ch.ion('mg_4',setup=0) 24 | 25 | By setting the keyword *setup* to 0 or `False` the complete setup of the ion is not performed, but a certain amount of information is retrieved. Since neither a temperature or electron density were specified, none of these attributes know anything related to these two quantitities. The default value for setup is True so that the setup is performed with the specified temperatures and electron densities. In general, this is the way you want to construct the mg_4 *ion*. 26 | 27 | :: 28 | 29 | for attr in vars(mg4): 30 | print(attr) 31 | 32 | IonStr 33 | FIP 34 | Z 35 | AbundanceName 36 | Ip 37 | Ion 38 | IoneqAll 39 | PDensity 40 | Abundance 41 | RadTemperature 42 | FileName 43 | RStar 44 | ProtonDensityRatio 45 | Dielectronic 46 | Defaults 47 | IoneqName 48 | Spectroscopic 49 | 50 | The Python function `vars` retrieves the attributes of the mg4 object. 51 | 52 | :: 53 | 54 | print('%s'%(mg4.IoneqName)) 55 | 56 | chianti 57 | 58 | print('the abundance file name is %s'%(mg4.AbundanceName)) 59 | 60 | the abundance file name is sun_coronal_1992_feldman_ext 61 | 62 | print('the abundance of %s is %10.2e'%(mg4.Spectroscopic,mg4.Abundance)) 63 | 64 | the abundance of Mg IV is 1.41e-04 65 | 66 | One can get a more complete description of the various attributes and methods of the mg4 object 67 | 68 | :: 69 | 70 | for one in dir(mg4): 71 | print(one) 72 | 73 | Abundance 74 | AbundanceName 75 | Defaults 76 | Dielectronic 77 | FIP 78 | FileName 79 | Ion 80 | IonStr 81 | IoneqAll 82 | IoneqName 83 | Ip 84 | PDensity 85 | ProtonDensityRatio 86 | RStar 87 | RadTemperature 88 | Spectroscopic 89 | Z 90 | __class__ 91 | __delattr__ 92 | __dict__ 93 | __dir__ 94 | __doc__ 95 | __eq__ 96 | __format__ 97 | __ge__ 98 | __getattribute__ 99 | __gt__ 100 | __hash__ 101 | __init__ 102 | __le__ 103 | __lt__ 104 | __module__ 105 | __ne__ 106 | __new__ 107 | __reduce__ 108 | __reduce_ex__ 109 | __repr__ 110 | __setattr__ 111 | __sizeof__ 112 | __str__ 113 | __subclasshook__ 114 | __weakref__ 115 | boundBoundLoss 116 | cireclvlDescale 117 | convolve 118 | diCross 119 | diRate 120 | drRate 121 | drRateLvl 122 | eaCross 123 | eaDescale 124 | eaRate 125 | emiss 126 | emissList 127 | emissPlot 128 | emissRatio 129 | gofnt 130 | intensity 131 | intensityList 132 | intensityPlot 133 | intensityRatio 134 | intensityRatioInterpolate 135 | intensityRatioSave 136 | ionGate 137 | ioneqOne 138 | ionizCross 139 | ionizRate 140 | lineSpectrumPlot 141 | p2eRatio 142 | popPlot 143 | populate 144 | recombRate 145 | rrRate 146 | setup 147 | setupIonrec 148 | spectrum 149 | spectrumPlot 150 | twoPhoton 151 | twoPhotonEmiss 152 | twoPhotonLoss 153 | upsilonDescale 154 | upsilonDescaleSplups 155 | 156 | First, at the top of the list are the attributes that were listed by the `vars` function. Then come a number of methods starting with '__'. These are generally not used and called *private* methods although nothing in Python is really private. In IDL, just about everything is private. After the *private* methods is a list of the methods provided by the mg4 *ion* class object. These all start with a lower case letter to separate them from the attributes that start with an upper case letter (this is a ChiantiPy convention). 157 | 158 | In the IPython and jupyter-qtconsole, typing 159 | 160 | :: 161 | 162 | mg4.diCross( 163 | 164 | and then hitting the tab key will bring up the doc-string for the diCross method, also found in the API reference in the documentation. And then 165 | 166 | :: 167 | 168 | mg4.diCross() 169 | 170 | calculates the direct ionization cross section of Mg IV for a set of energies above the ionization potential *Ip*. The direct ionization cross sections are then provided in the mg4.DiCross dictionary. 171 | 172 | 173 | Experience using the CHIANTI IDL package will provide the user with a background with what ChiantiPy can do. However, the way to accomplish them are much easier but must be learned. The best way to start is with the Quick Start guide and a book about Python. Book suggestions are *Learning Python* by Mark Lutz and the handy *Python Pocket Reference*, also by Mark Lutz. The first one is alway in reach and copies of the latter is on all of my computer desks. 174 | 175 | 176 | -------------------------------------------------------------------------------- /docs/source/_static/2.selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/2.selector.png -------------------------------------------------------------------------------- /docs/source/_static/bunch_399_404_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/bunch_399_404_label.png -------------------------------------------------------------------------------- /docs/source/_static/bunch_intensityPlot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/bunch_intensityPlot.png -------------------------------------------------------------------------------- /docs/source/_static/bunch_selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/bunch_selector.png -------------------------------------------------------------------------------- /docs/source/_static/bunch_spectrumPlot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/bunch_spectrumPlot.png -------------------------------------------------------------------------------- /docs/source/_static/bunch_spectrum_integrated_mg6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/bunch_spectrum_integrated_mg6.png -------------------------------------------------------------------------------- /docs/source/_static/chiantipy_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/chiantipy_logo.png -------------------------------------------------------------------------------- /docs/source/_static/continuum_2e7_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/continuum_2e7_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/continuum_flare_dem_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/continuum_flare_dem_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.gofnt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.gofnt.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.gofnt.selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.gofnt.selector.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.gofnt_alternate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.gofnt_alternate.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.int.ratio.vs.d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.int.ratio.vs.d.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.int.ratio.vs.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.int.ratio.vs.t.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.int.vs.d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.int.vs.d.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.int.vs.t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.int.vs.t.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.popplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.popplot.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.rel.emiss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.rel.emiss.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.spectrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.spectrum.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.spectrum2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.spectrum2.png -------------------------------------------------------------------------------- /docs/source/_static/fe14.spectrum_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14.spectrum_label.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_gofnt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_gofnt.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_gofnt_alternate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_gofnt_alternate.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_integrated_spectrum_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_integrated_spectrum_label.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_intensity_plot_lin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_intensity_plot_lin.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_intensity_plot_lin_index10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_intensity_plot_lin_index10.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_intensity_plot_lin_index10_rel_notitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_intensity_plot_lin_index10_rel_notitle.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_pop_vs_dens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_pop_vs_dens.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_spectrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_spectrum.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_spectrum2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_spectrum2.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_spectrumPlot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_spectrumPlot.png -------------------------------------------------------------------------------- /docs/source/_static/fe14_spectrum_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe14_spectrum_label.png -------------------------------------------------------------------------------- /docs/source/_static/fe_12_wvlranges_ratio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe_12_wvlranges_ratio.png -------------------------------------------------------------------------------- /docs/source/_static/fe_13_14_15_ioneq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe_13_14_15_ioneq.png -------------------------------------------------------------------------------- /docs/source/_static/fe_25_ff_fb_tp_2e7_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe_25_ff_fb_tp_2e7_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/fe_ioneq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/fe_ioneq.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_spectrumPlot_10_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_spectrumPlot_10_13.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_spectrumPlot_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_spectrumPlot_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_spectrumPlot_4_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_spectrumPlot_4_9.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_spectrumPlot_6_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_spectrumPlot_6_7.png -------------------------------------------------------------------------------- /docs/source/_static/mspectrum_spectrumPlot_fe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/mspectrum_spectrumPlot_fe.png -------------------------------------------------------------------------------- /docs/source/_static/myioneq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/myioneq.png -------------------------------------------------------------------------------- /docs/source/_static/ne6_mg6_spectrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/ne6_mg6_spectrum.png -------------------------------------------------------------------------------- /docs/source/_static/ne6_mg6_t_ratio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/ne6_mg6_t_ratio.png -------------------------------------------------------------------------------- /docs/source/_static/ne6_mg6_t_ratio_top7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/ne6_mg6_t_ratio_top7.png -------------------------------------------------------------------------------- /docs/source/_static/o_8_ff_fb_tp_3e6_1_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/o_8_ff_fb_tp_3e6_1_100.png -------------------------------------------------------------------------------- /docs/source/_static/o_8_ff_fb_tp_total_3e6_1_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/o_8_ff_fb_tp_total_3e6_1_100.png -------------------------------------------------------------------------------- /docs/source/_static/radloss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/radloss.png -------------------------------------------------------------------------------- /docs/source/_static/radloss_hhe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/radloss_hhe.png -------------------------------------------------------------------------------- /docs/source/_static/rl_coronal_1m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/rl_coronal_1m5.png -------------------------------------------------------------------------------- /docs/source/_static/rl_phot_1m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/rl_phot_1m5.png -------------------------------------------------------------------------------- /docs/source/_static/rl_phot_coronal_1m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/rl_phot_coronal_1m5.png -------------------------------------------------------------------------------- /docs/source/_static/rl_phot_tot_bb_fb_ff_2ph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/rl_phot_tot_bb_fb_ff_2ph.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_10_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_10_20.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_1_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_1_10.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_200_300_3panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_200_300_3panel.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_200_300_integrated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_200_300_integrated.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_200_300_w_si_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_200_300_w_si_9.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_2e7_1.84_1.90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_2e7_1.84_1.90.png -------------------------------------------------------------------------------- /docs/source/_static/spectrum_spectrumPlot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/_static/spectrum_spectrumPlot.png -------------------------------------------------------------------------------- /docs/source/_static/sphinxdoc.css: -------------------------------------------------------------------------------- 1 | /* 2 | * sphinxdoc.css_t 3 | * ~~~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- sphinxdoc theme. Originally created by 6 | * Armin Ronacher for Werkzeug. 7 | * 8 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | @import url("basic.css"); 14 | 15 | /* -- page layout ----------------------------------------------------------- */ 16 | 17 | body { 18 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 19 | 'Verdana', sans-serif; 20 | font-size: 16px; 21 | letter-spacing: -0.01em; 22 | line-height: 150%; 23 | text-align: center; 24 | background-color: #BFD1D4; 25 | color: black; 26 | padding: 0; 27 | border: 1px solid #aaa; 28 | 29 | margin: 0px 80px 0px 80px; 30 | min-width: 740px; 31 | } 32 | 33 | div.document { 34 | background-color: white; 35 | text-align: left; 36 | background-image: url(contents.png); 37 | background-repeat: repeat-x; 38 | } 39 | 40 | div.bodywrapper { 41 | margin: 0 calc(230px + 10px) 0 0; 42 | border-right: 1px solid #ccc; 43 | } 44 | 45 | div.body { 46 | margin: 0; 47 | padding: 0.5em 20px 20px 20px; 48 | } 49 | 50 | div.related { 51 | font-size: 1em; 52 | } 53 | 54 | div.related ul { 55 | background-image: url(navigation.png); 56 | height: 2em; 57 | border-top: 1px solid #ddd; 58 | border-bottom: 1px solid #ddd; 59 | } 60 | 61 | div.related ul li { 62 | margin: 0; 63 | padding: 0; 64 | height: 2em; 65 | float: left; 66 | } 67 | 68 | div.related ul li.right { 69 | float: right; 70 | margin-right: 5px; 71 | } 72 | 73 | div.related ul li a { 74 | margin: 0; 75 | padding: 0 5px 0 5px; 76 | line-height: 1.75em; 77 | color: #EE9816; 78 | } 79 | 80 | div.related ul li a:hover { 81 | color: #3CA8E7; 82 | } 83 | 84 | div.sphinxsidebarwrapper { 85 | padding: 0; 86 | } 87 | 88 | div.sphinxsidebar { 89 | margin: 0; 90 | padding: 0.5em 15px 15px 0; 91 | width: calc(230px - 20px); 92 | float: right; 93 | font-size: 1em; 94 | text-align: left; 95 | } 96 | 97 | div.sphinxsidebar h3, div.sphinxsidebar h4 { 98 | margin: 1em 0 0.5em 0; 99 | font-size: 1em; 100 | padding: 0.1em 0 0.1em 0.5em; 101 | color: white; 102 | border: 1px solid #86989B; 103 | background-color: #AFC1C4; 104 | } 105 | 106 | div.sphinxsidebar h3 a { 107 | color: white; 108 | } 109 | 110 | div.sphinxsidebar ul { 111 | padding-left: 1.5em; 112 | margin-top: 7px; 113 | padding: 0; 114 | line-height: 130%; 115 | } 116 | 117 | div.sphinxsidebar ul ul { 118 | margin-left: 20px; 119 | } 120 | 121 | div.footer { 122 | background-color: #E3EFF1; 123 | color: #86989B; 124 | padding: 3px 8px 3px 0; 125 | clear: both; 126 | font-size: 0.8em; 127 | text-align: right; 128 | } 129 | 130 | div.footer a { 131 | color: #86989B; 132 | text-decoration: underline; 133 | } 134 | 135 | /* -- body styles ----------------------------------------------------------- */ 136 | 137 | p { 138 | margin: 0.8em 0 0.5em 0; 139 | } 140 | 141 | a { 142 | color: #CA7900; 143 | text-decoration: none; 144 | } 145 | 146 | a:hover { 147 | color: #2491CF; 148 | } 149 | 150 | div.body a { 151 | text-decoration: underline; 152 | } 153 | 154 | h1 { 155 | margin: 0; 156 | padding: 0.7em 0 0.3em 0; 157 | font-size: 1.5em; 158 | color: #11557C; 159 | } 160 | 161 | h2 { 162 | margin: 1.3em 0 0.2em 0; 163 | font-size: 1.35em; 164 | padding: 0; 165 | } 166 | 167 | h3 { 168 | margin: 1em 0 -0.3em 0; 169 | font-size: 1.2em; 170 | } 171 | 172 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a { 173 | color: black!important; 174 | } 175 | 176 | h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { 177 | display: none; 178 | margin: 0 0 0 0.3em; 179 | padding: 0 0.2em 0 0.2em; 180 | color: #aaa!important; 181 | } 182 | 183 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, 184 | h5:hover a.anchor, h6:hover a.anchor { 185 | display: inline; 186 | } 187 | 188 | h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, 189 | h5 a.anchor:hover, h6 a.anchor:hover { 190 | color: #777; 191 | background-color: #eee; 192 | } 193 | 194 | a.headerlink { 195 | color: #c60f0f!important; 196 | font-size: 1em; 197 | margin-left: 6px; 198 | padding: 0 4px 0 4px; 199 | text-decoration: none!important; 200 | } 201 | 202 | a.headerlink:hover { 203 | background-color: #ccc; 204 | color: white!important; 205 | } 206 | 207 | cite, code, code { 208 | font-family: 'Consolas', 'Deja Vu Sans Mono', 209 | 'Bitstream Vera Sans Mono', monospace; 210 | font-size: 0.95em; 211 | letter-spacing: 0.01em; 212 | } 213 | 214 | code { 215 | background-color: #f2f2f2; 216 | border-bottom: 1px solid #ddd; 217 | color: #333; 218 | } 219 | 220 | code.descname, code.descclassname, code.xref { 221 | border: 0; 222 | } 223 | 224 | hr { 225 | border: 1px solid #abc; 226 | margin: 2em; 227 | } 228 | 229 | a code { 230 | border: 0; 231 | color: #CA7900; 232 | } 233 | 234 | a code:hover { 235 | color: #2491CF; 236 | } 237 | 238 | pre { 239 | font-family: 'Consolas', 'Deja Vu Sans Mono', 240 | 'Bitstream Vera Sans Mono', monospace; 241 | font-size: 0.95em; 242 | letter-spacing: 0.015em; 243 | line-height: 120%; 244 | padding: 0.5em; 245 | border: 1px solid #ccc; 246 | background-color: #f8f8f8; 247 | } 248 | 249 | pre a { 250 | color: inherit; 251 | text-decoration: underline; 252 | } 253 | 254 | td.linenos pre { 255 | padding: 0.5em 0; 256 | } 257 | 258 | div.quotebar { 259 | background-color: #f8f8f8; 260 | max-width: 250px; 261 | float: right; 262 | padding: 2px 7px; 263 | border: 1px solid #ccc; 264 | } 265 | 266 | div.topic { 267 | background-color: #f8f8f8; 268 | } 269 | 270 | table { 271 | border-collapse: collapse; 272 | margin: 0 -0.5em 0 -0.5em; 273 | } 274 | 275 | table td, table th { 276 | padding: 0.2em 0.5em 0.2em 0.5em; 277 | } 278 | 279 | div.admonition, div.warning { 280 | font-size: 0.9em; 281 | margin: 1em 0 1em 0; 282 | border: 1px solid #86989B; 283 | background-color: #f7f7f7; 284 | padding: 0; 285 | } 286 | 287 | div.admonition p, div.warning p { 288 | margin: 0.5em 1em 0.5em 1em; 289 | padding: 0; 290 | } 291 | 292 | div.admonition pre, div.warning pre { 293 | margin: 0.4em 1em 0.4em 1em; 294 | } 295 | 296 | div.admonition p.admonition-title, 297 | div.warning p.admonition-title { 298 | margin: 0; 299 | padding: 0.1em 0 0.1em 0.5em; 300 | color: white; 301 | border-bottom: 1px solid #86989B; 302 | font-weight: bold; 303 | background-color: #AFC1C4; 304 | } 305 | 306 | div.warning { 307 | border: 1px solid #940000; 308 | } 309 | 310 | div.warning p.admonition-title { 311 | background-color: #CF0000; 312 | border-bottom-color: #940000; 313 | } 314 | 315 | div.admonition ul, div.admonition ol, 316 | div.warning ul, div.warning ol { 317 | margin: 0.1em 0.5em 0.5em 3em; 318 | padding: 0; 319 | } 320 | 321 | div.versioninfo { 322 | margin: 1em 0 0 0; 323 | border: 1px solid #ccc; 324 | background-color: #DDEAF0; 325 | padding: 8px; 326 | line-height: 1.3em; 327 | font-size: 0.9em; 328 | } 329 | 330 | .viewcode-back { 331 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 332 | 'Verdana', sans-serif; 333 | } 334 | 335 | div.viewcode-block:target { 336 | background-color: #f4debf; 337 | border-top: 1px solid #ac9; 338 | border-bottom: 1px solid #ac9; 339 | } 340 | 341 | div.code-block-caption { 342 | background-color: #ddd; 343 | color: #222; 344 | border: 1px solid #ccc; 345 | } 346 | -------------------------------------------------------------------------------- /docs/source/_static/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | stylesheet = default_kpd 3 | pygments_style = sphinx 4 | 5 | [options] 6 | rightsidebar = false 7 | stickysidebar = false 8 | collapsiblesidebar = false 9 | externalrefs = false 10 | 11 | footerbgcolor = #11303d 12 | footertextcolor = #ffffff 13 | sidebarbgcolor = #1c4e63 14 | sidebarbtncolor = #3c6e83 15 | sidebartextcolor = #ffffff 16 | sidebarlinkcolor = #98dbcc 17 | relbarbgcolor = #133f52 18 | relbartextcolor = #ffffff 19 | relbarlinkcolor = #ffffff 20 | bgcolor = #ffffff 21 | textcolor = #000000 22 | headbgcolor = #f2f2f2 23 | headtextcolor = #20435c 24 | headlinkcolor = #c60f0f 25 | linkcolor = #355f7c 26 | visitedlinkcolor = #355f7c 27 | codebgcolor = #eeffcc 28 | codetextcolor = #333333 29 | 30 | bodyfont = sans-serif 31 | headfont = 'Trebuchet MS', sans-serif 32 | -------------------------------------------------------------------------------- /docs/source/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block header %} 3 |

4 | 5 | chiantipy 6 | 7 |
8 | {{ super() }} 9 | {% endblock %} 10 | {% block footer %} 11 |
12 | 13 | 14 |
15 | {{ super() }} 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.Gui.gui_cl.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.Gui\.gui\_cl package 2 | =============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.Gui\.gui\_cl\.gui module 8 | ----------------------------------- 9 | 10 | .. automodule:: ChiantiPy.Gui.gui_cl.gui 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: ChiantiPy.Gui.gui_cl 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.Gui.gui_qt5.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.Gui\.gui\_qt5 package 2 | ================================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.Gui\.gui\_qt5\.gui module 8 | ------------------------------------ 9 | 10 | .. automodule:: ChiantiPy.Gui.gui_qt5.gui 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | ChiantiPy\.Gui\.gui\_qt5\.ui module 16 | ----------------------------------- 17 | 18 | .. automodule:: ChiantiPy.Gui.gui_qt5.ui 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: ChiantiPy.Gui.gui_qt5 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.Gui.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.Gui package 2 | ====================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | ChiantiPy.Gui.gui_cl 10 | ChiantiPy.Gui.gui_qt5 11 | 12 | Module contents 13 | --------------- 14 | 15 | .. automodule:: ChiantiPy.Gui 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.base.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.base package 2 | ======================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.base\._IonTrails module 8 | ---------------------------------- 9 | 10 | .. automodule:: ChiantiPy.base._IonTrails 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | ChiantiPy\.base\._SpecTrails module 16 | ----------------------------------- 17 | 18 | .. automodule:: ChiantiPy.base._SpecTrails 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: ChiantiPy.base 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.core.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.core package 2 | ======================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | ChiantiPy.core.tests 10 | 11 | Submodules 12 | ---------- 13 | 14 | ChiantiPy\.core\.Continuum module 15 | --------------------------------- 16 | 17 | .. automodule:: ChiantiPy.core.Continuum 18 | :members: 19 | :undoc-members: 20 | :show-inheritance: 21 | 22 | ChiantiPy\.core\.Ion module 23 | --------------------------- 24 | 25 | .. automodule:: ChiantiPy.core.Ion 26 | :members: 27 | :undoc-members: 28 | :show-inheritance: 29 | 30 | ChiantiPy\.core\.Ioneq module 31 | ----------------------------- 32 | 33 | .. automodule:: ChiantiPy.core.Ioneq 34 | :members: 35 | :undoc-members: 36 | :show-inheritance: 37 | 38 | ChiantiPy\.core\.IpyMspectrum module 39 | ------------------------------------ 40 | 41 | .. automodule:: ChiantiPy.core.IpyMspectrum 42 | :members: 43 | :undoc-members: 44 | :show-inheritance: 45 | 46 | ChiantiPy\.core\.Mspectrum module 47 | --------------------------------- 48 | 49 | .. automodule:: ChiantiPy.core.Mspectrum 50 | :members: 51 | :undoc-members: 52 | :show-inheritance: 53 | 54 | ChiantiPy\.core\.RadLoss module 55 | ------------------------------- 56 | 57 | .. automodule:: ChiantiPy.core.RadLoss 58 | :members: 59 | :undoc-members: 60 | :show-inheritance: 61 | 62 | ChiantiPy\.core\.MradLoss module 63 | -------------------------------- 64 | 65 | .. automodule:: ChiantiPy.core.MradLoss 66 | :members: 67 | :undoc-members: 68 | :show-inheritance: 69 | 70 | ChiantiPy\.core\.Bunch module 71 | -------------------------------- 72 | 73 | .. automodule:: ChiantiPy.core.Bunch 74 | :members: 75 | :undoc-members: 76 | :show-inheritance: 77 | 78 | ChiantiPy\.core\.Spectrum module 79 | -------------------------------- 80 | 81 | .. automodule:: ChiantiPy.core.Spectrum 82 | :members: 83 | :undoc-members: 84 | :show-inheritance: 85 | 86 | Module contents 87 | --------------- 88 | 89 | .. automodule:: ChiantiPy.core 90 | :members: 91 | :undoc-members: 92 | :show-inheritance: 93 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.core.tests.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.core\.tests package 2 | ============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.core\.tests\.test\_Continuum module 8 | ---------------------------------------------- 9 | 10 | .. automodule:: ChiantiPy.core.tests.test_Continuum 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | ChiantiPy\.core\.tests\.test\_Ion module 16 | ---------------------------------------- 17 | 18 | .. automodule:: ChiantiPy.core.tests.test_Ion 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | ChiantiPy\.core\.tests\.test\_Ioneq module 24 | ------------------------------------------ 25 | 26 | .. automodule:: ChiantiPy.core.tests.test_Ioneq 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | ChiantiPy\.core\.tests\.test\_Spectrum module 32 | --------------------------------------------- 33 | 34 | .. automodule:: ChiantiPy.core.tests.test_Spectrum 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | Module contents 41 | --------------- 42 | 43 | .. automodule:: ChiantiPy.core.tests 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.fortranformat.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.fortranformat package 2 | ================================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.fortranformat\.FortranRecordReader module 8 | ---------------------------------------------------- 9 | 10 | .. automodule:: ChiantiPy.fortranformat.FortranRecordReader 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | ChiantiPy\.fortranformat\.FortranRecordWriter module 16 | ---------------------------------------------------- 17 | 18 | .. automodule:: ChiantiPy.fortranformat.FortranRecordWriter 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | ChiantiPy\.fortranformat\.config module 24 | --------------------------------------- 25 | 26 | .. automodule:: ChiantiPy.fortranformat.config 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | 32 | Module contents 33 | --------------- 34 | 35 | .. automodule:: ChiantiPy.fortranformat 36 | :members: 37 | :undoc-members: 38 | :show-inheritance: 39 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.model.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.model package 2 | ======================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.model\.Maker module 8 | ------------------------------ 9 | 10 | 11 | .. automodule:: ChiantiPy.model.Maker 12 | :members: 13 | :undoc-members: 14 | :show-inheritance: 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: ChiantiPy.model 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy package 2 | ================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | ChiantiPy.Gui 10 | ChiantiPy.base 11 | ChiantiPy.core 12 | ChiantiPy.fortranformat 13 | ChiantiPy.model 14 | ChiantiPy.tests 15 | ChiantiPy.tools 16 | 17 | Submodules 18 | ---------- 19 | 20 | 21 | ChiantiPy\.version module 22 | ------------------------- 23 | 24 | .. automodule:: ChiantiPy.version 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | 30 | Module contents 31 | --------------- 32 | 33 | .. automodule:: ChiantiPy 34 | :members: 35 | :undoc-members: 36 | :show-inheritance: 37 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.tests.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.tests package 2 | ======================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.tests\.setup\_package module 8 | --------------------------------------- 9 | 10 | .. automodule:: ChiantiPy.tests.setup_package 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: ChiantiPy.tests 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/source/api/ChiantiPy.tools.rst: -------------------------------------------------------------------------------- 1 | ChiantiPy\.tools package 2 | ======================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | ChiantiPy\.tools\.archival module 8 | --------------------------------- 9 | 10 | .. automodule:: ChiantiPy.tools.archival 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | ChiantiPy\.tools\.constants module 16 | ---------------------------------- 17 | 18 | .. automodule:: ChiantiPy.tools.constants 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | ChiantiPy\.tools\.data module 24 | ----------------------------- 25 | 26 | .. automodule:: ChiantiPy.tools.data 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | ChiantiPy\.tools\.filters module 32 | -------------------------------- 33 | 34 | .. automodule:: ChiantiPy.tools.filters 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | ChiantiPy\.tools\.io module 41 | --------------------------- 42 | 43 | .. automodule:: ChiantiPy.tools.io 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | 48 | ChiantiPy\.tools\.mputil module 49 | ------------------------------- 50 | 51 | .. automodule:: ChiantiPy.tools.mputil 52 | :members: 53 | :undoc-members: 54 | :show-inheritance: 55 | 56 | ChiantiPy\.tools\.sources module 57 | -------------------------------- 58 | 59 | .. automodule:: ChiantiPy.tools.sources 60 | :members: 61 | :undoc-members: 62 | :show-inheritance: 63 | 64 | ChiantiPy\.tools\.util module 65 | ----------------------------- 66 | 67 | .. automodule:: ChiantiPy.tools.util 68 | :members: 69 | :undoc-members: 70 | :show-inheritance: 71 | 72 | 73 | Module contents 74 | --------------- 75 | 76 | .. automodule:: ChiantiPy.tools 77 | :members: 78 | :undoc-members: 79 | :show-inheritance: 80 | -------------------------------------------------------------------------------- /docs/source/api/_static/chiantipy_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chianti-atomic/ChiantiPy/e9e853d08bff793b2599f9b3fa74454b5f2ce784/docs/source/api/_static/chiantipy_logo.png -------------------------------------------------------------------------------- /docs/source/api/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block header %} 3 |
4 | 5 | chiantipy 6 | 7 |
8 | {{ super() }} 9 | {% endblock %} 10 | {% block footer %} 11 |
12 | 13 | 14 |
15 | {{ super() }} 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /docs/source/api/index.rst: -------------------------------------------------------------------------------- 1 | .. ChiantiPy documentation master file, created by 2 | sphinx-quickstart on Sat Oct 6 16:03:24 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ChiantiPy's API documentation 7 | ============================= 8 | 9 | .. toctree:: 10 | :glob: 11 | :maxdepth: 4 12 | :caption: Contents: 13 | 14 | ChiantiPy 15 | 16 | 17 | Indices and tables 18 | ================== 19 | 20 | * :ref:`genindex` 21 | * :ref:`modindex` 22 | * :ref:`search` 23 | -------------------------------------------------------------------------------- /docs/source/bugs.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Reporting Bugs 3 | ================ 4 | 5 | 6 | All bugs are kept track of on the `GitHub issue tracker `_. If you run into any unexpected behavior or have a question please `send an email `_ or add an issue directly to the issue tracker. 7 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # ChiantiPy documentation build configuration file, created by 5 | # sphinx-quickstart on Sun Oct 7 13:48:14 2018. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | import os 21 | import sys 22 | sys.path.insert(0, os.path.abspath('.')) 23 | sys.path.insert(0, os.path.abspath('../')) 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | # 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = ['sphinx.ext.autodoc', 35 | 'sphinx.ext.doctest', 36 | 'sphinx.ext.todo', 37 | 'sphinx.ext.coverage', 38 | 'sphinx.ext.mathjax', 39 | 'sphinx.ext.githubpages', 40 | 'sphinx.ext.napoleon'] 41 | 42 | napoleon_google_docstring = False 43 | napoleon_use_param = False 44 | napoleon_use_ivar = True 45 | 46 | 47 | # Add any paths that contain templates here, relative to this directory. 48 | templates_path = ['_templates'] 49 | 50 | # The suffix(es) of source filenames. 51 | # You can specify multiple suffix as a list of string: 52 | # 53 | # source_suffix = ['.rst', '.md'] 54 | source_suffix = '.rst' 55 | 56 | # The master toctree document. 57 | master_doc = 'index' 58 | 59 | # General information about the project. 60 | project = 'ChiantiPy' 61 | copyright = '2025, Ken Dere' 62 | author = 'Ken Dere' 63 | 64 | # The version info for the project you're documenting, acts as replacement for 65 | # |version| and |release|, also used in various other places throughout the 66 | # built documents. 67 | # 68 | # The short X.Y version. 69 | version = '0.15.2' 70 | # The full version, including alpha/beta/rc tags. 71 | release = '0.15.2' 72 | 73 | # The language for content autogenerated by Sphinx. Refer to documentation 74 | # for a list of supported languages. 75 | # 76 | # This is also used if you do content translation via gettext catalogs. 77 | # Usually you set "language" from the command line for these cases. 78 | #language = None 79 | language = "en" 80 | 81 | # List of patterns, relative to source directory, that match files and 82 | # directories to ignore when looking for source files. 83 | # This patterns also effect to html_static_path and html_extra_path 84 | exclude_patterns = [] 85 | 86 | # The name of the Pygments (syntax highlighting) style to use. 87 | pygments_style = 'sphinx' 88 | 89 | # If true, `todo` and `todoList` produce output, else they produce nothing. 90 | todo_include_todos = True 91 | 92 | 93 | # -- Options for HTML output ---------------------------------------------- 94 | 95 | # The theme to use for HTML and HTML Help pages. See the documentation for 96 | # a list of builtin themes. 97 | # 98 | html_theme = 'sphinxdoc' 99 | 100 | # Theme options are theme-specific and customize the look and feel of a theme 101 | # further. For a list of options available for each theme, see the 102 | # documentation. 103 | # 104 | # html_theme_options = {} 105 | 106 | # Add any paths that contain custom static files (such as style sheets) here, 107 | # relative to this directory. They are copied after the builtin static files, 108 | # so a file named "default.css" will overwrite the builtin "default.css". 109 | html_static_path = ['_static'] 110 | 111 | # Custom sidebar templates, must be a dictionary that maps document names 112 | # to template names. 113 | # 114 | # This is required for the alabaster theme 115 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 116 | html_sidebars = { 117 | '**': [ 118 | 'relations.html', # needs 'show_related': True theme option to display 119 | 'searchbox.html', 120 | ] 121 | } 122 | 123 | 124 | # -- Options for HTMLHelp output ------------------------------------------ 125 | 126 | # Output file base name for HTML help builder. 127 | htmlhelp_basename = 'ChiantiPydoc' 128 | 129 | 130 | # -- Options for LaTeX output --------------------------------------------- 131 | 132 | latex_elements = { 133 | # The paper size ('letterpaper' or 'a4paper'). 134 | # 135 | # 'papersize': 'letterpaper', 136 | 137 | # The font size ('10pt', '11pt' or '12pt'). 138 | # 139 | # 'pointsize': '10pt', 140 | 141 | # Additional stuff for the LaTeX preamble. 142 | # 143 | # 'preamble': '', 144 | 145 | # Latex figure (float) alignment 146 | # 147 | # 'figure_align': 'htbp', 148 | } 149 | 150 | # Grouping the document tree into LaTeX files. List of tuples 151 | # (source start file, target name, title, 152 | # author, documentclass [howto, manual, or own class]). 153 | latex_documents = [ 154 | (master_doc, 'ChiantiPy.tex', 'ChiantiPy Documentation', 155 | 'Ken Dere', 'manual'), 156 | ] 157 | 158 | 159 | # -- Options for manual page output --------------------------------------- 160 | 161 | # One entry per manual page. List of tuples 162 | # (source start file, name, description, authors, manual section). 163 | man_pages = [ 164 | (master_doc, 'ChiantiPy', 'ChiantiPy Documentation', 165 | [author], 1) 166 | ] 167 | 168 | 169 | # -- Options for Texinfo output ------------------------------------------- 170 | 171 | # Grouping the document tree into Texinfo files. List of tuples 172 | # (source start file, target name, title, author, 173 | # dir menu entry, description, category) 174 | texinfo_documents = [ 175 | (master_doc, 'ChiantiPy', 'ChiantiPy Documentation', 176 | author, 'ChiantiPy', 'One line description of project.', 177 | 'Miscellaneous'), 178 | ] 179 | 180 | 181 | 182 | 183 | # Example configuration for intersphinx: refer to the Python standard library. 184 | #intersphinx_mapping = {'https://docs.python.org/': None} 185 | -------------------------------------------------------------------------------- /docs/source/getting_started.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Getting started with ChiantiPy 3 | ============================== 4 | 5 | Prerequisites 6 | ------------- 7 | 8 | * CHIANTI_, the atomic database for astrophysical spectroscopy (Version 10 or later) 9 | 10 | .. _CHIANTI: http://www.chiantidatabase.org/ 11 | 12 | * Python3_ (3.8 is the current development version) 13 | 14 | .. _PYTHON3: http://www.python.org 15 | 16 | * Numpy_ (currently developed with 1.20) 17 | 18 | .. _Numpy: http://www.scipy.org/ 19 | 20 | * Scipy_ (currently developed with 1.6) 21 | 22 | .. _Scipy: http://www.scipy.org/ 23 | 24 | * Matplotlib_ (currently developed with 3.3.4) 25 | 26 | .. _Matplotlib: http://matplotlib.sourceforge.net/ 27 | 28 | * Matplotlib requires a GUI library 29 | 30 | PyQt5_ 31 | 32 | Once one of these is installed, it must be set as the backend in your matplotlibrc file, e.g., backend: Qt5Agg 33 | 34 | .. _PyQt5: http://www.riverbankcomputing.co.uk/ 35 | 36 | 37 | * ipyparallel (required for multiprocessing with ipymspectrum) 38 | 39 | * (not really a prerequisite but **extremely** useful) IPython_ version 7.21 and Jupyter_ 40 | 41 | .. _IPython: http://ipython.org 42 | 43 | .. _Jupyter: http://jupyter.readthedocs.io/en/latest/ 44 | 45 | 46 | Install the CHIANTI database 47 | ---------------------------- 48 | 49 | The gzipped *data* tar ball can be downloaded from the CHIANTI website_ 50 | 51 | .. _website: http://www.chiantidatabase.org/chianti_download.html 52 | 53 | * put the file in a convenient directory, cd to the directory and untar the file 54 | 55 | * ChiantiPy uses the environment variable *XUVTOP* to find the database. Set XUVTOP to the name of the directory where the CHIANTI data tarball was placed. For example 56 | 57 | :: 58 | 59 | setenv XUVTOP /data1/directory.where.the.tarball.was.placed 60 | 61 | 62 | or on Windows: To set the environment variable, go to Control Panel -> System -> Advanced System Properties -> Environment Variables. 63 | 64 | 65 | Some sites have the CHIANTI database maintained as part of a SolarSoft distribution. In that case, simply set XUVTOP to the directory were it resides, usually something like $SSW/packages/chianti/dbase 66 | 67 | Install the Prerequisites 68 | ------------------------- 69 | 70 | On **Linux** systems this can usually be done with your package manager. 71 | 72 | On **Windows**, **Linux** and **Mac** systems, it is possible to use 73 | 74 | * the Anaconda_ distribution from from Continuum, or, 75 | 76 | .. _Anaconda: http://continuum.io/downloads 77 | 78 | * the Canopy_ distribution from Enthought. 79 | 80 | .. _Canopy: https://store.enthought.com/downloads/#default 81 | 82 | On **Windows**, it is also possible to use: 83 | 84 | * WinPython_ 85 | 86 | .. _WinPython: http://winpython.github.io/ 87 | 88 | All of these packages are free, at least for noncommercial use (I believe) and have a considerable amount of documentation. **You shoud check the version of IPython that is provided**. 89 | 90 | 91 | Install the ChiantiPy package 92 | ----------------------------- 93 | 94 | In order to be compatible with the latest version (10) of the CHIANTI atomic database, it is necessary to install the latest version (0.10.0) of ChiantiPy 95 | 96 | :: 97 | 98 | pip install ChiantiPy 99 | 100 | or 101 | 102 | :: 103 | 104 | pip3 install ChiantiPy 105 | 106 | 107 | I have not tried this with ChiantiPy, myself. 108 | 109 | 110 | The ChiantiPy package can be downloaded from the ChiantiPy_ project page at Sourceforge, untar it, cd to the directory where it was unpacked, and then, as root 111 | 112 | .. _ChiantiPy: http://sourceforge.net/projects/chiantipy/ 113 | 114 | :: 115 | 116 | python setup.py install 117 | 118 | If you do not have root privileges, simply put the ChiantiPy directory in your PYTHONPATH 119 | 120 | :: 121 | 122 | python setup.py install --prefix=somewhere_in_my_PYTHONPATH 123 | 124 | 125 | or on a Mac, with the Anaconda package 126 | 127 | :: 128 | 129 | python setup.py install --prefix=/Users/your_user_name/anaconda/ 130 | 131 | **Thanks to Peter Young (GMU) for providing the instructions for installation on Mac and Windows** 132 | 133 | Note - ChiantiPy interactions with various GUI backends 134 | ------------------------------------------------------- 135 | 136 | First, Matplotlib requires a GUI backend and can be specified by the user in the matplotlibrc file. Matplotlib expects to find this file in $HOME/.config/matplotlib, although it might require that you copy it to that directory. 137 | 138 | ChiantiPy also uses a GUI dialog widget set. Selections can also be made via the command line. The user choice is specified in the chiantirc file. One is included with the distribution. On Linux, if it is copied into either the $HOME/.config or $HOME/.chianti directory, it will automatically be picked up. It is a text file and can be edited. On Windows, it should be copied to $PROFILEHOME/.config or $PROFILEHOME/.chianti where it will also be picked up. Otherwise, the default GUI is to use the command line. A default chiantirc file is included with the distribution. 139 | 140 | In order for the ChiantiPy dialog widget to be used, a backend for them must be initiated. If you choose the same backend for matplotlib (PyQt5 is best) as for the ChiantiPy widgets, then running %matplotlib in an IPython or Jupyter session will do the trick. In an interactive Python session, invoking a matplotlib or matplotlib qt command first should also do the trick. 141 | 142 | :: 143 | 144 | matplotlib inline 145 | 146 | or 147 | 148 | :: 149 | 150 | matplotlib qt 151 | 152 | if you are using Qt5 153 | 154 | If you choose to use a GUI backend other than that used for matplotlib, then in an IPython or a Jupyter command the following magic commands are also available to start the backend: 155 | 156 | :: 157 | 158 | %gui qt 159 | 160 | 161 | ChiantiPy has mostly been tested with the Qt5 backend for Matplotlib and using the ChiantiPy Qt5 widgets. 162 | 163 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. ChiantiPy documentation master file, created by 2 | sphinx-quickstart on Sun Oct 7 13:48:14 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ChiantiPy Documentation 7 | ======================= 8 | 9 | Welcome to the ChiantiPy documentation. ChiantiPy is a pure Python package for performing calculations of astrophysical spectra using the `CHIANTI atomic database `_. 10 | 11 | The latest version of ChiantiPy is 0.15.2 and is compatible with CHIANTI database version 11.0. It is not compatible with versions prior to 10.0.X. 12 | 13 | ChiantiPy v0.15.2 is released under the OSI approved ISC license. From `Wikipedia `_: The ISC license is a permissive free software license written by the Internet Software Consortium (ISC). It is functionally equivalent to the simplified BSD and MIT/Expat licenses, ... 14 | 15 | `CHIANTI `_ consists of a database of atomic data that can be used to interpret spectral lines and continua emitted from high-temperature, optically-thin astrophysical sources. 16 | 17 | CHIANTI is developed and maintained by scientists at George Mason University (USA), the University of Michigan (USA), NASA/Goddard Space Flight Center (USA) and the University of Cambridge (UK). The first version of CHIANTI was released in 1997 and version 11.0 in 2025. 18 | 19 | .. toctree:: 20 | :maxdepth: 2 21 | 22 | getting_started 23 | quick_start 24 | tutorial 25 | api/index 26 | notes 27 | IDL_intro 28 | resources 29 | changelog 30 | bugs 31 | 32 | 33 | Indices and tables 34 | ================== 35 | 36 | * :ref:`genindex` 37 | * :ref:`modindex` 38 | * :ref:`search` 39 | -------------------------------------------------------------------------------- /docs/source/notes.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Notes 3 | ===== 4 | 5 | Setting default values 6 | ---------------------- 7 | 8 | Several parameter values can be set to define the way ChiantiPy behaves. The following parameter values can be set in your chiantirc file. A chiantirc file is available in the downloaded package but it will only be read if it is located in either ~HOME/.config (probably the best place) or ~HOME/.chianti or ~PROFILEHOME/.config or ~PROFILEHOME/.chianti. It is then possible to modifiy the file to select the default value you wish to use: 9 | 10 | These are: 11 | 12 | 13 | wavelength 14 | 15 | The default value is angstrom. Other possible values are *nm* for nanometers, *ev* for electron volts or *kev* for kilo-electron volts. However, the continuum classes can only be used with the wavelengths in angstroms 16 | 17 | 18 | flux 19 | The default value is energy. Acceptable values are *energy* and *photon* and these govern emissivities and intensities. If set to energy, emission units are in erg. 20 | 21 | abundfile 22 | 23 | The name of the abundance file. Acceptable values are any of the file names in XUVTOP/abundance, such as *cosmic_1973_allen*. The default value is *sun_photospheric_2015_scott* that includes the abundances of Scott et al., 2015, A&A, 573, A25. 24 | 25 | ioneqfile 26 | the name of the ionization equilibrium file. Acceptable values are any of the file names in XUVTOP/ioneq such as *arnaud_raymond*, *arnaud_rothenflug*, or *chianti*. The default value is *chianti* which includes the ionization equilibrium calculations of K.P. Dere, G. Del Zanna, P.R. Young, E. Landi, R Sutherland, 2019, ApJ, 241, 2 and are considered to be based on the best ionization and recombination rates currently available. 27 | 28 | 29 | 30 | Setting *minAbund* in spectrum calculations 31 | ------------------------------------------- 32 | 33 | When calculation spectra with *spectrum* or *mspectrum*, it is often useful to set the "minAbund" keyword which governs the minimum abundance of any element included in the calculation. Below is a list of elemental abundances for the elements through zinc and the elements that will be included by several value of "minAbund". These are for photospheric abundances, some of which may have changed since this table was made. 34 | 35 | ======= ========= ======== ======= ====== 36 | 37 | 38 | Element Abundance minAbund 39 | ------- --------- ------------------------- 40 | .. .. 1.e-6 1.e-5 1.e-4 41 | ======= ========= ======== ======= ====== 42 | H 1.00e+00 + + + 43 | He 8.51e-02 + + + 44 | Li 1.26e-11 45 | Be 2.51e-11 46 | B 3.55e-10 47 | C 3.31e-04 + + + 48 | N 8.32e-05 + + 49 | O 6.76e-04 + + + 50 | F 3.63e-08 51 | Ne 1.20e-04 + + + 52 | Na 2.14e-06 + 53 | Mg 3.80e-05 + + 54 | Al 2.95e-06 + 55 | Si 3.55e-05 + + 56 | P 2.82e-07 57 | S 2.14e-05 + + 58 | Cl 3.16e-07 59 | Ar 2.51e-06 + 60 | K 1.32e-07 61 | Ca 2.29e-06 + 62 | Sc 1.48e-09 63 | Ti 1.05e-07 64 | V 1.00e-08 65 | Cr 4.68e-07 66 | Mn 2.45e-07 67 | Fe 3.16e-05 + + 68 | Co 8.32e-08 69 | Ni 1.78e-06 + 70 | Cu 1.62e-08 71 | Zn 3.98e-08 72 | ======= ========= ======== ======= ====== 73 | 74 | It shoud be noted that CHIANTI does not include a complete set of data for every ion of every element in this list. 75 | 76 | -------------------------------------------------------------------------------- /docs/source/resources.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Resources for ChiantiPy Users 3 | ============================= 4 | 5 | 6 | 7 | Forums 8 | ====== 9 | 10 | 11 | `The CHIANTI Google group`_ 12 | 13 | .. _The CHIANTI Google group: https://groups.google.com/forum/#!forum/chianti 14 | 15 | Github_ 16 | 17 | .. _Github: https://github.com/chianti-atomic/ChiantiPy 18 | 19 | -------------------------------------------------------------------------------- /jupyter_notebooks/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains 9 Jupyter IPython notebooks that demonstrate some of the ways to use ChiantiPy and the CHIANTI database 2 | 3 | QuickStart.ipynb - a notebook that generally follows the Quick-Start guide in the docs 4 | 5 | A demo of the bunch class is found in: bunch_demo.ipynb 6 | 7 | Two demos of the spectrum class are found in: spectrum_demo.ipynb and spectrum_demo_2.ipynb 8 | 9 | The directory also contains 5 other notebooks and a json file. These are demo files for reproducing some of the analyses in the paper "Electron densities and their uncertainties derived from spectral emission line intensities" by Kenneth Dere. This paper has been published in the Monthly Notices of the Royal Astronomical Society, 2020, 496, 2334. 10 | 11 | The notebook file '1_fe_13_demo_make_model.ipynb' constructs the model that is used by 2_fe_13_demo_check_model.ipynb and 3_fe_13_demo_chi2_search.ipynb by reading the 'tab2_1993_qs_fe_13.json' file. It is easiest if all files are placed in the same directory. This files contains the Fe XIII line intensities from Brosius et al., 1996, Astrophysical Journal Supplement Series, 106, 143. This notebook file needs to be run first. 12 | 13 | The next notebook to run is: 2_fe_13_demo_check_model.ipynb -- This notebook load the previously created pickle containing the match attribute. In this notebook a density and emission measure are guessed from an 'em loci' plot and the predictions compard with the observations. 14 | 15 | The next notebook to run is: 3_fe_13_demo_chi2_search.ipynb -- This performs a brute force chi-squared search over the density range and finds the best fit density and emission measure. These best values are then inserted into the model, a prediction made and compared with the observations. 16 | 17 | The next notebook to run is: 4_fe_13_demo_mcmc.ipynb -- This performs a MCMC analysis of the spectra to determine the most likely density and emission measure from an analysis of the trace. The trace is also save for futher analysis. 18 | 19 | The next notebook to run is: 5_fe_13_demo_mcmc_trace_analyze.ipynb -- the load the trace so that it can be re-analyzed 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /jupyter_notebooks/tab2_1993_qs_fe_13.json: -------------------------------------------------------------------------------- 1 | {"filename": "/data2/svn/data/serts-eunis/serts/table2-1993-QS_fe_13.txt", "wvl0": [311.574, 312.171, 312.907, 318.129, 320.802, 321.464, 348.196, 359.658, 359.851], "intensity": [6.13, 17.8, 7.34, 6.09, 24.5, 8.64, 55.0, 28.4, 11.8], "intStd": [0.91, 2.99, 3.67, 1.16, 2.85, 1.46, 6.25, 3.56, 2.94], "dwvl": [0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04], "ions": ["fe_13", "fe_13", "fe_13", "fe_13", "fe_13", "fe_13", "fe_13", "fe_13", "fe_13"], "ref": ["Brosius, Jeffrey W.; Davila, Joseph M.; Thomas, Roger J.; Monsignori-Fossi, Brunella C.", "Measuring Active and Quiet-Sun Coronal Plasma Properties with Extreme-Ultraviolet Spectra from SERTS ", "1996, Astrophysical Journal Supplement v.106, p.143", "ADSref: https://ui.adsabs.harvard.edu/abs/1996ApJS..106..143B/abstract"]} -------------------------------------------------------------------------------- /licenses/LICENSE: -------------------------------------------------------------------------------- 1 | ISC software license 2 | 3 | Copyright (c) 2015, Kenneth P Dere kdere@gmu.edu 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /licenses/LICENSE.fortranformat: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Brendan Arnold 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel" 5 | ] 6 | build-backend = "setuptools.build_meta" 7 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | python_files = test_?*.py 3 | addopts = -p no:doctest 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | scipy 3 | matplotlib 4 | ipyparallel 5 | roman 6 | pyQt5 7 | -------------------------------------------------------------------------------- /rtd_environment.yml: -------------------------------------------------------------------------------- 1 | name: chiantipy 2 | dependencies: 3 | - python=3.6 4 | - astropy 5 | - numpy=1.14 6 | - scipy 7 | - matplotlib 8 | - ipython 9 | - ipyparallel 10 | - sphinx_rtd_theme 11 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [build_docs] 2 | source-dir = docs/source 3 | build-dir = docs/build 4 | all_files = 1 5 | 6 | [upload_docs] 7 | upload-dir = docs/build/html 8 | show-response = 1 9 | 10 | [pytest] 11 | minversion = 3.6 12 | norecursedirs = build docs/build 13 | 14 | 15 | [metadata] 16 | package_name = ChiantiPy 17 | description = a Python interface to the CHIANTI atomic database for astrophysical spectroscopy 18 | author = Ken Dere 19 | author_email = kdere@gmu.edu 20 | license = ISC 21 | url = https://github.com/chianti-atomic/ChiantiPy 22 | edit_on_github = True 23 | github_project = chianti-atomic/ChiantiPy 24 | 25 | 26 | [options.package_data] 27 | * = *.txt, *.rst 28 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | 5 | with open("README.rst", "r", encoding='utf-8') as fh: 6 | long_description = fh.read() 7 | 8 | 9 | setup(name = 'ChiantiPy', 10 | description = 'a Python interface to the CHIANTI atomic database for astrophysical spectroscopy', 11 | long_description = long_description, 12 | # long_description_content_type = text/rst, 13 | version = '0.15.2', 14 | author = 'Ken Dere', 15 | author_email = 'kdere@gmu.edu', 16 | url = 'https://github.com/chianti-atomic/ChiantiPy', 17 | packages = find_packages(), 18 | classifiers = [ 19 | 'Development Status :: 3 - Alpha', 20 | 'Environment :: Console', 21 | 'Intended Audience :: Science/Research', 22 | 'Intended Audience :: End Users/Desktop', 23 | 'License :: OSI Approved :: ISC License (ISCL)', 24 | 'Operating System :: POSIX :: Linux', 25 | 'Programming Language :: Python :: 3', 26 | 'Topic :: Scientific/Engineering :: Astronomy', 27 | 'Topic :: Scientific/Engineering :: Physics' 28 | ] 29 | ) 30 | --------------------------------------------------------------------------------