def fit_rings(file, trim_rad=470, disp=None):
    """
    main routine to take a FITS file, read it in, azimuthally average it,
    find the rings, and then fit voigt profiles to them.

    Parameters
    ----------
    file : string filename of FITS file to analyze
    trim_rad : int maximum radial extent of profile
    disp : boolean to control DS9 display of image

    Returns
    -------
    list containing:
        boolean - success of finding peaks or not
        numpy array - wavelengths of profile
        numpy array - radial flux profile data
        numpy array - best-fit radial flux profile
        dict - parameters of best-fit
    """



    hdu = pyfits.open(file)
    (data, header) = (hdu[0].data, hdu[0].header)
    etalon = int(header['ET-STATE'].split()[3])
    etwave_key = "ET%dWAVE0" % etalon
    name_key = "ET%dMODE" % etalon
    etname = header[name_key]
    cenwave = float(header[etwave_key])
    binning = int(header['CCDSUM'].split()[0])
    if header['OBSMODE'] != 'FABRY-PEROT':
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    ysize, xsize = data.shape


    

    # cut FP image down to square
    fp_im = data[:,
                 (xsize - ysize) / 2:
                 (xsize + ysize) / 2]
    if disp:
        disp.set_np2arr(fp_im, dtype=np.int32)
    # mask those gaps
    fp_im = ma.masked_less_equal(data[:,
                                      (xsize - ysize) / 2:
                                      (xsize + ysize) / 2], 0.0)

    # define center based on FP ghost imaging with special mask
    xc = 2054 / binning
    yc = 2008 / binning

#    print "FP ring centre should be at x= %.1f y= %.1f" % (xc+280, yc)

    #Find the list of rings:

    ring_list=findrings(data, thresh=5, niter=5, minsize=10)

    print "%1d ring(s) found" % (len(ring_list))    

    sxc=syc=0
    for i in range(len(ring_list)):
        ring_list[i]=findcenter(data, ring_list[i], method='center')
        print "Ring number %1d: centre at X= %.1f, Y=%.1f, Radius= %.1f" % (i+1, ring_list[i].xc, ring_list[i].yc,ring_list[i].prad)
        if ring_list[i].prad > 250 and ring_list[i].prad < 390:
            sxc=ring_list[i].xc
            syc=ring_list[i].yc

#    xcn,ycn=find_center(fp_im,xc,yc)
       
    if sxc >0 and syc > 0:

        print "Found ring centre at x= %.1f y= %.1f" % (sxc, syc)
        xc=sxc-280
        yc=syc
        
        #Xc0 and Yc0 is the ring centre for a good ring
        # Ted's values:

        xc0=802
        yc0=503

        #From Tim's:
#        xc0=800
#        yc0=500

        deltaX=int(3.6*(syc-yc0))
        deltaY=int(4.7*((sxc)-xc0))

#        print "With this new centre, recommend dX= %1d, dY=%1d" % (deltaX, deltaY)

    else:
        print "Found ring centre at x= %.1f y= %.1f" % (sxc, syc)        
        print "Using FP ghost ring centre at x= %.1f y= %.1f" % (xc+280, yc)
    
    # we use the 4x4 version of trim_rad since the vast majority of FP
    # data is taken with 4x4 binning
    trim_rad *= 4 / binning

    mask_val = 0.0
    f = {}
    if cenwave < 5200:
        f['MR'] = 22149.6
        f['LR'] = 22795.92
        f['TF'] = 24360.32
    if cenwave > 6500 and cenwave < 6600:
        f['MR'] = 22713.0
        f['LR'] = 24191.40
        f['TF'] = 24360.32
    if cenwave >= 6600 and cenwave < 6700:
        f['MR'] = 22848.0
        f['LR'] = 24169.32
        f['TF'] = 23830.20
    if cenwave >= 6700 and cenwave < 6900:
        f['MR'] = 22828.92
        f['LR'] = 24087.68
        f['TF'] = 24553.32
    if cenwave >= 7300 and cenwave < 7700:
        f['MR'] = 22864.06
        f['LR'] = 24087.68
        f['TF'] = 24553.32
    else:
        f['MR'] = 22828.92
        f['LR'] = 24400.32
        f['TF'] = 24553.32

    # get the radial profile and flatten it with a default QTH flat profile
    prof, r = FP_profile(fp_im, xc, yc, trim_rad=trim_rad, mask=mask_val)

