Ejemplo n.º 1
0
def make_calring(hdu, method=None, thresh=5, niter=3, conv=0.05, minsize=10, axc=None, ayc=None):
    """Open each image and measure the position of the ring including its center and radius
     
      Return the information about the calibration ring
   """

    # setup the data
    data = hdu[0].data
    # extract the time and convert to decimal hours
    utctime = saltkey.get("UTC-OBS", hdu[0])
    utctime = salttime.time_obs2hr((utctime.split()[-1]))

    # determine the correct etalon and information to extract
    etstate = saltkey.get("ET-STATE", hdu[0])

    if etstate.count("S2"):
        etz = saltkey.get("ET1Z", hdu[0])
    elif etstate.count("S3"):
        etz = saltkey.get("ET2Z", hdu[0])
    else:
        msg = "This etalon state is not currently supported"
        raise SaltError(msg)

    # extract the ring
    ring_list = findrings(data, thresh=thresh, niter=niter, minsize=minsize, axc=axc, ayc=ayc)

    # assumes only one ring in the data set
    ring = ring_list[0]

    # determine the center and radius of the ring
    if method is not None:
        ring = findcenter(data, ring, method, niter=niter, conv=conv)

    if axc:
        ring.xc = axc
    if ayc:
        ring.yc = ayc

    return ring.xc, ring.yc, ring.prad, ring.prad_err, etz, utctime
