Previous topic

Random-point crossover genetic algorithm with demo GUI

Next topic

Advanced plotting

This Page

An interactive spectrum normalizerΒΆ

The following script uses the matplotlib widget to normalise a spectrum using a spline fit on user-defined points.

When saved to file, the user can invoke the script via the terminal with the command:

$:> python HD50230.txt

or any other text file containing two columns (wavelength, flux). You can download the example file here.

When started, you get a window like this:


A user can left/right-click to select/deselect continuum points:


Hitting enter fits the splines throught the continuum points:


Hitting n normalises the spectrum:


The user can write the result to a file with w and reset to the original spectrum with r.

import pylab as plt
import numpy as np
from scipy.interpolate import splrep,splev
import sys
import os

def onclick(event):
    # when none of the toolbar buttons is activated and the user clicks in the
    # plot somewhere, compute the median value of the spectrum in a 10angstrom
    # window around the x-coordinate of the clicked point. The y coordinate
    # of the clicked point is not important. Make sure the continuum points
    # `feel` it when it gets clicked, set the `feel-radius` (picker) to 5 points
    toolbar = plt.get_current_fig_manager().toolbar
    if event.button==1 and toolbar.mode=='':
        window = ((event.xdata-5)<=wave) & (wave<=(event.xdata+5))
        y = np.median(flux[window])

def onpick(event):
    # when the user clicks right on a continuum point, remove it
    if event.mouseevent.button==3:
        if hasattr(event.artist,'get_label') and event.artist.get_label()=='cont_pnt':

def ontype(event):
    # when the user hits enter:
    # 1. Cycle through the artists in the current axes. If it is a continuum
    #    point, remember its coordinates. If it is the fitted continuum from the
    #    previous step, remove it
    # 2. sort the continuum-point-array according to the x-values
    # 3. fit a spline and evaluate it in the wavelength points
    # 4. plot the continuum
    if event.key=='enter':
        cont_pnt_coord = []
        for artist in plt.gca().get_children():
            if hasattr(artist,'get_label') and artist.get_label()=='cont_pnt':
            elif hasattr(artist,'get_label') and artist.get_label()=='continuum':
        cont_pnt_coord = np.array(cont_pnt_coord)[...,0]
        sort_array = np.argsort(cont_pnt_coord[:,0])
        x,y = cont_pnt_coord[sort_array].T
        spline = splrep(x,y,k=3)
        continuum = splev(wave,spline)

    # when the user hits 'n' and a spline-continuum is fitted, normalise the
    # spectrum
    elif event.key=='n':
        continuum = None
        for artist in plt.gca().get_children():
            if hasattr(artist,'get_label') and artist.get_label()=='continuum':
                continuum = artist.get_data()[1]
        if continuum is not None:

    # when the user hits 'r': clear the axes and plot the original spectrum
    elif event.key=='r':

    # when the user hits 'w': if the normalised spectrum exists, write it to a
    # file.
    elif event.key=='w':
        for artist in plt.gca().get_children():
            if hasattr(artist,'get_label') and artist.get_label()=='normalised':
                data = np.array(artist.get_data())
                print('Saved to file')

if __name__ == "__main__":
    # Get the filename of the spectrum from the command line, and plot it
    filename = sys.argv[1]
    wave,flux = np.loadtxt(filename).T
    spectrum, = plt.plot(wave,flux,'k-',label='spectrum')

    # Connect the different functions to the different events
    plt.gcf().canvas.mpl_connect('pick_event',onpick) # show the window
Copyright: Smithsonian Astrophysical Observatory under terms of CC Attribution 3.0 Creative Commons