<jupyter_start><jupyter_text>Warm-Hot IGM X-ray SpectrumFigure 10.6 from Chapter 10 of *Interstellar and Intergalactic Medium* by <NAME>, 2021, Cambridge University Press.Plot of detection of OVII Lyman-$\alpha$ x-ray absorption lines from the Warm-Hot intergalactic medium (WHIGM)along the line-of-sight to the x-ray bright quasar 1ES1553+113 at resdhifts z=0.355 and z=0.434.  Data wereobtained using the *XMM-Newton X-ray Telescope* and the Reflection Grating Spectrometer (RGS) instrument.Data from [Nicastro et al. 2018, Nature, 558, 406](https://ui.adsabs.harvard.edu/abs/2018Natur.558..406N),replotted using reduced data provided by <NAME> and <NAME>, The Ohio State University.<jupyter_code>%matplotlib inline

import math
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, LogLocator, NullFormatter

import warnings
warnings.filterwarnings('ignore',category=UserWarning, append=True)
warnings.filterwarnings('ignore',category=RuntimeWarning, append=True)<jupyter_output><empty_output><jupyter_text>Standard Plot FormatSetup the standard plotting format and make the plot. Fonts and resolution adopted follow CUP style.<jupyter_code>figName = 'Fig10_6' 

# graphic aspect ratio = width/height

aspect = 4.0/3.0 # 4:3

# Text width in inches - don't change, this is defined by the print layout

textWidth = 6.0 # inches

# output format and resolution

figFmt = 'png'
dpi = 600

# Graphic dimensions 

plotWidth = dpi*textWidth
plotHeight = plotWidth/aspect
axisFontSize = 10
labelFontSize = 8
lwidth = 0.5
axisPad = 5
wInches = textWidth 
hInches = wInches/aspect

# Plot filename

plotFile = f'{figName}.{figFmt}'

# LaTeX is used throughout for markup of symbols, Times-Roman serif font

plt.rc('text', usetex=True)
plt.rc('font', **{'family':'serif','serif':['Times-Roman'],'weight':'bold','size':'16'})

# Font and line weight defaults for axes

matplotlib.rc('axes',linewidth=lwidth)
matplotlib.rcParams.update({'font.size':axisFontSize})

# axis and label padding

plt.rcParams['xtick.major.pad'] = f'{axisPad}'
plt.rcParams['ytick.major.pad'] = f'{axisPad}'
plt.rcParams['axes.labelpad'] = f'{axisPad}'<jupyter_output><empty_output><jupyter_text>Convenience function Define a function to compute a Gaussian emission-line profile given the central wavelength,full-width at half maximum (FWHM), peak intensity, for an array of wavelengths, lam.Not pretty, not meant to be.<jupyter_code>def gauss(lam,cen,fwhm,pk):
    sig = fwhm/(2.0*math.sqrt(2.0*math.log(2)))
    arg = (lam-cen)*(lam-cen)/(2*sig*sig)
    return pk*np.exp(-arg)<jupyter_output><empty_output><jupyter_text>Read in the X-ray Spectra DataData are in a 6-column ASCII format: * wavelength - wavelength in Angstroms, range 8-30 * err_wavelength - wavelength error in Angstroms * flux - flux in Jansky (10$^{-26}$ erg s$^{-1}$ cm$^{-2}$ Hz$^{-1}$) * err_flux - flux error in Jansky * model - best fit model * continuum - continuum model component We will plot the fluxes normalized relative to the best fit continuum, as is conventional for absorption-linestudies at all wavelengths.The model for the lines will be represented by Gaussian functions of the instrumental width of the RGSinstrument (0.08-Angstroms), and estimates of the central wavelength and absorbed flux.  The model absorptionlines are meant to be illustrative, and do not represent a statistically-rigorous fit to these data.<jupyter_code># RGS1 data

dataFile = 'Nicastro2018_RGS1.txt'

data = pd.read_csv(dataFile,sep=r'\s+',comment='#')
wave1 = np.array(data['wavelength'])
errWave1 = np.array(data['err_wavelength'])
flux1 = np.array(data['flux'])
errFlux1 = np.array(data['err_flux'])
fluxMod1 = np.array(data['model'])
fluxCont1 = np.array(data['continuum'])

# normalized flux and errors

fluxNorm1 = flux1/fluxCont1
ferrNorm1 = errFlux1/fluxCont1

# RGS2 data

dataFile = 'Nicastro2018_RGS2.txt'

data = pd.read_csv(dataFile,sep=r'\s+',comment='#')
wave2 = np.array(data['wavelength'])
errWave2 = np.array(data['err_wavelength'])
flux2 = np.array(data['flux'])
errFlux2 = np.array(data['err_flux'])
fluxMod2 = np.array(data['model'])
fluxCont2 = np.array(data['continuum'])

# normalized flux and errors

fluxNorm2 = flux2/fluxCont2
ferrNorm2 = errFlux2/fluxCont2

# Plotting Limits

xMin = 28.5  # Angstroms
xMax = 32.0

yMin = 0.6 # normalized flux
yMax = 1.2 # 

# model absorption lines, OVII Ly-alpha, z=0.3551 and 0.4339

fwhm = 0.08 # Angstroms, instrumental width

cen1 = 29.275 # Angstroms
pk1 = 1.0-0.85

cen2 = 30.976 # Angstroms
pk2 = 1.0-0.70

waveModel = np.linspace(xMin,xMax,501)
fluxModel = 1.0 - gauss(waveModel,cen1,fwhm,pk1) - gauss(waveModel,cen2,fwhm,pk2)<jupyter_output><empty_output><jupyter_text>Make the plotRGS channel 1 in black, RGS channel 2 in gray.  Error bars on the wavelengths and fluxes, model absorptionlines as Gaussian with the parameters reported in the Nicastro et al. paper.<jupyter_code>fig,ax = plt.subplots()

fig.set_dpi(dpi)
fig.set_size_inches(wInches,hInches,forward=True)

ax.tick_params('both',length=6,width=lwidth,which='major',direction='in',top='on',right='on')
ax.tick_params('both',length=3,width=lwidth,which='minor',direction='in',top='on',right='on')

# Limits

plt.xlim(xMin,xMax)
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(0.2))
plt.xlabel(r'Wavelength [\AA]',fontsize=axisFontSize)