Ejemplo n.º 2
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[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
Ejemplo n.º 3
0
def saltfpringfind(images, method=None, section=None, thresh=5, minsize=10, niter=5, conv=0.05,
                displayimage=True, clobber=False, logfile='salt.log',verbose=True):

   with logging(logfile,debug) as log:

       # Check the input images 
       infiles = saltio.argunpack ('Input',images)

       #check the method
       method=saltio.checkfornone(method)

       # read in the section
       section=saltio.checkfornone(section)
       if section is None: 
           pass
       else:
           section=saltio.getSection(section)
 
       # open each raw image file
       for img in infiles:

          #open the fits file
	  struct=saltio.openfits(img)
          data=struct[0].data

          #determine the background value for the image
          if section is None:
             #if section is none, just use all pixels greater than zero
             bdata=data[data>0]
          else:
             y1,y2,x1,x2=section
             bdata=data[y1:y2,x1:x2]
          bmean, bmedian, bstd=iterstat(bdata, sig=thresh, niter=niter, verbose=False)
          message="Image Background Statistics\n%30s %6s %8s %8s\n%30s %5.4f %5.4f %5.4f\n" %  \
                ('Image', 'Mean', 'Median', 'Std',img, bmean, bmedian, bstd)
          log.message(message, with_stdout=verbose)
    
          mdata=data*(data-bmean>thresh*bstd)

          #prepare the first guess for the image
          ring_list=findrings(data, thresh=thresh, niter=niter, minsize=minsize)

          #if specified, find the center of the ring
          if method is not None:
             for i in range(len(ring_list)):
                 ring_list[i]=findcenter(data, ring_list[i], method, niter=niter, conv=conv)
            

          #if one peak: no rings.  If two peaks: one ring, if two peaks: four rings
          if len(ring_list)==1:
             msg="One ring dected in image"
          else:
             msg="%i rings found in image" % len(ring_list)
          log.message(message, with_stdout=verbose)

          if displayimage:
             regfile=img.replace('.fits', '.reg')
             if clobber and os.path.isfile(regfile): fout=saltio.delete(regfile)
             fout=open(regfile, 'w')
             fout.write("""# Region file format: DS9 version 4.1
# Filename:  %s
global color=green dashlist=8 3 width=1 font="helvetica 10 normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1
physical
""" % img)
             for ring in ring_list:
                 fout.write('circle(%f, %f, %f)\n' % (ring.xc,ring.yc,ring.prad))
                 fout.write('circle(%f, %f, %f)\n' % (ring.xc,ring.yc,ring.prad-3*ring.sigma))
                 fout.write('circle(%f, %f, %f)\n' % (ring.xc,ring.yc,ring.prad+3*ring.sigma))

             fout.close()
             display(img, catname=regfile, rformat='reg')

	  message = 'Ring Parameters\n%30s %6s %6s %6s\n' % ('Image', 'XC', 'YC', 'Radius')
          log.message(message, with_stdout=verbose)
          for ring in ring_list:
              msg='%30s %6.2f %6.2f %6.2f\n' % (img, ring.xc, ring.yc, ring.prad)
              log.message(msg, with_header=False, with_stdout=verbose)
Ejemplo n.º 4
0
def saltfpringfind(images,
                   method=None,
                   section=None,
                   thresh=5,
                   minsize=10,
                   niter=5,
                   conv=0.05,
                   displayimage=True,
                   clobber=False,
                   logfile='salt.log',
                   verbose=True):

    with logging(logfile, debug) as log:

        # Check the input images
        infiles = saltio.argunpack('Input', images)

        #check the method
        method = saltio.checkfornone(method)

        # read in the section
        section = saltio.checkfornone(section)
        if section is None:
            pass
        else:
            section = saltio.getSection(section)

        # open each raw image file
        for img in infiles:

            #open the fits file
            struct = saltio.openfits(img)
            data = struct[0].data

            #determine the background value for the image
            if section is None:
                #if section is none, just use all pixels greater than zero
                bdata = data[data > 0]
            else:
                y1, y2, x1, x2 = section
                bdata = data[y1:y2, x1:x2]
            bmean, bmedian, bstd = iterstat(bdata,
                                            sig=thresh,
                                            niter=niter,
                                            verbose=False)
            message="Image Background Statistics\n%30s %6s %8s %8s\n%30s %5.4f %5.4f %5.4f\n" %  \
                  ('Image', 'Mean', 'Median', 'Std',img, bmean, bmedian, bstd)
            log.message(message, with_stdout=verbose)

            mdata = data * (data - bmean > thresh * bstd)

            #prepare the first guess for the image
            ring_list = findrings(data,
                                  thresh=thresh,
                                  niter=niter,
                                  minsize=minsize)

            #if specified, find the center of the ring
            if method is not None:
                for i in range(len(ring_list)):
                    ring_list[i] = findcenter(data,
                                              ring_list[i],
                                              method,
                                              niter=niter,
                                              conv=conv)

        #if one peak: no rings.  If two peaks: one ring, if two peaks: four rings
            if len(ring_list) == 1:
                msg = "One ring dected in image"
            else:
                msg = "%i rings found in image" % len(ring_list)
            log.message(message, with_stdout=verbose)

            if displayimage:
                regfile = img.replace('.fits', '.reg')
                if clobber and os.path.isfile(regfile):
                    fout = saltio.delete(regfile)
                fout = open(regfile, 'w')
                fout.write("""# Region file format: DS9 version 4.1
# Filename:  %s
global color=green dashlist=8 3 width=1 font="helvetica 10 normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1
physical
""" % img)
                for ring in ring_list:
                    fout.write('circle(%f, %f, %f)\n' %
                               (ring.xc, ring.yc, ring.prad))
                    fout.write('circle(%f, %f, %f)\n' %
                               (ring.xc, ring.yc, ring.prad - 3 * ring.sigma))
                    fout.write('circle(%f, %f, %f)\n' %
                               (ring.xc, ring.yc, ring.prad + 3 * ring.sigma))

                fout.close()
                display(img, catname=regfile, rformat='reg')

            message = 'Ring Parameters\n%30s %6s %6s %6s\n' % ('Image', 'XC',
                                                               'YC', 'Radius')
            log.message(message, with_stdout=verbose)
            for ring in ring_list:
                msg = '%30s %6.2f %6.2f %6.2f\n' % (img, ring.xc, ring.yc,
                                                    ring.prad)
                log.message(msg, with_header=False, with_stdout=verbose)
Ejemplo n.º 5
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[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 ghost ring centre 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 "Using 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 "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
    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