Skip to content

IDL and ChiantiPy gives different results. #420

@MadFisa

Description

@MadFisa

Hi,

I was generating a lookup table for spectra of individual elements for creating a look up table. While doing the analysis, I found that my results were different from my collaborator. On further investigation, we found that the spectra generated by the IDL scripts he used was different from the ones I generated using the ChiantiPy. I will attach the results below. The plots are generated using mspectrum class with unity abundance. If images looks too small in github, downloading and viewing should help.

This is the continuum for each element plotted with IDL using solid lines and Python with dotted lines. Different colors are different temperatures.

Continnuum_flux

We can see there is a difference in the values after first row of elements. Next plot shows the ratio IDL/Python for the elements. Note that ratio for Cu, V and Sc is in 1e10s . These particular elements show biggest difference and as far as I know, do not have ions in CHIANTI.

Continnuum_ratio

Next plot shows line calculation for each elements for a particular temperature with IDL in solid blue and python ones in dotted orange.

lines_flux

Here also we can see some differences. Next plot is the ratio.
lines_ratio

I have also attached the codes used to generate the IDL and python spectra.

IDL code

pro getSpec

!PATH = expand_path('+/home/mithun/Bin/chianti/idl/')+':'+ !PATH
use_chianti, '/home/mithun/Bin/chianti/dbase'

temperature=10^[6.5,6.8,7.0,7.2]

edensity=1d10

allelements=['h','he','li','be','b','c','n','o','f','ne','na','mg','al','si','p','s','cl','ar','k','ca','sc','ti','v','cr','mn','fe','co','ni','cu','zn']
ents_Z=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]

masterlist_file='/home/mithun/Bin/chianti/dbase/masterlist/masterlist.ions'
read_masterlist,masterlist_file,all_ions

n_elem=n_elements(allelements)
n_temperature=n_elements(temperature)

wmin=0.8
wmax=124
wstep=0.01

nwbins=long((wmax-wmin)/wstep)+1
allLineSpec=dblarr(nwbins,n_temperature,n_elem)
allContSpec=dblarr(nwbins,n_temperature,n_elem)

abund_file='/home/mithun/Bin/chianti/dbase/abundance/unity.abund'

restore,'lineSpec_CHIANTI_10p0p2.sav'

for j=0,n_elem-1 do begin

    ion_list=all_ions[where(STRMATCH(all_ions, allelements[j]+'_'+'*') eq 1)]
isothermal, wmin,wmax,wstep,temperature,lmbda,spectrum,list_wvl,list_ident,$
      edensity=edensity,/ergs,sngl_ion=ion_list,abund_name=abund_file,ioneq_name=!ioneq_file,$
      /all  

    allLineSpec(*,*,j)=spectrum     

em_int=make_array(n_temperature,value=1,/double)
temp=temperature
ioneq_name=!ioneq_file
freebound, temp,lmbda,fb, $
           em_int=em_int, abund_file=abund_file, $
           ioneq_file=ioneq_name,Element=allelements[j]
freefree,temp,lmbda,ff, $
         em_int=em_int, abund_file=abund_file, $
         ioneq_file=ioneq_name,Element=allelements[j]
two_photon, temp,  lmbda, two_phot, $
            edensity=edensity, em_int=em_int, abund_file=abund_file, $
            ioneq_file=ioneq_name,Element=allelements[j]
totcont=(fb+ff+two_phot)/1d40*wstep

    allContSpec(*,*,j)=totcont 

endfor

save,lmbda,temperature,allContSpec,file='contSpec_CHIANTI_10p0p2.sav'
save,lmbda,temperature,allLineSpec,file='lineSpec_CHIANTI_10p0p2.sav'

stop
end

Python code

#!/usr/bin/env python3

import ChiantiPy.core as ch
import matplotlib.pyplot as plt
import numpy as np
from scipy.io import readsav

#%% Define params
CALCULATE = True  # Flag to decide whether to do calcuation again or use stored ones.

elements_list = [
    "H",
    "He",
    "Li",
    "Be",
    "B",
    "C",
    "N",
    "O",
    "F",
    "Ne",
    "Na",
    "Mg",
    "Al",
    "Si",
    "P",
    "S",
    "Cl",
    "Ar",
    "K",
    "Ca",
    "Sc",
    "Ti",
    "V",
    "Cr",
    "Mn",
    "Fe",
    "Co",
    "Ni",
    "Cu",
    "Zn",
    "Ga",
    "Ge",
    "As",
    "Se",
    "Br",
    "Kr",
    "Rb",
    "Sr",
    "Y",
    "Zr",
    "Nb",
    "Mo",
    "Tc",
    "Ru",
    "Rh",
    "Pg",
    "Ag",
    "Cd",
    "In",
    "Sn",
]

elements = elements_list[:30]

test_elements = elements[:5]

#%% Load idl data
dLine = readsav("lineSpec_CHIANTI_10p0p2.sav") # Line spectra (nelem,ntemperature,nwave) 
dCont = readsav("contSpec_CHIANTI_10p0p2.sav") # Continuum spectra  (nelem,ntemperature,nwave) 