#    Not flatfielding the profile as ring already flat-fielded using saltflat.
#    prof = flatprof(prof, binning)

    wave = cenwave / np.sqrt(1.0 + (r * binning / f[etname]) ** 2)

    # find the peaks and bail out if none found
    npeaks, peak_list = find_peaks(prof, width=40)
    if npeaks < 1:
        print "No peaks found."
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    print "Found %d rings at:" % npeaks
    cenwidth = 20
    for peak in peak_list:
        cen_peak = centroid(prof, peak, cenwidth)
        if np.isnan(cen_peak):
            cen_peak = peak

        print "\t R %f" % cen_peak
        if disp:
            disp.set("regions command {circle %f %f %f # color=red}" %
                     (xc, yc, cen_peak))

    # max_r = peak_list[0]
    # pmax = prof[max_r]
    back = 250.0
    fwhm = 5.0
    gam = 1.0
    init = [back]
    bounds = [(0.0, 2.0e8)]

    # keep brightest
    peak = peak_list[0]

    # position
    init.append(cenwave / np.sqrt(1.0 + (peak * binning / f[etname]) ** 2))
    bounds.append((cenwave - 30, cenwave + 30))
    # amplitude
    init.append(prof[peak])
    bounds.append((0.0, 1.0e8))
    # FWHM
    init.append(fwhm)
    bounds.append((0.1, 20.0))
    # gamma
    init.append(gam)
    bounds.append((0.0, 5.0))

    ### keep these around in case we want to try again someday
    #
    #fit = opt.fmin_slsqp(fit_func, init, args=(prof, wave),
    #                     bounds=bounds)
    #fit, nfeval, rc = opt.fmin_tnc(fit_func, init, args=(prof, wave),
    #                               epsilon=0.0001,
    #                               bounds=bounds,
    #                               approx_grad=True,
    #                               disp=0,
    #                               maxfun=5000)

    # good ol' powell method FTW
    fit = opt.fmin_powell(fit_func, init, args=(prof, wave),
                          ftol=0.00001, full_output=False, disp=False)

    #print "Return code: %s" % opt.tnc.RCSTRINGS[rc]

    pars = {}
    fit_v = fit[0]
    print "\nBackground = %f" % fit[0]
    pars['Background'] = fit[0]
    pars['R'] = []
    pars['Amplitude'] = []
    pars['Gauss FWHM'] = []
    pars['Gamma'] = []
    pars['FWHM'] = []
    for i in range(1, len(fit), 4):
        fwhm = voigt_fwhm(fit[i + 2], fit[i + 3])
        pars['R'].append(fit[i])
        pars['Amplitude'].append(fit[i + 1])
        pars['Gauss FWHM'].append(fit[i + 2])
        pars['Gamma'].append(fit[i + 3])
        pars['FWHM'].append(fwhm)
        fit_v = fit_v + qvoigt(wave, fit[i + 1], fit[i],
                               fit[i + 2], fit[i + 3])

    return True, wave, prof, fit_v, pars
Beispiel #2
0
def fit_rings(file, flatfile=None, disp=None):
    if flatfile:
        flat = np.loadtxt(flatfile)
    hdu = pyfits.open(file)
    (data, header) = (hdu[1].data, hdu[0].header)
    etalon = int(header['ET-STATE'].split()[3])
    etwave_key = "ET%dWAVE0" % etalon
    name_key = "ET%dMODE" % etalon
    etname = header[name_key]
    cenwave = float(header[etwave_key])
    binning = int(header['CCDSUM'].split()[0])
    if header['OBSMODE'] != 'FABRY-PEROT':
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    ysize, xsize = data.shape

    # cut FP image down to square
    fp_im = data[:, (xsize - ysize) / 2:(xsize + ysize) / 2]
    if disp:
        disp.set_np2arr(fp_im, dtype=np.int32)

    # mask those gaps
    fp_im = ma.masked_less_equal(
        data[:, (xsize - ysize) / 2:(xsize + ysize) / 2], 0.0)

    # first guess is the center of the aperture (assume 4x4 binning here)
    xc = 4 * 513.5 / binning
    yc = 4 * 514.5 / binning
    mask_val = 0.0
    f = {}
    f['MR'] = 22848.0
    f['LR'] = 24169.32

    # find brightest ring and refine center
    cenwidth = 20

    if flatfile:
        prof, r = FP_profile(fp_im, xc, yc,
                             trim_rad=len(flat), mask=mask_val)
        prof = prof / flat
    else:
        prof, r = FP_profile(fp_im, xc, yc,
                             trim_rad=4 * 450.0 / binning, mask=mask_val)

    wave = cenwave / np.sqrt(1.0 + (r * binning / f[etname]) ** 2)

    npeaks, peak_list = find_peaks(prof, width=40)
    if npeaks < 1:
        print "No peaks found."
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    print "Found %d rings at:" % npeaks
    for peak in peak_list:
        cen_peak = centroid(prof, peak, cenwidth)
        if np.isnan(cen_peak):
            cen_peak = peak

        print "\t R %f" % cen_peak
        if disp:
            disp.set(
                "regions command {circle %f %f %f # color=red}" %
                (xc, yc, cen_peak))

    back = 100.0
    fwhm = 1.0
    gam = 1.0
    init = [back]

    # keep brightest
    if len(peak_list) > 1:
        peaks = peak_list[0:1]
    else:
        peaks = peak_list

    for peak in peaks:
        # position
        init.append(cenwave / np.sqrt(1.0 + (peak * binning / f[etname]) ** 2))
        # amplitude
        init.append(prof[peak])
        # FWHM
        init.append(fwhm)
        # gamma
        init.append(gam)

    #fit = opt.fmin_slsqp(fit_func, init,
    #    args=(prof, rsq), bounds=bounds)
    #fit = opt.fmin_tnc(fit_func, init,
    # args=(prof, rsq), bounds=bounds, approx_grad=True)
    fit = opt.fmin_powell(fit_func,
                          init,
                          args=(prof, wave),
                          ftol=0.00001,
                          full_output=False,
                          disp=False)
    pars = {}
    fit_v = fit[0]
    print "Background = %f" % fit[0]
    pars['Background'] = fit[0]
    pars['R'] = []
    pars['Amplitude'] = []
    pars['Gauss FWHM'] = []
    pars['Gamma'] = []
    pars['FWHM'] = []
    for i in range(1, len(fit), 4):
        fwhm = voigt_fwhm(fit[i + 2], fit[i + 3])
        pars['R'].append(fit[i])
        pars['Amplitude'].append(fit[i + 1])
        pars['Gauss FWHM'].append(fit[i + 2])
        pars['Gamma'].append(fit[i + 3])
        pars['FWHM'].append(fwhm)
        fit_v = fit_v + qvoigt(wave, fit[i + 1],
                               fit[i], fit[i + 2], fit[i + 3])

    return True, wave, prof, fit_v, pars
