PlotBand
A Python script for simulating UV/Vis spectra
There are a number of tools for simulating UV/Vis spectra (such as GaussSum), but sometimes you might want to use a quantum chemistry code that isn't supported (or something else exotic). PlotBand is a simple Python3 script that uses matplotlib (and numpy) to generate a UV/Vis spectrum using only excitation energies and oscillator strengths. Using matplotlib means the script is easily hackable for producing publication-ready graphics. If you find the script useful, or find any problems, then please let us know.
PlotBand
import sys
# Check for numpy and matplotlib, try to exit gracefully if not found
import imp
try:
imp.find_module('numpy')
foundnp = True
except ImportError:
foundnp = False
try:
imp.find_module('matplotlib')
foundplot = True
except ImportError:
foundplot = False
if not foundnp:
print("Numpy is required. Exiting")
sys.exit()
if not foundplot:
print("Matplotlib is required. Exiting")
sys.exit()
import numpy as np
import matplotlib.pyplot as plt
# Adjust the following three variables to change which area of the spectrum is plotted and number of points used
# in plotting the curves
start=200
finish=380
points=300
# A sqrt(2) * standard deviation of 0.4 eV is 3099.6 nm. 0.1 eV is 12398.4 nm. 0.2 eV is 6199.2 nm.
stdev = 12398.4
# For Lorentzians, gamma is half bandwidth at half peak height (nm)
gamma = 12.5
# Excitation energies in nm
bands = [330,328,328,308,290,290,288,283,276,270,268]
# Oscillator strengths (dimensionless)
f = [7.90e-7,0.00,7.16e-4,1.02e-2,1.38e-6,2.94e-7,0.00,8.86e-4,1.54e-5,1.25e-2,9.31e-3]
# Basic check that we have the same number of bands and oscillator strengths
if len(bands) != len(f):
print('Number of bands does not match the number of oscillator strengths.')
sys.exit()
# Information on producing spectral curves (Gaussian and Lorentzian) is adapted from:
# P. J. Stephens, N. Harada, Chirality 22, 229 (2010).
# Gaussian curves are often a better fit for UV/Vis.
def gaussBand(x, band, strength, stdev):
"Produces a Gaussian curve"
bandshape = 1.3062974e8 * (strength / (1e7/stdev)) * np.exp(-(((1.0/x)-(1.0/band))/(1.0/stdev))**2)
return bandshape
def lorentzBand(x, band, strength, stdev, gamma):
"Produces a Lorentzian curve"
bandshape = 1.3062974e8 * (strength / (1e7/stdev)) * ((gamma**2)/((x - band)**2 + gamma**2))
return bandshape
x = np.linspace(start,finish,points)
composite = 0
for count,peak in enumerate(bands):
thispeak = gaussBand(x, peak, f[count], stdev)
# thispeak = lorentzBand(x, peak, f[count], stdev, gamma)
composite += thispeak
fig, ax = plt.subplots()
ax.plot(x,composite)
plt.xlabel('$\lambda$ / nm')
plt.ylabel('$\epsilon$ / L mol$^{-1}$ cm$^{-1}$')
plt.show()
If the script doesn't generate anything, it may be that you don't have a matplotlib backend that is capable of interactive plotting. In that case you could try substituting the line plt.show() with plt.savefig('foo.png').
The resulting image should look like this: