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
def get_key_value_dict(adinput=None, keyword=None, dict_key_extver=False):
    """
    The get_key_value_dict() function works similarly to the AstroData
    get_key_value() and phu_get_key_value() member functions in that if the
    value of the keyword for each pixel data extension is None, None is
    returned and the reason why the value is None is stored in the
    exception_info attribute of the AstroData object.
    
    :param adinput: the AstroData object
    :type adinput: AstroData
    
    :param keyword: the keyword(s) to access in the pixel data extensions of
                    the AstroData object
    :type keyword: string or list of strings
    
    :rtype: dictionary
    :return: if a single keyword is supplied to the keyword parameter, the key
             of the return dictionary is the ('*', EXTVER) tuple and the value
             is the value of the keyword from the header of the pixel data
             extension of the input AstroData object with that EXTVER. If
             multiple keywords are supplied to the keyword parameter, the key
             of the return dictionary is the name of the keyword as supplied to
             the keyword parameter and the value is a dictionary, where the key
             of the dictionary is the ('*', EXTVER) tuple and the value is the
             value of the keyword from the header of the pixel data extension
             of the input AstroData object with that EXTVER.
    
    """
    # Since this helper function accesses keywords in the headers of the pixel
    # data extensions, first construct a dictionary where the key of the
    # dictionary is an (EXTNAME, EXTVER) tuple
    all_keyword_value_dict = {}
    final_keyword_value_dict = {}

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

    return_dictionary = False

    # Loop over the pixel data extensions in the dataset
    for ext in adinput[pixel_exts]:

        # Loop over each keyword in the input keyword list
        for keyword in keyword_list:

            # Get the value of the keyword from the header of each pixel data
            # extension
            value = ext.get_key_value(keyword)

            if value is None:
                # The get_key_value() function returns None if a value cannot
                # be found and stores the exception info. Store the last
                # occurance of the exception to the dataset.
                if hasattr(ext, "exception_info"):
                    setattr(adinput, "exception_info", ext.exception_info)

            if keyword in all_keyword_value_dict:
                # Update the dictionary with the value
                all_keyword_value_dict[keyword].update({(ext.extname(), ext.extver()): value})
            else:
                all_keyword_value_dict.update({keyword: {(ext.extname(), ext.extver()): value}})

    for keyword, keyword_value_dict in all_keyword_value_dict.iteritems():
        try:
            if keyword_value_dict == {}:
                # If the dictionary is still empty, the AstroData object has no
                # pixel data extensions
                raise Errors.CorruptDataError()

            unique_values = set(keyword_value_dict.values())
            if len(unique_values) == 1 and None in unique_values:
                # The value of the keyword was not found for any of the pixel
                # data extensions (all the values in the dictionary are equal
                # to None)
                raise adinput.exception_info

            # Instantiate the DescriptorValue (DV) object
            dv = DescriptorValue(keyword_value_dict)

            # Create a new dictionary where the key of the dictionary is an
            # EXTVER integer
            extver_dict = dv.collapse_by_extver()

            if not dv.validate_collapse_by_extver(extver_dict):
                # The validate_collapse_by_extver function returns False if the
                # values in the dictionary with the same EXTVER are not equal
                raise Errors.CollapseError()

            if dict_key_extver:
                # Return the dictionary where the key of the dictionary is an
                # EXTVER integer
                ret_dict = extver_dict
            else:
                # Instantiate a new DV object using the newly created
                # dictionary and get the dictionary where the key of the
                # dictionary is an ("*", EXTVER) tuple
                new_dv = DescriptorValue(extver_dict)
                ret_dict = new_dv.as_dict()

        except:
            setattr(adinput, "exception_info", sys.exc_info()[1])
            ret_dict = None

        # Construct the dictionary of dictionaries
        final_keyword_value_dict.update({keyword: ret_dict})

    if len(final_keyword_value_dict) == 1:
        return final_keyword_value_dict.values()[0]
    else:
        return final_keyword_value_dict