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:

A UV/Vis spectrum

The syntax highlighting for this page was produced using Pygments.