plt.ylim(yMin,yMax)
plt.ylabel(r'Data/Continuum',fontsize=axisFontSize)

plt.errorbar(wave1,fluxNorm1,xerr=errWave1,yerr=ferrNorm1,color='black',fmt='o',ms=1,zorder=10,lw=0.5)
plt.errorbar(wave2,fluxNorm2,xerr=errWave2,yerr=ferrNorm2,color='#666666',fmt='o',ms=1,zorder=10,lw=0.5)

# Model showing the absorption line

plt.plot(waveModel,fluxModel,'-',lw=1.0,color='black')
plt.text(cen1,1-pk1-0.025,r'O{\sc vii}',color='black',ha='center',va='top',fontsize=axisFontSize)
plt.text(cen1,1-pk1-0.055,r'(z=0.355)',color='black',ha='center',va='top',fontsize=labelFontSize)

plt.text(cen2,1-pk2-0.025,r'O{\sc vii}',color='black',ha='center',va='top',fontsize=axisFontSize)
plt.text(cen2,1-pk2-0.055,r'(z=0.434)',color='black',ha='center',va='top',fontsize=labelFontSize)

plt.plot()
plt.savefig(plotFile,bbox_inches='tight',facecolor='white')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13906969360215907, 'fraction_numerical': 0.03937132878234641, 'mean_word_length': 6.359813084112149, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '301714', 'license': 'CC0-1.0', 'n_tokens_mistral': 2457, 'n_tokens_neox': 2233, 'n_words': 516, 'path': 'Chapter10/Fig10_6_Nicastro2018.ipynb', 'repo_name': 'CambridgeUniversityPress/Interstellar-and-Intergalactic-Medium', 'size': '6319'}