Beispiel #3
0
def fit_rings(file, trim_rad=470, disp=None):
    """
    main routine to take a FITS file, read it in, azimuthally average it,
    find the rings, and then fit voigt profiles to them.

    Parameters
    ----------
    file : string filename of FITS file to analyze
    trim_rad : int maximum radial extent of profile
    disp : boolean to control DS9 display of image

    Returns
    -------
    list containing:
        boolean - success of finding peaks or not
        numpy array - wavelengths of profile
        numpy array - radial flux profile data
        numpy array - best-fit radial flux profile
        dict - parameters of best-fit
    """
    hdu = pyfits.open(file)
    (data, header) = (hdu[1].data, hdu[0].header)
    etalon = int(header['ET-STATE'].split()[3])
    etwave_key = "ET%dWAVE0" % etalon
    name_key = "ET%dMODE" % etalon
    etname = header[name_key]
    cenwave = float(header[etwave_key])
    binning = int(header['CCDSUM'].split()[0])
    if header['OBSMODE'] != 'FABRY-PEROT':
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    ysize, xsize = data.shape

    # cut FP image down to square
    fp_im = data[:, (xsize - ysize) / 2:(xsize + ysize) / 2]
    if disp:
        disp.set_np2arr(fp_im, dtype=np.int32)
    # mask those gaps
    fp_im = ma.masked_less_equal(
        data[:, (xsize - ysize) / 2:(xsize + ysize) / 2], 0.0)

    # define center based on FP ghost imaging with special mask
    xc = 2054 / binning
    yc = 2008 / binning
    # we use the 4x4 version of trim_rad since the vast majority of FP
    # data is taken with 4x4 binning
    trim_rad *= 4 / binning

    mask_val = 0.0
    f = {}
    if cenwave < 5200:
        f['MR'] = 22149.6
        f['LR'] = 22795.92
        f['TF'] = 24360.32
    if cenwave > 6500 and cenwave < 6600:
        f['MR'] = 22713.0
        f['LR'] = 24191.40
        f['TF'] = 24360.32
    if cenwave >= 6600 and cenwave < 6700:
        f['MR'] = 22848.0
        f['LR'] = 24169.32
        f['TF'] = 23830.20
    if cenwave >= 6700 and cenwave < 6900:
        f['MR'] = 22828.92
        f['LR'] = 24087.68
        f['TF'] = 24553.32
    else:
        f['MR'] = 22828.92
        f['LR'] = 24400.32
        f['TF'] = 24553.32

    # get the radial profile and flatten it with a default QTH flat profile
    prof, r = FP_profile(fp_im, xc, yc, trim_rad=trim_rad, mask=mask_val)
    prof = flatprof(prof, binning)

    wave = cenwave / np.sqrt(1.0 + (r * binning / f[etname])**2)

    # find the peaks and bail out if none found
    npeaks, peak_list = find_peaks(prof, width=40)
    if npeaks < 1:
        print "No peaks found."
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    print "Found %d rings at:" % npeaks
    cenwidth = 20
    for peak in peak_list:
        cen_peak = centroid(prof, peak, cenwidth)
        if np.isnan(cen_peak):
            cen_peak = peak

        print "\t R %f" % cen_peak
        if disp:
            disp.set("regions command {circle %f %f %f # color=red}" %
                     (xc, yc, cen_peak))

    # max_r = peak_list[0]
    # pmax = prof[max_r]
    back = 250.0
    fwhm = 5.0
    gam = 1.0
    init = [back]
    bounds = [(0.0, 2.0e8)]

    # keep brightest
    peak = peak_list[0]

    # position
    init.append(cenwave / np.sqrt(1.0 + (peak * binning / f[etname])**2))
    bounds.append((cenwave - 30, cenwave + 30))
    # amplitude
    init.append(prof[peak])
    bounds.append((0.0, 1.0e8))
    # FWHM
    init.append(fwhm)
    bounds.append((0.1, 20.0))
    # gamma
    init.append(gam)
    bounds.append((0.0, 5.0))

    ### keep these around in case we want to try again someday
    #
    #fit = opt.fmin_slsqp(fit_func, init, args=(prof, wave),
    #                     bounds=bounds)
    #fit, nfeval, rc = opt.fmin_tnc(fit_func, init, args=(prof, wave),
    #                               epsilon=0.0001,
    #                               bounds=bounds,
    #                               approx_grad=True,
    #                               disp=0,
    #                               maxfun=5000)

    # good ol' powell method FTW
    fit = opt.fmin_powell(fit_func,
                          init,
                          args=(prof, wave),
                          ftol=0.00001,
                          full_output=False,
                          disp=False)

    #print "Return code: %s" % opt.tnc.RCSTRINGS[rc]

    pars = {}
    fit_v = fit[0]
    print "\nBackground = %f" % fit[0]
    pars['Background'] = fit[0]
    pars['R'] = []
    pars['Amplitude'] = []
    pars['Gauss FWHM'] = []
    pars['Gamma'] = []
    pars['FWHM'] = []
    for i in range(1, len(fit), 4):
        fwhm = voigt_fwhm(fit[i + 2], fit[i + 3])
        pars['R'].append(fit[i])
        pars['Amplitude'].append(fit[i + 1])
        pars['Gauss FWHM'].append(fit[i + 2])
        pars['Gamma'].append(fit[i + 3])
        pars['FWHM'].append(fwhm)
        fit_v = fit_v + qvoigt(wave, fit[i + 1], fit[i], fit[i + 2],
                               fit[i + 3])

    return True, wave, prof, fit_v, pars
