Example #1
0
File: AtmCorr.py Project: kvyh/kpy
def handle_create(outname=None, filelist=[], plot_filt=False):
    """Create standard star correction. Units are erg/s/cm2/Ang

    Read in the std-correction vector for each standard star, massage
    the correction (see below) and output an ensemble correction.

    Args:
        outname (str): name for resulting correction array (def: atm-corr.npy)
        filelist (list): list of standard star extractions (e.g. sp_STD-\*.npy)
        plot_filt (bool): set to plot intermediate filtered steps (def: False)

    Returns:
        dict: A dictionary containing the ensemble correction and some
        details::

            {   "nm": wavelengths (nm),
                "maxnm": maximum wavelength,
                "correction": the correction spectrum,
                "doc": "Correct ph/10 m/nm to erg/s/cm2/ang",
                "Nspec": number of spectra used,
                "correction_std": STDev of ensemble corrections,
                "outname": outname (see Parameters),
                "files": filelist (see Parameters),
                "when": timestamp string,
                "user": user who ran the process    }

    Note:
        Writes a \*.npy file with the resulting correction

    """

    if outname is None:
        outname = 'atm-corr.npy'

    ll = Wavelength.fiducial_spectrum()
    corrs = []
    corr_vals = []
    legend = [
        "corr",
    ]
    filt_legend = ["orig"]
    maxnm = 915.
    for ifile in filelist:
        """ Filename is sp_STD-nnnnn_obs*.npy """

        # Try to read input file
        try:
            data = np.load(ifile)[0]
        except:
            raise Exception("Not able to load %s. " % ifile)

        # Check quality of extraction
        if data["quality"] > 0:
            print "Bad std extraction in %s" % ifile
            continue

        # Check for calculated correction
        if "std-correction" not in data.keys():
            print "No std-correction vector in %s" % ifile
            continue
        correction = data['std-correction']

        # What was the maximum wavelength?
        if "std-maxnm" in data.keys():
            if data['std-maxnm'] > maxnm:
                maxnm = data['std-maxnm']
        # Convert file named sp_STD-nnnn_obs* to a name compaitable
        # with Standards.py.  First strip of "sp_STD-"
        pred = ifile[7:]
        pred = pred.split("_")[0]
        legend.append(pred)
        pred = pred.lower().replace("+", "").replace("-", "_")
        print ifile, pred, pred in Stds.Standards
        # Are we in our list of standard stars?
        if pred not in Stds.Standards:
            print(
                "File named '%s' is reduced to '%s' and no such standard "
                "seems to exist." % (ifile, pred))
            continue
        # Record median correction in ROI
        roi = (ll > 600) & (ll < 850)
        corr_vals.append(np.median(correction[roi]))
        # Normalize each correction by the median value
        correction /= corr_vals[-1]
        corrs.append(correction)
    # END: for ifile in filelist:

    # Rescale each correction and scale to erg/s/cm2/Ang
    corrs = np.array(corrs)
    erg_s_cm2_ang = corrs * np.median(corr_vals) * 1e-16
    # Take the median of the correction vectors
    the_corr = scipy.stats.nanmedian(erg_s_cm2_ang, 0)
    # Fit red end unless we are calibrated out there
    if not np.isfinite(the_corr).all() and maxnm < 1000.0:
        print "Fitting red end"
        # Fit polynomial to extrapolate correction
        redend = (ll > 880) & (ll < maxnm)
        ss = np.poly1d(np.polyfit(ll[redend], the_corr[redend], 2))
        # Insert extrapolation back into correction vector
        redend = (ll > maxnm)
        the_corr[redend] = ss(ll[redend])

    # Plot data, if requested
    if plot_filt:
        pl.figure(2)
        pl.clf()
        pl.grid(True)
        pl.ylim(1e-20, 1e-15)
        pl.semilogy(ll, the_corr, linewidth=1)
        pl.xlabel("Wavelength [nm]")
        pl.ylabel("Correction [erg/s/cm cm/Ang]")
        pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    """
    # Now clean over the Balmer series (skip this for now)
    balmers = [656.3, 486.1, 434.0, 410.2, 397.0]
    #balmers = [656.3, 486.1, 434.0]
    for balmer in balmers:
        #pl.figure(3)
        line_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.01)[0])
        broad_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.04)[0])
        broad_ll = list(broad_ROI)
        broad_ll.sort()
        #pl.plot(ll[broad_ll], the_corr[broad_ll])
        around_line_ROI = list(broad_ROI - line_ROI)
        #pl.plot(ll[around_line_ROI], the_corr[around_line_ROI],'^')
        fit = np.poly1d(np.polyfit(ll[around_line_ROI],
            the_corr[around_line_ROI], 5))
        to_fix = list(line_ROI)
        #the_corr[to_fix] = fit(ll[to_fix])
        #pl.plot(ll[to_fix], the_corr[to_fix])
        #pl.show()
        """

    # Plot intermediate correction
    if plot_filt:
        pl.semilogy(ll, the_corr * 4., linewidth=2)
        filt_legend.append("Balmer*4")
    # Filter correction to remove spectral features and leave response alone
    the_corr = scipy.signal.savgol_filter(the_corr, 9, 5)
    # Plot intermediate correction
    if plot_filt:
        pl.semilogy(ll, the_corr * 2., linewidth=2)
        filt_legend.append("Filtered*2")
        pl.semilogy(ll, the_corr, linewidth=2)
        filt_legend.append("Filtered")
        pl.legend(filt_legend)
        pl.show()

    # Plot data
    pl.figure(1)
    pl.clf()
    pl.grid(True)
    pl.ylim(1e-20, 1e-15)
    pl.semilogy(ll, the_corr, linewidth=4)
    for ix, e in enumerate(erg_s_cm2_ang):
        pl.semilogy(ll, e * corr_vals[ix] / np.mean(corr_vals))

    pl.xlabel("Wavelength [nm]")
    pl.ylabel("Correction [erg/s/cm cm/Ang]")
    pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    pl.legend(legend)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        pl.savefig("Standard_Correction.pdf")

    print("Mean cor: %10.3g, Sigma cor: %10.3g" %
          (np.mean(corr_vals) * 1e-16, np.std(corr_vals) * 1e-16))
    maxnm = np.min([maxnm, np.max(ll)])
    print "Max nm: %7.2f" % maxnm

    # Construct result
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        res = {
            "nm": ll,
            "maxnm": maxnm,
            "correction": the_corr,
            "doc": "Correct ph/10 m/nm to erg/s/cm2/ang",
            "Nspec": len(corrs),
            "correction_std": np.nanstd(erg_s_cm2_ang, 0),
            "outname": outname,
            "files": filelist,
            "when": '%s' % datetime.datetime.now(),
            "user": os.getlogin()
        }

    np.save(outname, [res])
    return res
Example #2
0
def handle_create(outname=None, filelist=[]):
    ''' Create standard star correction. Units are erg/s/cm2/Ang '''

    if outname is None: outname = 'atm-corr.npy'

    ll = Wavelength.fiducial_spectrum()
    spectra = []
    corrs = []
    corr_vals = []
    for file in filelist:
        ''' Filename is STD-nnnnn_obs* '''

        try:
            data = np.load(file)[0]
        except:
            raise Exception(
                "Not passed a spectrum file, the file should start with spectrum_"
            )

        # Convert file named sp_STD-nnnn_obs* to a name compaitable
        # with Standards.py
        pred = file.lstrip("spectrum_STD-")
        pred = pred.lstrip("sp_STD-")
        pred = pred.split("_")[0]
        pred = pred.lower().replace("+", "").replace("-", "_")
        print file, pred, pred in SS.Standards

        if pred not in SS.Standards:
            print "File named '%s' is reduced to '%s' and no such standard seems to exist." % (
                file, pred)
            continue

        ff = interp1d(data['nm'], data['ph_10m_nm'], bounds_error=False)
        spectra.append(ff(ll))

        # Now process the standard
        standard = SS.Standards[pred]
        wav = standard[:, 0] / 10.0
        flux = standard[:, 1]
        std_ff = interp1d(wav, flux, bounds_error=False, fill_value=np.nan)
        correction = std_ff(ll) / ff(ll)

        ROI = (ll > 600) & (ll < 850)
        corr_vals.append(np.median(correction[ROI]))
        correction /= corr_vals[-1]

        corrs.append(correction)

    corrs = np.array(corrs)
    erg_s_cm2_ang = corrs * np.median(corr_vals) * 1e-16

    roi = (ll > 900) & (ll < 1000)
    the_corr = scipy.stats.nanmedian(erg_s_cm2_ang, 0)
    if not np.isfinite(the_corr).all():
        # Fit polynomial to extrapolate correction
        redend = (ll > 800) & (ll < 915)
        ss = np.poly1d(np.polyfit(ll[redend], the_corr[redend], 2))

        redend = (ll > 910)
        the_corr[redend] = ss(ll[redend])

    # Now clean over the Balmer series
    balmers = [656.3, 486.1, 434.0, 410.2, 397.0]
    for balmer in balmers:
        eps = balmer * 0.02
        line_ROI = sets.Set(np.where(np.abs((ll - balmer) / balmer) < 0.03)[0])
        broad_ROI = sets.Set(
            np.where(np.abs((ll - balmer) / balmer) < 0.06)[0])
        around_line_ROI = list(broad_ROI - line_ROI)
        fit = np.poly1d(
            np.polyfit(ll[around_line_ROI], the_corr[around_line_ROI], 1))
        to_fix = list(line_ROI)
        the_corr[to_fix] = fit(ll[to_fix])

    the_corr = scipy.signal.savgol_filter(the_corr, 3, 1)

    # Plot data
    pl.figure(1)
    pl.clf()
    pl.grid(True)
    pl.ylim(1e-20, 1e-15)
    pl.semilogy(ll, the_corr, linewidth=4)
    for ix, e in enumerate(erg_s_cm2_ang):
        pl.semilogy(ll, e * corr_vals[ix] / np.mean(corr_vals))

    pl.xlabel("Wavelength [nm]")
    pl.ylabel("Correction [erg/s/cm cm/Ang]")
    pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    pl.savefig("Standard_Correction.pdf")
    print np.mean(corr_vals) * 1e-16, np.std(corr_vals) * 1e-16

    # Construct result
    res = {
        "nm": ll,
        "correction": the_corr,
        "doc": "Correct ph/10 m/nm to erg/2/cm2/ang",
        "Nspec": len(corrs),
        "correction_std": np.nanstd(erg_s_cm2_ang, 0),
        "outname": outname,
        "files": filelist,
        "when": '%s' % datetime.datetime.now(),
        "user": os.getlogin()
    }

    np.save(outname, [res])
    return res
Example #3
0
def handle_create(outname=None, filelist=[], plot_filt=False):
    """Create standard star correction. Units are erg/s/cm2/Ang

    Read in the std-correction vector for each standard star, massage
    the correction (see below) and output an ensemble correction.

    Args:
        outname (str): name for resulting correction array (def: atm-corr.npy)
        filelist (list): list of standard star extractions (e.g. sp_STD-\*.npy)
        plot_filt (bool): set to plot intermediate filtered steps (def: False)

    Returns:
        dict: A dictionary containing the ensemble correction and some
        details::

            {   "nm": wavelengths (nm),
                "maxnm": maximum wavelength,
                "correction": the correction spectrum,
                "doc": "Correct ph/10 m/nm to erg/s/cm2/ang",
                "Nspec": number of spectra used,
                "correction_std": STDev of ensemble corrections,
                "outname": outname (see Parameters),
                "files": filelist (see Parameters),
                "when": timestamp string,
                "user": user who ran the process    }

    Note:
        Writes a \*.npy file with the resulting correction

    """

    if outname is None:
        outname = 'atm-corr.npy'

    ll = Wavelength.fiducial_spectrum()
    corrs = []
    corr_vals = []
    legend = ["corr", ]
    filt_legend = ["orig"]
    maxnm = 915.
    for ifile in filelist:
        """ Filename is sp_STD-nnnnn_obs*.npy """

        # Try to read input file
        try:
            data = np.load(ifile)[0]
        except:
            raise Exception("Not able to load %s. " % ifile)

        # Check quality of extraction
        if data["quality"] > 0:
            print "Bad std extraction in %s" % ifile
            continue

        # Check for calculated correction
        if "std-correction" not in data.keys():
            print "No std-correction vector in %s" % ifile
            continue
        correction = data['std-correction']

        # What was the maximum wavelength?
        if "std-maxnm" in data.keys():
            if data['std-maxnm'] > maxnm:
                maxnm = data['std-maxnm']
        # Convert file named sp_STD-nnnn_obs* to a name compaitable
        # with Standards.py.  First strip of "sp_STD-"
        pred = ifile[7:]
        pred = pred.split("_")[0]
        legend.append(pred)
        pred = pred.lower().replace("+", "").replace("-", "_")
        print ifile, pred, pred in Stds.Standards
        # Are we in our list of standard stars?
        if pred not in Stds.Standards:
            print("File named '%s' is reduced to '%s' and no such standard "
                  "seems to exist." % (ifile, pred))
            continue
        # Record median correction in ROI
        roi = (ll > 600) & (ll < 850)
        corr_vals.append(np.median(correction[roi]))
        # Normalize each correction by the median value
        correction /= corr_vals[-1]
        corrs.append(correction)
    # END: for ifile in filelist:

    # Rescale each correction and scale to erg/s/cm2/Ang
    corrs = np.array(corrs)
    erg_s_cm2_ang = corrs * np.median(corr_vals) * 1e-16
    # Take the median of the correction vectors
    the_corr = scipy.stats.nanmedian(erg_s_cm2_ang, 0)
    # Fit red end unless we are calibrated out there
    if not np.isfinite(the_corr).all() and maxnm < 1000.0:
        print "Fitting red end"
        # Fit polynomial to extrapolate correction
        redend = (ll > 880) & (ll < maxnm)
        ss = np.poly1d(np.polyfit(ll[redend], the_corr[redend], 2))
        # Insert extrapolation back into correction vector
        redend = (ll > maxnm)
        the_corr[redend] = ss(ll[redend])

    # Plot data, if requested
    if plot_filt:
        pl.figure(2)
        pl.clf()
        pl.grid(True)
        pl.ylim(1e-20, 1e-15)
        pl.semilogy(ll, the_corr, linewidth=1)
        pl.xlabel("Wavelength [nm]")
        pl.ylabel("Correction [erg/s/cm cm/Ang]")
        pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")

    """
    # Now clean over the Balmer series (skip this for now)
    balmers = [656.3, 486.1, 434.0, 410.2, 397.0]
    #balmers = [656.3, 486.1, 434.0]
    for balmer in balmers:
        #pl.figure(3)
        line_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.01)[0])
        broad_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.04)[0])
        broad_ll = list(broad_ROI)
        broad_ll.sort()
        #pl.plot(ll[broad_ll], the_corr[broad_ll])
        around_line_ROI = list(broad_ROI - line_ROI)
        #pl.plot(ll[around_line_ROI], the_corr[around_line_ROI],'^')
        fit = np.poly1d(np.polyfit(ll[around_line_ROI],
            the_corr[around_line_ROI], 5))
        to_fix = list(line_ROI)
        #the_corr[to_fix] = fit(ll[to_fix])
        #pl.plot(ll[to_fix], the_corr[to_fix])
        #pl.show()
        """

    # Plot intermediate correction
    if plot_filt:
        pl.semilogy(ll, the_corr * 4., linewidth=2)
        filt_legend.append("Balmer*4")
    # Filter correction to remove spectral features and leave response alone
    the_corr = scipy.signal.savgol_filter(the_corr, 9, 5)
    # Plot intermediate correction
    if plot_filt:
        pl.semilogy(ll, the_corr * 2., linewidth=2)
        filt_legend.append("Filtered*2")
        pl.semilogy(ll, the_corr, linewidth=2)
        filt_legend.append("Filtered")
        pl.legend(filt_legend)
        pl.show()

    # Plot data
    pl.figure(1)
    pl.clf()
    pl.grid(True)
    pl.ylim(1e-20, 1e-15)
    pl.semilogy(ll, the_corr, linewidth=4)
    for ix, e in enumerate(erg_s_cm2_ang):
        pl.semilogy(ll, e * corr_vals[ix] / np.mean(corr_vals))

    pl.xlabel("Wavelength [nm]")
    pl.ylabel("Correction [erg/s/cm cm/Ang]")
    pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    pl.legend(legend)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        pl.savefig("Standard_Correction.pdf")

    print("Mean cor: %10.3g, Sigma cor: %10.3g" %
          (np.mean(corr_vals) * 1e-16, np.std(corr_vals) * 1e-16))
    maxnm = np.min([maxnm, np.max(ll)])
    print "Max nm: %7.2f" % maxnm

    # Construct result
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        res = {
            "nm": ll,
            "maxnm": maxnm,
            "correction": the_corr,
            "doc": "Correct ph/10 m/nm to erg/s/cm2/ang",
            "Nspec": len(corrs),
            "correction_std": np.nanstd(erg_s_cm2_ang, 0),
            "outname": outname,
            "files": filelist,
            "when": '%s' % datetime.datetime.now(),
            "user": os.getlogin()
        }

    np.save(outname, [res])
    return res
Example #4
0
def handle_create(outname=None, filelist=[]):
    ''' Create standard star correction. Units are erg/s/cm2/Ang '''

    if outname is None: outname='atm-corr.npy'

    ll = Wavelength.fiducial_spectrum()
    spectra = []
    corrs = []
    corr_vals =[]
    for file in filelist: 
        ''' Filename is STD-nnnnn_obs* '''

        try: data = np.load(file)[0]
        except:
            raise Exception("Not passed a spectrum file, the file should start with spectrum_")
        
        # Convert file named sp_STD-nnnn_obs* to a name compaitable
        # with Standards.py
        pred = file.lstrip("spectrum_STD-")
        pred = pred.lstrip("sp_STD-")
        pred = pred.split("_")[0]
        pred = pred.lower().replace("+","").replace("-","_")
        print file, pred, pred in SS.Standards

        if pred not in SS.Standards:
            print "File named '%s' is reduced to '%s' and no such standard seems to exist."  % (file, pred)
            continue


        ff = interp1d(data['nm'], data['ph_10m_nm'], bounds_error=False)
        spectra.append(ff(ll))


        # Now process the standard
        standard = SS.Standards[pred]
        wav = standard[:,0]/10.0
        flux = standard[:,1]
        std_ff = interp1d(wav, flux, bounds_error=False, fill_value=np.nan)
        correction = std_ff(ll)/ff(ll)

        ROI = (ll > 600) & (ll < 850)
        corr_vals.append(np.median(correction[ROI]))
        correction /= corr_vals[-1]

        corrs.append(correction)

    corrs = np.array(corrs) 
    erg_s_cm2_ang = corrs * np.median(corr_vals) * 1e-16


    
    roi = (ll > 900) & (ll < 1000)
    the_corr = scipy.stats.nanmedian(erg_s_cm2_ang,0)
    if not np.isfinite(the_corr).all():
        # Fit polynomial to extrapolate correction
        redend = (ll > 800) & (ll < 915)
        ss = np.poly1d(np.polyfit(ll[redend], the_corr[redend], 2))

        redend = (ll>910)
        the_corr[redend] = ss(ll[redend])


    # Now clean over the Balmer series
    balmers = [656.3, 486.1, 434.0, 410.2, 397.0]
    for balmer in balmers:
        eps = balmer * 0.02
        line_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.03)[0])
        broad_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.06)[0])
        around_line_ROI = list(broad_ROI - line_ROI)
        fit = np.poly1d(np.polyfit(ll[around_line_ROI], 
            the_corr[around_line_ROI], 1))
        to_fix = list(line_ROI)
        the_corr[to_fix] = fit(ll[to_fix])

    the_corr = scipy.signal.savgol_filter(the_corr, 3, 1)


    # Plot data
    pl.figure(1)
    pl.clf()
    pl.grid(True)
    pl.ylim(1e-20,1e-15)
    pl.semilogy(ll, the_corr, linewidth=4)
    for ix,e in enumerate(erg_s_cm2_ang):
        pl.semilogy(ll, e*corr_vals[ix]/np.mean(corr_vals))

    pl.xlabel("Wavelength [nm]")
    pl.ylabel("Correction [erg/s/cm cm/Ang]")
    pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    pl.savefig("Standard_Correction.pdf")
    print np.mean(corr_vals) * 1e-16, np.std(corr_vals)*1e-16

    # Construct result
    res = {"nm": ll,
        "correction": the_corr,
        "doc": "Correct ph/10 m/nm to erg/2/cm2/ang",
        "Nspec": len(corrs),
        "correction_std": np.nanstd(erg_s_cm2_ang,0),
        "outname": outname,
        "files": filelist,
        "when": '%s' % datetime.datetime.now(),
        "user": os.getlogin()
        }

    np.save(outname, [res])
    return res
Example #5
0
def handle_create(outname=None, filelist=[], plot_filt=False):
    ''' Create standard star correction. Units are erg/s/cm2/Ang '''

    if outname is None: outname='atm-corr.npy'

    ll = Wavelength.fiducial_spectrum()
    corrs = []
    corr_vals =[]
    legend=["corr",]
    filt_legend=["orig"]
    maxnm = 915.
    for file in filelist:
        ''' Filename is sp_STD-nnnnn_obs*.npy '''

        # Try to read input file
        try: data = np.load(file)[0]
        except:
            raise Exception("Not passed a spectrum file, the file should start with sp_")

        # Check for calculated correction
        if "std-correction" not in data.keys():
            print "No std-correction vector in %s" % file
            continue
        correction = data['std-correction']

        # What was the maximum wavelength?
        if "std-maxnm" in data.keys():
            if data['std-maxnm'] > maxnm: maxnm = data['std-maxnm']

        # Convert file named sp_STD-nnnn_obs* to a name compaitable
        # with Standards.py
        pred = file.lstrip("sp_STD-")
        pred = pred.split("_")[0]
        legend.append(pred)
        pred = pred.lower().replace("+","").replace("-","_")
        print file, pred, pred in SS.Standards

        if pred not in SS.Standards:
            print "File named '%s' is reduced to '%s' and no such standard seems to exist."  % (file, pred)
            continue

        # Record median correction in ROI
        ROI = (ll > 600) & (ll < 850)
        corr_vals.append(np.median(correction[ROI]))
        
        # Normalize each correction by the median value
        correction /= corr_vals[-1]
        corrs.append(correction)
        
    # END: for file in filelist:

    # Rescale each correction and scale to erg/s/cm2/Ang
    corrs = np.array(corrs)
    erg_s_cm2_ang = corrs * np.median(corr_vals) * 1e-16

    # Take the median of the correction vectors
    the_corr = scipy.stats.nanmedian(erg_s_cm2_ang,0)
    
    # Fit red end unless we are calibrated out there
    if not np.isfinite(the_corr).all() and maxnm < 1000.0:
        print "Fitting red end"
        # Fit polynomial to extrapolate correction
        redend = (ll > 880) & (ll < maxnm)
        ss = np.poly1d(np.polyfit(ll[redend], the_corr[redend], 2))

        redend = (ll>maxnm)
        the_corr[redend] = ss(ll[redend])

    # Plot data, if requested
    if plot_filt:
        pl.figure(2)
        pl.clf()
        pl.grid(True)
        pl.ylim(1e-20,1e-15)
        pl.semilogy(ll, the_corr, linewidth=1)

        pl.xlabel("Wavelength [nm]")
        pl.ylabel("Correction [erg/s/cm cm/Ang]")
        pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")

    '''
    # Now clean over the Balmer series (skip this for now)
    balmers = [656.3, 486.1, 434.0, 410.2, 397.0]
    #balmers = [656.3, 486.1, 434.0]
    for balmer in balmers:
        #pl.figure(3)
        line_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.01)[0])
        broad_ROI = sets.Set(np.where(np.abs((ll-balmer)/balmer) < 0.04)[0])
        broad_ll = list(broad_ROI)
        broad_ll.sort()
        #pl.plot(ll[broad_ll], the_corr[broad_ll])
        around_line_ROI = list(broad_ROI - line_ROI)
        #pl.plot(ll[around_line_ROI], the_corr[around_line_ROI],'^')
        fit = np.poly1d(np.polyfit(ll[around_line_ROI],
            the_corr[around_line_ROI], 5))
        to_fix = list(line_ROI)
        #the_corr[to_fix] = fit(ll[to_fix])
        #pl.plot(ll[to_fix], the_corr[to_fix])
        #pl.show()
        '''

    if plot_filt:
        pl.semilogy(ll, the_corr*4., linewidth=2)
        filt_legend.append("Balmer*4")

    # Filter correction to remove spectral features and leave response alone
    the_corr = scipy.signal.savgol_filter(the_corr, 9, 5)

    if plot_filt:
        pl.semilogy(ll, the_corr*2., linewidth=2)
        filt_legend.append("Filtered*2")
        pl.semilogy(ll, the_corr, linewidth=2)
        filt_legend.append("Filtered")
        pl.legend(filt_legend)
        pl.show()

    # Plot data
    pl.figure(1)
    pl.clf()
    pl.grid(True)
    pl.ylim(1e-20,1e-15)
    pl.semilogy(ll, the_corr, linewidth=4)
    for ix,e in enumerate(erg_s_cm2_ang):
        pl.semilogy(ll, e*corr_vals[ix]/np.mean(corr_vals))

    pl.xlabel("Wavelength [nm]")
    pl.ylabel("Correction [erg/s/cm cm/Ang]")
    pl.title("Correct ph/10 m/nm to erg/s/cm2/Ang")
    pl.legend(legend)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        pl.savefig("Standard_Correction.pdf")

    print "Mean cor: %10.3g, Sigma cor: %10.3g" % (np.mean(corr_vals) * 1e-16, np.std(corr_vals)*1e-16)
    maxnm = np.min([maxnm,np.max(ll)])
    print "Max nm: %7.2f" % maxnm

    # Construct result
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        res = {"nm": ll,
            "maxnm": maxnm,
            "correction": the_corr,
            "doc": "Correct ph/10 m/nm to erg/2/cm2/ang",
            "Nspec": len(corrs),
            "correction_std": np.nanstd(erg_s_cm2_ang,0),
            "outname": outname,
            "files": filelist,
            "when": '%s' % datetime.datetime.now(),
            "user": os.getlogin()
            }

    np.save(outname, [res])
    return res