temperature = np.asarray(dLine["temperature"], dtype=np.float64)
temp_label = [f"logT={np.log10(temperature_i):.2f}" for temperature_i in temperature]
wvl = np.asarray(dLine["lmbda"], dtype=np.float64)
dwvl = np.concatenate([np.diff(wvl), [0.01]])  # wavelength bin size

#%% Create spectra
# Doing the same calcuation as idl in python
cont_file_name = "ChiantiPy0p15p0ContSpec_CHIANTI10p02_unfiltered.npy"
line_file_name = "ChiantiPy0p15p0LineSpec_CHIANTI10p02_unfiltered.npy"
if CALCULATE:
    density = 1e10
    py_ContSpec = []
    py_LineSpec = []
    for element in elements:
        s_cont = ch.mspectrum(
            temperature,
            density,
            wvl,
            verbose=1,
            abundance="unity",
            elementList=[element],
            doContinuum=1,
            doLines=0,
            # filter=(dirac_delt,1000)
        )
        s_line = ch.mspectrum(
            temperature,
            density,
            wvl,
            verbose=1,
            abundance="unity",
            elementList=[element],
            doContinuum=0,
            doLines=1,
            # filter=(dirac_delt,1000)
        )

        # Multiply by wavelenght bin size to convert from per AA to  to  total flux in the bin.
        py_ContSpec.append(np.multiply(dwvl, s_cont.Spectrum["intensity"]))
        py_LineSpec.append(np.multiply(dwvl, s_line.Spectrum["intensity"]))

    #%% Save to text
    py_ContSpec = np.array(py_ContSpec)
    py_LineSpec = np.array(py_LineSpec)
    np.save(cont_file_name, py_ContSpec)
    np.save(line_file_name, py_LineSpec)

#%% Load from text
py_ContSpec = np.load(cont_file_name)
py_LineSpec = np.load(line_file_name)
#%% Plot Continuum
fig1, ax1 = plt.subplots(ncols=5, nrows=6, figsize=(16, 9), sharex=True)
fig1.set_tight_layout(True)
fig1.suptitle(r"flux$(erg \; s^{-1} sr^{-1} em^{-1})$ vs wavelength$(\AA^{-1})$")
fig2, ax2 = plt.subplots(ncols=5, nrows=6, figsize=(16, 9), sharex=True)
fig2.set_tight_layout(True)
fig2.suptitle("ratio vs wavelength")
ax1 = ax1.flat
ax2 = ax2.flat
for i, el in enumerate(elements):
    ax1[i].set_title(el)
    ax1[i].plot(
        wvl,
        dCont.allContSpec[i, :, :].T,
    )
    ax1[i].set_yscale("log")
    ax1[i].set_xscale("log")
    ax1[i].set_prop_cycle(None)  # Resetting the color cycle
    ax1[i].plot(
        wvl,
        py_ContSpec[i, :, :].T,
        "--",
    )
    ax1[i].set_ylim([1e-32, 1e-20])
    ratio = dCont.allContSpec[i, :, :] / py_ContSpec[i, :, :]
    ax2[i].plot(
        wvl,
        ratio.T,
    )
    ax2[i].set_title(f"{el}_ratio")
    # ax2[i].set_xscale("log")

fig1.supxlabel("Wavelength (Armstrong)")
fig1.supylabel("flux")
fig1.legend(temp_label)
fig2.supxlabel("Wavelength (Armstrong)")
fig2.supylabel("IDL/Py ratio")
fig2.legend(temp_label)
plt.show()

#%% Plot Lines
fig1, ax1 = plt.subplots(ncols=5, nrows=6, figsize=(16, 9))
fig1.set_tight_layout(True)
fig2, ax2 = plt.subplots(ncols=5, nrows=6, figsize=(16, 9))
fig2.set_tight_layout(True)
ax1 = ax1.flat
ax2 = ax2.flat
temp_idx = 2  # Only plotting temperature with this index for clarity
for i, el in enumerate(elements):
    ax1[i].set_title(el)
    ax1[i].plot(wvl, dLine.alllinespec[i, temp_idx, :].T, label=temperature)
    ax1[i].set_yscale("log")
    ax1[i].set_xscale("log")
    ax1[i].plot(wvl, py_LineSpec[i, temp_idx, :].T, "--", label=temperature)
    ax1[i].set_ylim([1e-32, 1e-20])
    ax1[i].set_prop_cycle(None)  # Resetting the color cycle
    ratio = dLine.alllinespec[i, temp_idx, :] / py_LineSpec[i, temp_idx, :]
    ax2[i].plot(wvl, ratio.T, label=temperature)
    ax2[i].set_title(f"{el}_ratio")
    ax2[i].set_xscale("log")
fig1.suptitle(
    r"flux$(erg \; s^{-1} sr^{-1} em^{-1})$ vs wavelength$(\AA^{-1})$ "
    + f"{temp_label[temp_idx]}"
)
fig1.supylabel("flux")
fig1.legend(["IDL", "Python"])
fig2.supxlabel("Wavelength (Armstrong)")
fig2.supylabel("IDL/Py ratio")
# fig2.legend(np.log10(temperature))
plt.show()

I am not sure what is the reason for this discrepancy, especially in the continuum. I am sorry if its as simple as missing some keyword arguments. Is this discrepancy known?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions