The Singular Value Decomposition (SVD) ======================================== .. p23ready PyA's `SVD` class provides the means to carry out a singular value decomposition as is, e.g., useful to recover line profiles. .. currentmodule:: PyAstronomy.pyasl .. autoclass:: SVD :members: Example: Delta functions and rotational broadening -------------------------------------------------- :: import numpy as np import matplotlib.pylab as plt from PyAstronomy import pyasl # Get some "data" wvl = np.arange(5000., 5010., 0.02) template = np.ones(len(wvl)) # There are two sharp lines in the template template[100] = 0.5 template[115] = 0.3 # Apply rotational broadening to the delta spectrum nflux = pyasl.rotBroad(wvl, template, 0.5, 23.45, edgeHandling="firstlast") # Carry out decomposition svd = pyasl.SVD() # Use 51 bins for the width of the broadening function. # Needs to be an odd number. svd.decompose(template, 51) # Obtain the broadening function needed to # recover "observed" spectrum. Note that the # edges (51/2 bins) will actually be neglected. b = svd.getBroadeningFunction(nflux) # Get the model, which results from the broadening # function and the template; obtain the indices # where it applies, too. m, mind = svd.getModel(b, modelIndices=True) # Plot the outcome plt.plot(b, 'bp-') plt.plot(mind, m, 'r.') plt.plot(nflux, 'g--') plt.show() Example: Adding noise and neglecting singular values ------------------------------------------------------ :: import numpy as np import matplotlib.pylab as plt from PyAstronomy import pyasl # Get some "data" wvl = np.arange(5000., 5010., 0.02) template = np.ones(len(wvl)) # There are two sharp lines in the template template[100] = 0.5 template[115] = 0.3 # Apply rotational broadening to the delta spectrum nflux = pyasl.rotBroad(wvl, template, 0.5, 23.45, edgeHandling="firstlast") nflux += np.random.normal(0., 0.005, len(nflux)) # Carry out decomposition svd = pyasl.SVD() svd.decompose(template, 51) # Access the singular values sv = svd.getSingularValues() # Calculate the reduced chi square as a function of the number # of singular values neglected in the calculation of the # model. chi = [] for i in range(1, len(sv), 5): b = svd.getBroadeningFunction(nflux, wlimit=sorted(sv)[i]) m, mind = svd.getModel(b, modelIndices=True, asarray=True) chi.append(((nflux[mind] - m)**2/0.005**2).sum() / len(mind)) plt.title("Reduced $\chi^2$ vs. number of neglected singular values") plt.plot(range(1, len(sv), 5), chi, 'bp-') plt.show()