Beispiel #4
0
def fit_rings(file, trim_rad=470, disp=None):
    """
    main routine to take a FITS file, read it in, azimuthally average it,
    find the rings, and then fit voigt profiles to them.

    Parameters
    ----------
    file : string filename of FITS file to analyze
    trim_rad : int maximum radial extent of profile
    disp : boolean to control DS9 display of image

    Returns
    -------
    list containing:
        boolean - success of finding peaks or not
        numpy array - wavelengths of profile
        numpy array - radial flux profile data
        numpy array - best-fit radial flux profile
        dict - parameters of best-fit
    """
    hdu = pyfits.open(file)
    (data, header) = (hdu[1].data, hdu[0].header)
    etalon = int(header["ET-STATE"].split()[3])
    etwave_key = "ET%dWAVE0" % etalon
    name_key = "ET%dMODE" % etalon
    etname = header[name_key]
    cenwave = float(header[etwave_key])
    binning = int(header["CCDSUM"].split()[0])
    if header["OBSMODE"] != "FABRY-PEROT":
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    ysize, xsize = data.shape

    # cut FP image down to square
    fp_im = data[:, (xsize - ysize) / 2 : (xsize + ysize) / 2]
    if disp:
        disp.set_np2arr(fp_im, dtype=np.int32)
    # mask those gaps
    fp_im = ma.masked_less_equal(data[:, (xsize - ysize) / 2 : (xsize + ysize) / 2], 0.0)

    # define center based on FP ghost imaging with special mask
    xc = 2054 / binning
    yc = 2008 / binning
    # we use the 4x4 version of trim_rad since the vast majority of FP
    # data is taken with 4x4 binning
    trim_rad *= 4 / binning

    mask_val = 0.0
    f = {}
    if cenwave < 5200:
        f["MR"] = 22149.6
        f["LR"] = 22795.92
        f["TF"] = 24360.32
    if cenwave > 6500 and cenwave < 6600:
        f["MR"] = 22713.0
        f["LR"] = 24191.40
        f["TF"] = 24360.32
    if cenwave >= 6600 and cenwave < 6700:
        f["MR"] = 22848.0
        f["LR"] = 24169.32
        f["TF"] = 23830.20
    if cenwave >= 6700 and cenwave < 6900:
        f["MR"] = 22828.92
        f["LR"] = 24087.68
        f["TF"] = 24553.32
    else:
        f["MR"] = 22828.92
        f["LR"] = 24400.32
        f["TF"] = 24553.32

    # get the radial profile and flatten it with a default QTH flat profile
    prof, r = FP_profile(fp_im, xc, yc, trim_rad=trim_rad, mask=mask_val)
    prof = flatprof(prof, binning)

    wave = cenwave / np.sqrt(1.0 + (r * binning / f[etname]) ** 2)

    # find the peaks and bail out if none found
    npeaks, peak_list = find_peaks(prof, width=40)
    if npeaks < 1:
        print "No peaks found."
        return False, np.empty(1), np.empty(1), np.empty(1), np.empty(1)

    print "Found %d rings at:" % npeaks
    cenwidth = 20
    for peak in peak_list:
        cen_peak = centroid(prof, peak, cenwidth)
        if np.isnan(cen_peak):
            cen_peak = peak

        print "\t R %f" % cen_peak
        if disp:
            disp.set("regions command {circle %f %f %f # color=red}" % (xc, yc, cen_peak))

    # max_r = peak_list[0]
    # pmax = prof[max_r]
    back = 250.0
    fwhm = 5.0
    gam = 1.0
    init = [back]
    bounds = [(0.0, 2.0e8)]

    # keep brightest
    peak = peak_list[0]

    # position
    init.append(cenwave / np.sqrt(1.0 + (peak * binning / f[etname]) ** 2))
    bounds.append((cenwave - 30, cenwave + 30))
    # amplitude
    init.append(prof[peak])
    bounds.append((0.0, 1.0e8))
    # FWHM
    init.append(fwhm)
    bounds.append((0.1, 20.0))
    # gamma
    init.append(gam)
    bounds.append((0.0, 5.0))

    ### keep these around in case we want to try again someday
    #
    # fit = opt.fmin_slsqp(fit_func, init, args=(prof, wave),
    #                     bounds=bounds)
    # fit, nfeval, rc = opt.fmin_tnc(fit_func, init, args=(prof, wave),
    #                               epsilon=0.0001,
    #                               bounds=bounds,
    #                               approx_grad=True,
    #                               disp=0,
    #                               maxfun=5000)

    # good ol' powell method FTW
    fit = opt.fmin_powell(fit_func, init, args=(prof, wave), ftol=0.00001, full_output=False, disp=False)

    # print "Return code: %s" % opt.tnc.RCSTRINGS[rc]

    pars = {}
    fit_v = fit[0]
    print "\nBackground = %f" % fit[0]
    pars["Background"] = fit[0]
    pars["R"] = []
    pars["Amplitude"] = []
    pars["Gauss FWHM"] = []
    pars["Gamma"] = []
    pars["FWHM"] = []
    for i in range(1, len(fit), 4):
        fwhm = voigt_fwhm(fit[i + 2], fit[i + 3])
        pars["R"].append(fit[i])
        pars["Amplitude"].append(fit[i + 1])
        pars["Gauss FWHM"].append(fit[i + 2])
        pars["Gamma"].append(fit[i + 3])
        pars["FWHM"].append(fwhm)
        fit_v = fit_v + qvoigt(wave, fit[i + 1], fit[i], fit[i + 2], fit[i + 3])

    return True, wave, prof, fit_v, pars