예제 #1
0
 def test_match_cxy(self):
     xx = np.arange(1, 11) * 1.
     yy = np.arange(1, 11) * 1.
     sx = np.arange(2, 12) * 1.
     sy = np.arange(2, 12) * 1.
     (indxy, indr) = astrotools.match_cxy(xx, yy, sx, sy)
     expected_indxy = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
     expected_indr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
     assert (indxy == expected_indxy).all and (indr == expected_indr).all()
예제 #2
0
 def test_match_cxy(self):
     xx = np.arange(1, 11) * 1.
     yy = np.arange(1, 11) * 1.
     sx = np.arange(2, 12) * 1.
     sy = np.arange(2, 12) * 1.
     (indxy, indr) = astrotools.match_cxy(xx, yy, sx, sy)
     expected_indxy = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
     expected_indr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
     assert (indxy == expected_indxy).all and (indr == expected_indr).all()
예제 #3
0
def _correlate_sources(ad1, ad2, delta=None, firstPass=10, cull_sources=False):
    """
    This function takes sources from the OBJCAT extensions in two
    images and attempts to correlate them. It returns a list of 
    reference source positions and their correlated image source 
    positions.
    
    :param ad1: reference image
    :type ad1: AstroData instance
    
    :param ad2: input image
    :type ad2: AstroData instance
    
    :param delta: maximum distance in pixels to allow a match. If
                  left as None, it will attempt to find an appropriate
                  number (recommended).
    :type delta: float
    
    :param firstPass: estimated maximum distance between correlated
                      sources. This distance represents the expected
                      mismatch between the WCSs of the input images.
    :type firstPass: float
    
    :param cull_sources: flag to indicate whether to reject sources that
                   are insufficiently star-like
    :type cull_sources: bool
    """

    log = gemLog.getGeminiLog()

    # If desired, clip out the most star-like sources in the OBJCAT
    if cull_sources:
        good_src_1 = gt.clip_sources(ad1)[("SCI", 1)]
        good_src_2 = gt.clip_sources(ad2)[("SCI", 1)]

        if len(good_src_1) < 3 or len(good_src_2) < 3:
            log.warning("Too few sources in culled list, using full set " "of sources")
            x1 = ad1["OBJCAT"].data.field("X_IMAGE")
            y1 = ad1["OBJCAT"].data.field("Y_IMAGE")
            x2 = ad2["OBJCAT"].data.field("X_IMAGE")
            y2 = ad2["OBJCAT"].data.field("Y_IMAGE")
        else:
            x1 = good_src_1["x"]
            y1 = good_src_1["y"]
            x2 = good_src_2["x"]
            y2 = good_src_2["y"]
    else:
        # Otherwise, just get all sources
        x1 = ad1["OBJCAT"].data.field("X_IMAGE")
        y1 = ad1["OBJCAT"].data.field("Y_IMAGE")
        x2 = ad2["OBJCAT"].data.field("X_IMAGE")
        y2 = ad2["OBJCAT"].data.field("Y_IMAGE")

    # get WCS from both images
    wcs1 = pywcs.WCS(ad1["SCI"].header)
    wcs2 = pywcs.WCS(ad2["SCI"].header)

    # convert image 2 data to sky coordinates
    ra2, dec2 = wcs2.wcs_pix2sky(x2, y2, 1)

    # convert image 2 sky data to image 1 pixel coordinates
    conv_x2, conv_y2 = wcs1.wcs_sky2pix(ra2, dec2, 1)

    # find matches
    ind1, ind2 = at.match_cxy(x1, conv_x2, y1, conv_y2, delta=delta, firstPass=firstPass, log=log)

    if len(ind1) != len(ind2):
        raise Errors.ScienceError("Mismatched arrays returned from match_cxy")

    if len(ind1) < 1 or len(ind2) < 1:
        return [[], []]
    else:
        obj_list = [zip(x1[ind1], y1[ind1]), zip(x2[ind2], y2[ind2])]
        return obj_list
def _match_objcat_refcat(adinput=None):
    """
    Match the sources in the objcats against those in the corresponding
    refcat. Update the refid column in the objcat with the Id of the 
    catalog entry in the refcat. Update the refmag column in the objcat
    with the magnitude of the corresponding source in the refcat in the
    band that the image is taken in.

    :param adinput: AD object(s) to match catalogs in
    :type adinput: AstroData objects, either a single instance or a list
    """

    # Instantiate the log. This needs to be done outside of the try block,
    # since the log object is used in the except block 
    log = gemLog.getGeminiLog()

    # The validate_input function ensures that the input is not None and
    # returns a list containing one or more inputs
    adinput_list = gt.validate_input(input=adinput)

    # Initialize the list of output AstroData objects
    adoutput_list = []
    try:

        # Loop over each input AstroData object in the input list
        for ad in adinput_list:
            filter_name = ad.filter_name(pretty=True).as_pytype()
            if filter_name in ['J', 'H', 'K']:
                magcolname = filter_name+'mag'
                magerrcolname = 'e_'+filter_name+'mag'
            else:
                log.warning("Filter %s is not in JHK table - will not be "
                            "able to flux calibrate" % filter_name)
                magcolname = None
                magerrcolname = None

                # Loop through the objcat extensions
            if ad['OBJCAT'] is None:
                raise Errors.InputError("Missing OBJCAT in %s" % (ad.filename))
            for objcat in ad['OBJCAT']:
                extver = objcat.extver()

                # Check that a refcat exists for this objcat extver
                refcat = ad['REFCAT',extver]
                if(not(refcat)):
                    log.warning("Missing [REFCAT,%d] in %s - Cannot match objcat"
                                " against missing refcat" % (extver,ad.filename))
                else:
                    # Get the x and y position lists from both catalogs
                    cat_ra = objcat.data['X_WORLD']    # this is RA
                    cat_dec = objcat.data['Y_WORLD']    # this is DEC
                    ref_ra = refcat.data['RAJ2000']
                    ref_dec = refcat.data['DEJ2000']

                    g=np.where((cat_ra<194.28) & (cat_ra>194.26))
                    #print 'RF0:',cat_ra[g]
                    #print 'RF1:',cat_dec[g]
                    # Get new pixel coordinates for all ra,dec in the dictionary.
                    # Use the input wcs object.
                   
                    # FIXME - need to address the wraparound problem here
                    # if we straddle ra = 360.00 = 0.00

                    initial = 15.0/3600.0 # 15 arcseconds in degrees
                    final = 0.5/3600.0 # 0.5 arcseconds in degrees

                    (oi, ri) = at.match_cxy(cat_ra,ref_ra,cat_dec,ref_dec,
                                      firstPass=initial, delta=final, log=log)

                    # If too few matches, assume the match was bad
                    if len(oi)<1:
                        oi = []

                    log.stdinfo("Matched %d objects in ['OBJCAT',%d] against"
                                " ['REFCAT',%d]" % (len(oi), extver, extver))

                    # Loop through the reference list updating the refid in the objcat
                    # and the refmag, if we can
                    for i in range(len(oi)):
                        objcat.data['REF_NUMBER'][oi[i]] = refcat.data['Id'][ri[i]]
                        if(magcolname):
                            objcat.data['REF_MAG'][oi[i]] = refcat.data[magcolname][ri[i]]
                            objcat.data['REF_MAG_ERR'][oi[i]] = refcat.data[magerrcolname][ri[i]]


            adoutput_list.append(ad)

        return adoutput_list
    except:
        # Log the message from the exception
        log.critical(repr(sys.exc_info()[1]))
        raise