# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as itp
from math import *
def interp(x, max_gap=0.05):
sections = [[x[0]]]
# divide data into monotonic sections
for i in range(1, len(x)):
if x[i-1,0] < x[i,0] and x[i-1,1] >= x[i,1]:
sections[-1].append(x[i])
else:
sections.append([x[i]])
# interpolate within each section
for si, s in enumerate(sections):
if len(s) >= 2:
# use third-order polynomial of logarithmized data
spline = itp.make_interp_spline([log(d[0]) for d in s],
[np.log(d[1:]) for d in s], bc_type="natural")
for i in range(len(s) - 1, 0, -1):
nsub = log(s[i-1][0] / s[i][0]) / log(1 - max_gap)
if nsub > 1:
nsub = int(ceil(nsub))
xnew = s[i-1][0] * (s[i][0] / s[i-1][0]) ** (np.arange(1, nsub) / nsub)
s = s[:i] + [np.concatenate(([xnew[j]], d)) for j, d in enumerate(np.exp(spline(np.log(xnew))))] + s[i:]
sections[si] = s
return np.concatenate(sections)
# data from https://physics.nist.gov/PhysRefData/XrayMassCoef/tab4.html
rho_Ti = 4.54
mu_Ti = interp(np.fromstring("""
1.00000E-3 5.869E+3 1.50000E-3 2.096E+3 2.00000E-3 9.860E+2 3.00000E-3 3.323E+2
4.00000E-3 1.517E+2 4.96640E-3 8.380E+1 4.96640E-3 6.878E+2 5.00000E-3 6.838E+2
6.00000E-3 4.323E+2 8.00000E-3 2.023E+2 1.00000E-2 1.107E+2 1.50000E-2 3.587E+1
2.00000E-2 1.585E+1 3.00000E-2 4.972E+0 4.00000E-2 2.214E+0 5.00000E-2 1.213E+0
6.00000E-2 7.661E-1 8.00000E-2 4.052E-1 1.00000E-1 2.721E-1 1.50000E-1 1.649E-1
2.00000E-1 1.314E-1 3.00000E-1 1.043E-1
""", sep=" ").reshape((-1, 2)))
rho_I = 4.93
mu_I = interp(np.fromstring("""
1.00000E-3 9.096E+3 1.03542E-3 8.465E+3 1.07210E-3 7.863E+3 1.07210E-3 8.198E+3
1.50000E-3 3.919E+3 2.00000E-3 1.997E+3 3.00000E-3 7.420E+2 4.00000E-3 3.607E+2
4.55710E-3 2.592E+2 4.55710E-3 7.550E+2 4.70229E-3 7.123E+2 4.85210E-3 6.636E+2
4.85210E-3 8.943E+2 5.00000E-3 8.430E+2 5.18810E-3 7.665E+2 5.18810E-3 8.837E+2
6.00000E-3 6.173E+2 8.00000E-3 2.922E+2 1.00000E-2 1.626E+2 1.50000E-2 5.512E+1
2.00000E-2 2.543E+1 3.00000E-2 8.561E+0 3.31694E-2 6.553E+0 3.31694E-2 3.582E+1
4.00000E-2 2.210E+1 5.00000E-2 1.232E+1 6.00000E-2 7.579E+0 8.00000E-2 3.510E+0
1.00000E-1 1.942E+0 1.50000E-1 6.978E-1 2.00000E-1 3.663E-1 3.00000E-1 1.771E-1
""", sep=" ").reshape((-1, 2)))
rho_bone = 1.92
mu_bone = interp(np.fromstring("""
1.00000E-3 3.781E+3 1.03542E-3 3.452E+3 1.07210E-3 3.150E+3 1.07210E-3 3.156E+3
1.18283E-3 2.434E+3 1.30500E-3 1.873E+3 1.30500E-3 1.883E+3 1.50000E-3 1.295E+3
2.00000E-3 5.869E+2 2.14550E-3 4.824E+2 2.14550E-3 7.114E+2 2.30297E-3 5.916E+2
2.47200E-3 4.907E+2 2.47200E-3 4.962E+2 3.00000E-3 2.958E+2 4.00000E-3 1.331E+2
4.03810E-3 1.296E+2 4.03810E-3 3.332E+2 5.00000E-3 1.917E+2 6.00000E-3 1.171E+2
8.00000E-3 5.323E+1 1.00000E-2 2.851E+1 1.50000E-2 9.032E+0 2.00000E-2 4.001E+0
3.00000E-2 1.331E+0 4.00000E-2 6.655E-1 5.00000E-2 4.242E-1 6.00000E-2 3.148E-1
8.00000E-2 2.229E-1 1.00000E-1 1.855E-1 1.50000E-1 1.480E-1 2.00000E-1 1.309E-1
3.00000E-1 1.113E-1
""", sep=" ").reshape((-1, 2)))
rho_blood = 1.06
mu_blood = interp(np.fromstring("""
1.00000E-3 3.806E+3 1.03542E-3 3.473E+3 1.07210E-3 3.167E+3 1.07210E-3 3.173E+3
1.50000E-3 1.282E+3 2.00000E-3 5.737E+2 2.14550E-3 4.700E+2 2.14550E-3 4.722E+2
2.30297E-3 3.858E+2 2.47200E-3 3.149E+2 2.47200E-3 3.186E+2 2.64140E-3 2.633E+2
2.82240E-3 2.175E+2 2.82240E-3 2.219E+2 3.00000E-3 1.862E+2 3.60740E-3 1.088E+2
3.60740E-3 1.109E+2 4.00000E-3 8.187E+1 5.00000E-3 4.232E+1 6.00000E-3 2.458E+1
7.11200E-3 1.479E+1 7.11200E-3 1.514E+1 8.00000E-3 1.068E+1 1.00000E-2 5.519E+0
1.50000E-2 1.744E+0 2.00000E-2 8.428E-1 3.00000E-2 3.852E-1 4.00000E-2 2.715E-1
5.00000E-2 2.278E-1 6.00000E-2 2.057E-1 8.00000E-2 1.827E-1 1.00000E-1 1.695E-1
1.50000E-1 1.492E-1 2.00000E-1 1.358E-1 3.00000E-1 1.176E-1
""", sep=" ").reshape((-1, 2)))
rho_brain = 1.04
mu_brain = interp(np.fromstring("""
1.00000E-3 3.697E+3 1.03542E-3 3.373E+3 1.07210E-3 3.075E+3 1.07210E-3 3.087E+3
1.50000E-3 1.246E+3 2.00000E-3 5.576E+2 2.14550E-3 4.567E+2 2.14550E-3 4.656E+2
2.30297E-3 3.806E+2 2.47200E-3 3.108E+2 2.47200E-3 3.145E+2 2.64140E-3 2.601E+2
2.82240E-3 2.149E+2 2.82240E-3 2.193E+2 3.00000E-3 1.842E+2 3.60740E-3 1.077E+2
3.60740E-3 1.109E+2 4.00000E-3 8.191E+1 5.00000E-3 4.242E+1 6.00000E-3 2.468E+1
8.00000E-3 1.047E+1 1.00000E-2 5.410E+0 1.50000E-2 1.710E+0 2.00000E-2 8.281E-1
3.00000E-2 3.811E-1 4.00000E-2 2.702E-1 5.00000E-2 2.275E-1 6.00000E-2 2.058E-1
8.00000E-2 1.831E-1 1.00000E-1 1.701E-1 1.50000E-1 1.498E-1 2.00000E-1 1.364E-1
3.00000E-1 1.181E-1
""", sep=" ").reshape((-1, 2)))
rho_muscle = 1.05
mu_muscle = interp(np.fromstring("""
1.00000E-3 3.719E+3 1.03542E-3 3.393E+3 1.07210E-3 3.094E+3 1.07210E-3 3.100E+3
1.50000E-3 1.251E+3 2.00000E-3 5.594E+2 2.14550E-3 4.581E+2 2.14550E-3 4.626E+2
2.30297E-3 3.776E+2 2.47200E-3 3.085E+2 2.47200E-3 3.140E+2 2.64140E-3 2.597E+2
2.82240E-3 2.145E+2 2.82240E-3 2.160E+2 3.00000E-3 1.812E+2 3.60740E-3 1.057E+2
3.60740E-3 1.100E+2 4.00000E-3 8.127E+1 5.00000E-3 4.206E+1 6.00000E-3 2.446E+1
8.00000E-3 1.037E+1 1.00000E-2 5.356E+0 1.50000E-2 1.693E+0 2.00000E-2 8.205E-1
3.00000E-2 3.783E-1 4.00000E-2 2.685E-1 5.00000E-2 2.262E-1 6.00000E-2 2.048E-1
8.00000E-2 1.823E-1 1.00000E-1 1.693E-1 1.50000E-1 1.492E-1 2.00000E-1 1.358E-1
3.00000E-1 1.176E-1
""", sep=" ").reshape((-1, 2)))
rho_water = 1.0
mu_water = interp(np.fromstring("""
1.00000E-3 4.078E+3 1.50000E-3 1.376E+3 2.00000E-3 6.173E+2 3.00000E-3 1.929E+2
4.00000E-3 8.278E+1 5.00000E-3 4.258E+1 6.00000E-3 2.464E+1 8.00000E-3 1.037E+1
1.00000E-2 5.329E+0 1.50000E-2 1.673E+0 2.00000E-2 8.096E-1 3.00000E-2 3.756E-1
4.00000E-2 2.683E-1 5.00000E-2 2.269E-1 6.00000E-2 2.059E-1 8.00000E-2 1.837E-1
1.00000E-1 1.707E-1 1.50000E-1 1.505E-1 2.00000E-1 1.370E-1 3.00000E-1 1.186E-1
""", sep=" ").reshape((-1, 2)))
rho_breast = 1.02
mu_breast = interp(np.fromstring("""
1.00000E-3 3.263E+3 1.03542E-3 2.975E+3 1.07210E-3 2.710E+3 1.07210E-3 2.716E+3
1.50000E-3 1.088E+3 2.00000E-3 4.842E+2 2.14550E-3 3.961E+2 2.14550E-3 3.983E+2
2.30297E-3 3.250E+2 2.47200E-3 2.649E+2 2.47200E-3 2.686E+2 2.64140E-3 2.221E+2
2.82240E-3 1.831E+2 2.82240E-3 1.845E+2 3.00000E-3 1.546E+2 4.00000E-3 6.625E+1
5.00000E-3 3.407E+1 6.00000E-3 1.972E+1 8.00000E-3 8.320E+0 1.00000E-2 4.295E+0
1.50000E-2 1.378E+0 2.00000E-2 6.889E-1 3.00000E-2 3.403E-1 4.00000E-2 2.530E-1
5.00000E-2 2.186E-1 6.00000E-2 2.006E-1 8.00000E-2 1.808E-1 1.00000E-1 1.688E-1
1.50000E-1 1.493E-1 2.00000E-1 1.361E-1 3.00000E-1 1.179E-1
""", sep=" ").reshape((-1, 2)))
rho_adipose_tissue = 0.95
mu_adipose_tissue = interp(np.fromstring("""
1.00000E-3 2.628E+3 1.03542E-3 2.392E+3 1.07210E-3 2.176E+3 1.07210E-3 2.182E+3
1.50000E-3 8.622E+2 2.00000E-3 3.800E+2 2.47200E-3 2.053E+2 2.47200E-3 2.072E+2
2.64140E-3 1.707E+2 2.82240E-3 1.405E+2 2.82240E-3 1.420E+2 3.00000E-3 1.188E+2
4.00000E-3 5.054E+1 5.00000E-3 2.587E+1 6.00000E-3 1.494E+1 8.00000E-3 6.300E+0
1.00000E-2 3.268E+0 1.50000E-2 1.083E+0 2.00000E-2 5.677E-1 3.00000E-2 3.063E-1
4.00000E-2 2.396E-1 5.00000E-2 2.123E-1 6.00000E-2 1.974E-1 8.00000E-2 1.800E-1
1.00000E-1 1.688E-1 1.50000E-1 1.500E-1 2.00000E-1 1.368E-1 3.00000E-1 1.187E-1
""", sep=" ").reshape((-1, 2)))
plt.figure()
plt.plot(mu_I[:,0] * 1e3, mu_I[:,1] * rho_I, label="iodine", color="#886644")
plt.plot(mu_Ti[:,0] * 1e3, mu_Ti[:,1] * rho_Ti, label="titanium", color="#555555")
plt.plot(mu_bone[:,0] * 1e3, mu_bone[:,1] * rho_bone, label="bone", color="#aaaaaa")
plt.plot(mu_blood[:,0] * 1e3, mu_blood[:,1] * rho_blood, label="blood", color="#aa0000")
plt.plot(mu_muscle[:,0] * 1e3, mu_muscle[:,1] * rho_muscle, label="muscle", color="#ee2211")
plt.plot(mu_brain[:,0] * 1e3, mu_brain[:,1] * rho_brain, label="brain", color="#33aaff")
plt.plot(mu_water[:,0] * 1e3, mu_water[:,1] * rho_water, label="water", color="#0000ff")
plt.plot(mu_breast[:,0] * 1e3, mu_breast[:,1] * rho_breast, label="breast", color="#ff77aa")
plt.plot(mu_adipose_tissue[:,0] * 1e3, mu_adipose_tissue[:,1] * rho_adipose_tissue, label="adipose tissue", color="#ffaa33")
plt.gca().set_yscale('log')
plt.xlim(0, 250)
plt.ylim(1e-1, 1e1)
plt.ylabel(r"$\mu$ [cm${}^{-1}$]")
plt.xlabel("E [keV]")
plt.legend(borderaxespad=1.5, framealpha=1)
plt.grid()
plt.tight_layout()
plt.savefig("X-ray_attenuation_spectra_tissues_volume.svg")