<jupyter_start><jupyter_text>Detecting Peaks in a Spectrum<jupyter_code>import spectrumlib
import matplotlib.pyplot as plt
import numpy as np
%pylab inline
filename = 'shear.png'
spectrum = spectrumlib.getSpectrum(filename)
plt.plot(spectrum)<jupyter_output><empty_output><jupyter_text>First, find the relative maxima of the spectrum.<jupyter_code>from scipy.signal import argrelextrema
maxes = argrelextrema(spectrum, np.greater, order=2)
print maxes[0]
for x in maxes[0]:
    plt.axvline(x)
plt.plot(spectrum, color='r')<jupyter_output><empty_output><jupyter_text>This clearly gives us way too many local maxima. So, next, we try the `find_peaks_cwt` function from `scipy.signal`, which uses wavelets.<jupyter_code>from scipy.signal import find_peaks_cwt
cwt_peaks = find_peaks_cwt(spectrum, np.arange(10,15))
print cwt_peaks
for x in cwt_peaks:
    plt.axvline(x)
plt.plot(spectrum, color='r')<jupyter_output><empty_output><jupyter_text>This is better, in that we lost all the spurious values, but it doesn't match that well, and we don't get thedouble-peak (near 150) anymore.https://gist.github.com/endolith/250860 has a python translation of a matlab peak-detection script. Downloaded as `peakdetect.py`<jupyter_code>import peakdetect
peaks, valleys = peakdetect.peakdet(spectrum, 3)
print peaks
for index, val in peaks:
    plt.axvline(index)
plt.plot(spectrum, color='r')<jupyter_output><empty_output><jupyter_text>This is a pretty decent result, which we should be able to use for matching with known spectra.  Calibration The sample spectrum above is for a fluorescent lamp. This is a known spectrum, that we can use for calibration. Here is a labelled plot of the spectrum: ![Alt text](640px-Fluorescent_lighting_spectrum_peaks_labelled.gif)"Fluorescent lighting spectrum peaks labelled". Licensed under CC BY-SA 3.0 via Wikimedia Commons - http://commons.wikimedia.org/wiki/File:Fluorescent_lighting_spectrum_peaks_labelled.gif/media/File:Fluorescent_lighting_spectrum_peaks_labelled.gif Visually, this appears to match pretty well with our spectrum. We calibrate the x-axis by matching two points with the known spectrum. Let's use the strongest two peaks: 5, at 546.5 nm (from Mercury) and 12, at 611.6 nm (from Europium). In our spectrum, peak 4 has a higher intensity than peak 12, but we'll use peak 12 anyway, because peaks 4 and 5 are too close together to get an accurate calibration.<jupyter_code>intensities = sorted([intensity for index, intensity in peaks])
peak5 = [index for index, intensity in peaks if intensity == intensities[-1]][0]
peak12 = [index for index, intensity in peaks if intensity == intensities[-3]][0]
print peak5, peak12<jupyter_output>159.0 229.0<jupyter_text>Linear scale between index numbers and wavelengths:`wavelength = m*index + b`<jupyter_code>peak5_wl = 546.5
peak12_wl = 611.6
m = (peak12_wl - peak5_wl)/(peak12 - peak5)
b = peak5_wl - m*peak5
print m, b
wavelengths = [m*index + b for index in range(len(spectrum))]
plt.plot(wavelengths, spectrum)
plt.xlabel('Wavelength (nm)')
plt.ylabel('Intensity')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09235255994815295, 'fraction_numerical': 0.024951393389500972, 'mean_word_length': 6.162412993039443, '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': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '162355', 'license': 'MIT', 'n_tokens_mistral': 1100, 'n_tokens_neox': 981, 'n_words': 327, 'path': 'peak-detection.ipynb', 'repo_name': 'greenca/diy-spectrometer', 'size': '3086'}