Instruction:
How would you explain what the following Python 3 function does
def interpret_fit_rms(tweakwcs_output, reference_catalog):
    # Start by collecting information by group_id
    group_ids = [info.meta['group_id'] for info in tweakwcs_output]
    # Compress the list to have only unique group_id values to avoid some unnecessary iterations
    group_ids = list(set(group_ids))
    group_dict = {'avg_RMS':None}
    obs_rms = []
    for group_id in group_ids:
        for item in tweakwcs_output:
            # When status = FAILED (fit failed) or REFERENCE (relative alignment done with first image
            # as the reference), skip to the beginning of the loop as there is no 'fit_info'.
            if item.meta['fit_info']['status'] != 'SUCCESS':
                continue
            # Make sure to store data for any particular group_id only once.
            if item.meta['group_id'] == group_id and \
               group_id not in group_dict:
                    group_dict[group_id] = {'ref_idx':None, 'FIT_RMS':None}
                    log.info("fit_info: {}".format(item.meta['fit_info']))
                    tinfo = item.meta['fit_info']
                    ref_idx = tinfo['matched_ref_idx']
                    fitmask = tinfo['fitmask']
                    group_dict[group_id]['ref_idx'] = ref_idx
                    ref_RA = reference_catalog[ref_idx]['RA'][fitmask]
                    ref_DEC = reference_catalog[ref_idx]['DEC'][fitmask]
                    input_RA = tinfo['fit_RA']
                    input_DEC = tinfo['fit_DEC']
                    img_coords = SkyCoord(input_RA, input_DEC,
                                          unit='deg',frame='icrs')
                    ref_coords = SkyCoord(ref_RA, ref_DEC, unit='deg',frame='icrs')
                    dra, ddec = img_coords.spherical_offsets_to(ref_coords)
                    ra_rms = np.std(dra.to(u.mas))
                    dec_rms = np.std(ddec.to(u.mas))
                    fit_rms = np.std(Angle(img_coords.separation(ref_coords), unit=u.mas)).value
                    group_dict[group_id]['FIT_RMS'] = fit_rms
                    group_dict[group_id]['RMS_RA'] = ra_rms
                    group_dict[group_id]['RMS_DEC'] = dec_rms

                    obs_rms.append(fit_rms)
    # Compute RMS for entire ASN/observation set
    total_rms = np.mean(obs_rms)
    #total_rms = np.sqrt(np.sum(np.array(obs_rms)**2))

    # Now, append computed results to tweakwcs_output
    for item in tweakwcs_output:
        group_id = item.meta['group_id']
        if group_id in group_dict:
            fit_rms = group_dict[group_id]['FIT_RMS']
            ra_rms = group_dict[group_id]['RMS_RA']
            dec_rms = group_dict[group_id]['RMS_DEC']
        else:
            fit_rms = None
            ra_rms = None
            dec_rms = None

        item.meta['fit_info']['FIT_RMS'] = fit_rms
        item.meta['fit_info']['TOTAL_RMS'] = total_rms
        item.meta['fit_info']['NUM_FITS'] = len(group_ids)
        item.meta['fit_info']['RMS_RA'] = ra_rms
        item.meta['fit_info']['RMS_DEC'] = dec_rms
        item.meta['fit_info']['catalog'] = reference_catalog.meta['catalog']

Response: Interpret the FIT information to convert RMS to physical units.


Instruction:
Here you have a function in Python 3, explain what it does
def sky(input=None,outExt=None,configObj=None, group=None, editpars=False, **inputDict):

    if input is not None:
        inputDict['input']=input
        inputDict['output']=None
        inputDict['updatewcs']=False
        inputDict['group']=group
    else:
        print("Please supply an input image", file=sys.stderr)
        raise ValueError

    configObj = util.getDefaultConfigObj(__taskname__,configObj,inputDict,loadOnly=(not editpars))
    if configObj is None:
        return

    if not editpars:
        run(configObj,outExt=outExt)

Response: This function performs a sky subtraction on a list of images and returns a copy of the original input image.


Instruction:
Implement a function in Python 3 to
apply sky value as read in from a user-supplied input file.

Response:
def _skyUserFromFile(imageObjList, skyFile, apply_sky=None):
    """
    Apply sky value as read in from a user-supplied input file.

    """
    skyKW="MDRIZSKY" #header keyword that contains the sky that's been subtracted

    # create dict of fname=sky pairs
    skyvals = {}
    if apply_sky is None:
        skyapplied = False # flag whether sky has already been applied to images
    else:
        skyapplied = apply_sky

    for line in open(skyFile):
        if apply_sky is None and line[0] == '#' and 'applied' in line:
            if '=' in line: linesep = '='
            if ':' in line: linesep = ':'
            appliedstr = line.split(linesep)[1].strip()
            if appliedstr.lower() in ['yes','true','y','t']:
                skyapplied = True
                print('...Sky values already applied by user...')

        if not util.is_blank(line) and line[0] != '#':
            lspl = line.split()
            svals = []
            for lvals in lspl[1:]:
                svals.append(float(lvals))
            skyvals[lspl[0]] = svals

    # Apply user values to appropriate input images
    for imageSet in imageObjList:
        fname = imageSet._filename
        numchips=imageSet._numchips
        sciExt=imageSet.scienceExt
        if fname in skyvals:
            print("    ...updating MDRIZSKY with user-supplied value.")
            for chip in range(1,numchips+1,1):
                if len(skyvals[fname]) == 1:
                    _skyValue = skyvals[fname][0]
                else:
                    _skyValue = skyvals[fname][chip-1]

                chipext = '%s,%d'%(sciExt,chip)
                _updateKW(imageSet[chipext],fname,(sciExt,chip),skyKW,_skyValue)

                # Update internal record with subtracted sky value
                #
                # .computedSky:   value to be applied by the
                #                 adrizzle/ablot steps.
                # .subtractedSky: value already (or will be by adrizzle/ablot)
                #                 subtracted from the image
                if skyapplied:
                    imageSet[chipext].computedSky = None # used by adrizzle/ablot
                else:
                    imageSet[chipext].computedSky = _skyValue
                imageSet[chipext].subtractedSky = _skyValue
                print("Setting ",skyKW,"=",_skyValue)
        else:
            print("*"*40)
            print("*")
            print("WARNING:")
            print("    .... NO user-supplied sky value found for ",fname)
            print("    .... Setting sky to a value of 0.0! ")
            print("*")
            print("*"*40)


Instruction:
Explain what the following Python 3 code does
def _skyUserFromHeaderKwd(imageSet,paramDict):
    _skyValue=0.0    #this will be the sky value computed for the exposure
    skyKW="MDRIZSKY" #header keyword that contains the sky that's been subtracted

    #just making sure, tricky users and all, these are things that will be used
    #by the sky function so we want them defined at least
    try:
        assert imageSet._numchips > 0, "invalid value for number of chips"
        assert imageSet._filename != '', "image object filename is empty!, doh!"
        assert imageSet._rootname != '', "image rootname is empty!, doh!"
        assert imageSet.scienceExt !='', "image object science extension is empty!"

    except AssertionError:
        raise AssertionError

    numchips=imageSet._numchips
    sciExt=imageSet.scienceExt

    # User Subtraction Case, User has done own sky subtraction,
    # so use the image header value for subtractedsky value
    skyuser=paramDict["skyuser"]

    if skyuser != '':
        print("User has computed their own sky values...")

        if skyuser != skyKW:
            print("    ...updating MDRIZSKY with supplied value.")
            for chip in range(1,numchips+1,1):
                chipext = '%s,%d'%(sciExt,chip)
                if not imageSet[chipext].group_member:
                    # skip extensions/chips that will not be processed
                    continue
                try:
                    _skyValue = imageSet[chipext].header[skyuser]
                except:
                    print("**************************************************************")
                    print("*")
                    print("*  Cannot find keyword ",skyuser," in ",imageSet._filename)
                    print("*")
                    print("**************************************************************\n\n\n")
                    raise KeyError

                _updateKW(imageSet[sciExt+','+str(chip)],
                          imageSet._filename,(sciExt,chip),skyKW,_skyValue)

                # Update internal record with subtracted sky value
                imageSet[chipext].subtractedSky = _skyValue
                imageSet[chipext].computedSky = None
                print("Setting ",skyKW,"=",_skyValue)

Response: This function is used to subtract the sky value from all the chips in the image file that imageSet represents and the image header keyword that contains the sky user in the imageSet.


Instruction:
Create a Python 3 function for
subtracting the sky from all the chips in the imagefile that imageSet represents imageSet is a single imageObject reference paramDict should be the subset from an actual config object if saveFile=True, then images that have been sky subtracted are saved to a predetermined output name else, overwrite the input images with the sky-subtracted results the output from sky subtraction is a copy of the original input file where all the science data extensions have been sky subtracted

Response:
def _skySub(imageSet,paramDict,saveFile=False):
    """
    subtract the sky from all the chips in the imagefile that imageSet represents

    imageSet is a single imageObject reference
    paramDict should be the subset from an actual config object
    if saveFile=True, then images that have been sky subtracted are saved to a predetermined output name
    else, overwrite the input images with the sky-subtracted results

    the output from sky subtraction is a copy of the original input file
    where all the science data extensions have been sky subtracted

    """

    _skyValue=0.0    #this will be the sky value computed for the exposure
    skyKW="MDRIZSKY" #header keyword that contains the sky that's been subtracted

    #just making sure, tricky users and all, these are things that will be used
    #by the sky function so we want them defined at least
    try:
        assert imageSet._numchips > 0, "invalid value for number of chips"
        assert imageSet._filename != '', "image object filename is empty!, doh!"
        assert imageSet._rootname != '', "image rootname is empty!, doh!"
        assert imageSet.scienceExt !='', "image object science extension is empty!"

    except AssertionError:
        raise AssertionError

    numchips=imageSet._numchips
    sciExt=imageSet.scienceExt

    # User Subtraction Case, User has done own sky subtraction,
    # so use the image header value for subtractedsky value
    skyuser=paramDict["skyuser"]

    if skyuser != '':
        print("User has computed their own sky values...")

        if skyuser != skyKW:
            print("    ...updating MDRIZSKY with supplied value.")
            for chip in range(1,numchips+1,1):
                try:
                    chipext = '%s,%d'%(sciExt,chip)
                    _skyValue = imageSet[chipext].header[skyuser]

                except:
                    print("**************************************************************")
                    print("*")
                    print("*  Cannot find keyword ",skyuser," in ",imageSet._filename)
                    print("*")
                    print("**************************************************************\n\n\n")
                    raise KeyError

                _updateKW(imageSet[sciExt+','+str(chip)],imageSet._filename,(sciExt,chip),skyKW,_skyValue)

                # Update internal record with subtracted sky value
                imageSet[chipext].subtractedSky = _skyValue
                imageSet[chipext].computedSky = None
                print("Setting ",skyKW,"=",_skyValue)

    else:
        # Compute our own sky values and record the values for use later.
        # The minimum sky value from all the  science chips in the exposure
        # is used as the reference sky for each chip

        log.info("Computing minimum sky ...")
        minSky=[] #store the sky for each chip
        minpscale = []

        for chip in range(1,numchips+1,1):
            myext=sciExt+","+str(chip)

            #add the data back into the chip, leave it there til the end of this function
            imageSet[myext].data=imageSet.getData(myext)

            image=imageSet[myext]
            _skyValue= _computeSky(image, paramDict, memmap=False)
            #scale the sky value by the area on sky
            # account for the case where no IDCSCALE has been set, due to a
            # lack of IDCTAB or to 'coeffs=False'.
            pscale=imageSet[myext].wcs.idcscale
            if pscale is None:
                log.warning("No Distortion coefficients available...using "
                            "default plate scale.")
                pscale = imageSet[myext].wcs.pscale
            _scaledSky=_skyValue / (pscale**2)
            #_skyValue=_scaledSky
            minSky.append(_scaledSky)
            minpscale.append(pscale)

        _skyValue = min(minSky)

        _reportedSky = _skyValue*(minpscale[minSky.index(_skyValue)]**2)
        log.info("Minimum sky value for all chips %s" % _reportedSky)

        #now subtract that value from all the chips in the exposure
        #and update the chips header keyword with the sub
        for chip in range(1,numchips+1,1):
            image=imageSet[sciExt,chip]
            myext = sciExt+","+str(chip)
            # account for the case where no IDCSCALE has been set, due to a
            # lack of IDCTAB or to 'coeffs=False'.
            idcscale = image.wcs.idcscale
            if idcscale is None: idcscale = image.wcs.pscale
            _scaledSky=_skyValue * (idcscale**2)
            image.subtractedSky = _scaledSky
            image.computedSky = _scaledSky
            log.info("Using sky from chip %d: %f\n" % (chip,_scaledSky))
            ###_subtractSky(image,(_scaledSky))
            # Update the header so that the keyword in the image is
            #the sky value which should be subtracted from the image
            _updateKW(image,imageSet._filename,(sciExt,chip),skyKW,_scaledSky)


Instruction:
Can you implement a function in Python 3 that
computes the sky value for the data array passed to the function

Response:
def _computeSky(image, skypars, memmap=False):

    """
    Compute the sky value for the data array passed to the function
    image is a fits object which contains the data and the header
    for one image extension

    skypars is passed in as paramDict

    """
    #this object contains the returned values from the image stats routine
    _tmp = imagestats.ImageStats(image.data,
            fields      = skypars['skystat'],
            lower       = skypars['skylower'],
            upper       = skypars['skyupper'],
            nclip       = skypars['skyclip'],
            lsig        = skypars['skylsigma'],
            usig        = skypars['skyusigma'],
            binwidth    = skypars['skywidth']
            )

    _skyValue = _extractSkyValue(_tmp,skypars['skystat'].lower())
    log.info("    Computed sky value/pixel for %s: %s "%
             (image.rootname, _skyValue))

    del _tmp

    return _skyValue


Instruction:
Explain what the following Python 3 code does
def _subtractSky(image,skyValue,memmap=False):
    try:
        np.subtract(image.data,skyValue,image.data)

    except IOError:
        print("Unable to perform sky subtraction on data array")
        raise IOError

Response: Subtracts the given sky value from each image in the data array.


Instruction:
Write a Python 3 script to
update the header with the kw value

Response:
def _updateKW(image, filename, exten, skyKW, Value):
    """update the header with the kw,value"""
    # Update the value in memory
    image.header[skyKW] = Value

    # Now update the value on disk
    if isinstance(exten,tuple):
        strexten = '[%s,%s]'%(exten[0],str(exten[1]))
    else:
        strexten = '[%s]'%(exten)
    log.info('Updating keyword %s in %s' % (skyKW, filename + strexten))
    fobj = fileutil.openImage(filename, mode='update', memmap=False)
    fobj[exten].header[skyKW] = (Value, 'Sky value computed by AstroDrizzle')
    fobj.close()


Instruction:
Explain what the following Python 3 code does
def _addDefaultSkyKW(imageObjList):
    skyKW = "MDRIZSKY"
    Value = 0.0
    for imageSet in imageObjList:
        fname = imageSet._filename
        numchips=imageSet._numchips
        sciExt=imageSet.scienceExt
        fobj = fileutil.openImage(fname, mode='update', memmap=False)
        for chip in range(1,numchips+1,1):
            ext = (sciExt,chip)
            if not imageSet[ext].group_member:
                # skip over extensions not used in processing
                continue
            if skyKW not in fobj[ext].header:
                fobj[ext].header[skyKW] = (Value, 'Sky value computed by AstroDrizzle')
                log.info("MDRIZSKY keyword not found in the %s[%s,%d] header."%(
                            fname,sciExt,chip))
                log.info("    Adding MDRIZSKY to header with default value of 0.")
        fobj.close()

Response: Add MDRIZSKY keyword to all input images and SCI headers of all input images.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def help(file=None):
    helpstr = getHelpAsString(docstring=True, show_ver = True)
    if file is None:
        print(helpstr)
    else:
        if os.path.exists(file): os.remove(file)
        f = open(file, mode = 'w')
        f.write(helpstr)
        f.close()

Response: Print out syntax help for running astrodrizzle


Instruction:
How would you explain what the following Python 3 function does
def rd2xy(input,ra=None,dec=None,coordfile=None,colnames=None,
            precision=6,output=None,verbose=True):
    """ Primary interface to perform coordinate transformations from
        pixel to sky coordinates using STWCS and full distortion models
        read from the input image header.
    """
    single_coord = False
    if coordfile is not None:
        if colnames in blank_list:
            colnames = ['c1','c2']
        elif isinstance(colnames,type('a')):
            colnames = colnames.split(',')
        # convert input file coordinates to lists of decimal degrees values
        xlist,ylist = tweakutils.readcols(coordfile,cols=colnames)
    else:
        if isinstance(ra,np.ndarray):
            ralist = ra.tolist()
            declist = dec.tolist()
        elif not isinstance(ra, list):
            ralist = [ra]
            declist = [dec]
        else:
            ralist = ra
            declist = dec
        xlist  = [0]*len(ralist)
        ylist = [0]*len(ralist)
        if len(xlist) == 1:
            single_coord = True
        for i,(r,d) in enumerate(zip(ralist,declist)):
            # convert input value into decimal degrees value
            xval,yval = tweakutils.parse_skypos(r,d)
            xlist[i] = xval
            ylist[i] = yval

    # start by reading in WCS+distortion info for input image
    inwcs = wcsutil.HSTWCS(input)
    if inwcs.wcs.is_unity():
        print("####\nNo valid WCS found in {}.\n  Results may be invalid.\n####\n".format(input))

    # Now, convert pixel coordinates into sky coordinates
    try:
        outx,outy = inwcs.all_world2pix(xlist,ylist,1)
    except RuntimeError:
        outx,outy = inwcs.wcs_world2pix(xlist,ylist,1)

    # add formatting based on precision here...
    xstr = []
    ystr = []
    fmt = "%."+repr(precision)+"f"
    for x,y in zip(outx,outy):
        xstr.append(fmt%x)
        ystr.append(fmt%y)

    if verbose or (not verbose and util.is_blank(output)):
        print ('# Coordinate transformations for ',input)
        print('# X      Y         RA             Dec\n')
        for x,y,r,d in zip(xstr,ystr,xlist,ylist):
            print("%s  %s    %s  %s"%(x,y,r,d))

    # Create output file, if specified
    if output:
        f = open(output,mode='w')
        f.write("# Coordinates converted from %s\n"%input)
        for x,y in zip(xstr,ystr):
            f.write('%s    %s\n'%(x,y))
        f.close()
        print('Wrote out results to: ',output)

    if single_coord:
        outx = outx[0]
        outy = outy[0]

    return outx, outy

Response: This function converts pixel coordinates to sky coordinates using STWCS and full distortion models from the input image header.


Instruction:
Write a Python 3 function that can
create an astrometric catalog that covers the input images field - of - view.

Response:
def create_astrometric_catalog(inputs, **pars):
    """Create an astrometric catalog that covers the inputs' field-of-view.

    Parameters
    ----------
    input : str, list
        Filenames of images to be aligned to astrometric catalog

    catalog : str, optional
        Name of catalog to extract astrometric positions for sources in the
        input images' field-of-view. Default: GAIADR2. Options available are
        documented on the catalog web page.

    output : str, optional
        Filename to give to the astrometric catalog read in from the master
        catalog web service.  If None, no file will be written out.

    gaia_only : bool, optional
        Specify whether or not to only use sources from GAIA in output catalog
        Default: False

    existing_wcs : ~stwcs.wcsutils.HSTWCS`
        existing WCS object specified by the user

    Notes
    -----
    This function will point to astrometric catalog web service defined
    through the use of the ASTROMETRIC_CATALOG_URL environment variable.

    Returns
    -------
    ref_table : ~.astropy.table.Table`
        Astropy Table object of the catalog

    """
    # interpret input parameters
    catalog = pars.get("catalog", 'GAIADR2')
    output = pars.get("output", 'ref_cat.ecsv')
    gaia_only = pars.get("gaia_only", False)
    table_format = pars.get("table_format", 'ascii.ecsv')
    existing_wcs = pars.get("existing_wcs", None)

    inputs, _ = parseinput.parseinput(inputs)
    # start by creating a composite field-of-view for all inputs
    # This default output WCS will have the same plate-scale and orientation
    # as the first chip in the list, which for WFPC2 data means the PC.
    # Fortunately, for alignment, this doesn't matter since no resampling of
    # data will be performed
    if existing_wcs:
        outwcs = existing_wcs
    else:
        outwcs = build_reference_wcs(inputs)
    radius = compute_radius(outwcs)
    ra, dec = outwcs.wcs.crval

    # perform query for this field-of-view
    ref_dict = get_catalog(ra, dec, sr=radius, catalog=catalog)
    colnames = ('ra', 'dec', 'mag', 'objID', 'GaiaID')
    col_types = ('f8', 'f8', 'f4', 'U25', 'U25')
    ref_table = Table(names=colnames, dtype=col_types)

    # Add catalog name as meta data
    ref_table.meta['catalog'] = catalog
    ref_table.meta['gaia_only'] = gaia_only

    # rename coordinate columns to be consistent with tweakwcs
    ref_table.rename_column('ra', 'RA')
    ref_table.rename_column('dec', 'DEC')

    # extract just the columns we want...
    num_sources = 0
    for source in ref_dict:
        if 'GAIAsourceID' in source:
            g = source['GAIAsourceID']
            if gaia_only and g.strip() == '':
                continue
        else:
            g = "-1"  # indicator for no source ID extracted
        r = float(source['ra'])
        d = float(source['dec'])
        m = -999.9  # float(source['mag'])
        o = source['objID']
        num_sources += 1
        ref_table.add_row((r, d, m, o, g))

    # Write out table to a file, if specified
    if output:
        ref_table.write(output, format=table_format)
        log.info("Created catalog '{}' with {} sources".format(output, num_sources))

    return ref_table


Instruction:
Can you implement a function in Python 3 that
creates the reference WCS based on all the inputs for a field

Response:
def build_reference_wcs(inputs, sciname='sci'):
    """Create the reference WCS based on all the inputs for a field"""
    # start by creating a composite field-of-view for all inputs
    wcslist = []
    for img in inputs:
        nsci = countExtn(img)
        for num in range(nsci):
            extname = (sciname, num + 1)
            if sciname == 'sci':
                extwcs = wcsutil.HSTWCS(img, ext=extname)
            else:
                # Working with HDRLET as input and do the best we can...
                extwcs = read_hlet_wcs(img, ext=extname)

            wcslist.append(extwcs)

    # This default output WCS will have the same plate-scale and orientation
    # as the first chip in the list, which for WFPC2 data means the PC.
    # Fortunately, for alignment, this doesn't matter since no resampling of
    # data will be performed
    outwcs = utils.output_wcs(wcslist)

    return outwcs


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_catalog(ra, dec, sr=0.1, fmt='CSV', catalog='GSC241'):
    serviceType = 'vo/CatalogSearch.aspx'
    spec_str = 'RA={}&DEC={}&SR={}&FORMAT={}&CAT={}&MINDET=5'
    headers = {'Content-Type': 'text/csv'}

    spec = spec_str.format(ra, dec, sr, fmt, catalog)
    serviceUrl = '{}/{}?{}'.format(SERVICELOCATION, serviceType, spec)
    rawcat = requests.get(serviceUrl, headers=headers)
    r_contents = rawcat.content.decode()  # convert from bytes to a String
    rstr = r_contents.split('\r\n')
    # remove initial line describing the number of sources returned
    # CRITICAL to proper interpretation of CSV data
    del rstr[0]
    r_csv = csv.DictReader(rstr)

    return r_csv

Response: Extract a catalog from VO web service.


Instruction:
Implement a Python 3 function for
computing the radius from the center to the furthest edge of the WCS.

Response:
def compute_radius(wcs):
    """Compute the radius from the center to the furthest edge of the WCS."""

    ra, dec = wcs.wcs.crval
    img_center = SkyCoord(ra=ra * u.degree, dec=dec * u.degree)
    wcs_foot = wcs.calc_footprint()
    img_corners = SkyCoord(ra=wcs_foot[:, 0] * u.degree,
                           dec=wcs_foot[:, 1] * u.degree)
    radius = img_center.separation(img_corners).max().value

    return radius


Instruction:
How would you explain what the following Python 3 function does
def find_gsc_offset(image, input_catalog='GSC1', output_catalog='GAIA'):
    serviceType = "GSCConvert/GSCconvert.aspx"
    spec_str = "TRANSFORM={}-{}&IPPPSSOOT={}"

    if 'rootname' in pf.getheader(image):
        ippssoot = pf.getval(image, 'rootname').upper()
    else:
        ippssoot = fu.buildNewRootname(image).upper()

    spec = spec_str.format(input_catalog, output_catalog, ippssoot)
    serviceUrl = "{}/{}?{}".format(SERVICELOCATION, serviceType, spec)
    rawcat = requests.get(serviceUrl)
    if not rawcat.ok:
        log.info("Problem accessing service with:\n{{}".format(serviceUrl))
        raise ValueError

    delta_ra = delta_dec = None
    tree = BytesIO(rawcat.content)
    for _, element in etree.iterparse(tree):
        if element.tag == 'deltaRA':
            delta_ra = float(element.text)
        elif element.tag == 'deltaDEC':
            delta_dec = float(element.text)

    return delta_ra, delta_dec

Response: Find the GSC to GAIA offset based on guide star coordinates relative to GAIA.


Instruction:
Can you write a function in Python 3 where it
uses photutils to find sources in image based on segmentation.

Response:
def extract_sources(img, **pars):
    """Use photutils to find sources in image based on segmentation.

    Parameters
    ----------
    dqmask : ndarray
        Bitmask which identifies whether a pixel should be used (1) in source
        identification or not(0). If provided, this mask will be applied to the
        input array prior to source identification.

    fwhm : float
        Full-width half-maximum (fwhm) of the PSF in pixels.

    threshold : float or None
        Value from the image which serves as the limit for determining sources.
        If None, compute a default value of (background+5*rms(background)).
        If threshold < 0.0, use absolute value as scaling factor for default value.

    source_box : int
        Size of box (in pixels) which defines the minimum size of a valid source.

    classify : bool
        Specify whether or not to apply classification based on invarient moments
        of each source to determine whether or not a source is likely to be a
        cosmic-ray, and not include those sources in the final catalog.

    centering_mode : str
        "segmentaton" or "starfind"
        Algorithm to use when computing the positions of the detected sources.
        Centering will only take place after `threshold` has been determined, and
        sources are identified using segmentation.  Centering using `segmentation`
        will rely on `photutils.segmentation.source_properties` to generate the
        properties for the source catalog.  Centering using `starfind` will use
        `photutils.IRAFStarFinder` to characterize each source in the catalog.

    nlargest : int, None
        Number of largest (brightest) sources in each chip/array to measure
        when using 'starfind' mode.

    output : str
        If specified, write out the catalog of sources to the file with this name.

    plot : bool
        Specify whether or not to create a plot of the sources on a view of the image.

    vmax : float
        If plotting the sources, scale the image to this maximum value.

    """
    fwhm = pars.get('fwhm', 3.0)
    threshold = pars.get('threshold', None)
    source_box = pars.get('source_box', 7)
    classify = pars.get('classify', True)
    output = pars.get('output', None)
    plot = pars.get('plot', False)
    vmax = pars.get('vmax', None)
    centering_mode = pars.get('centering_mode', 'starfind')
    deblend = pars.get('deblend', False)
    dqmask = pars.get('dqmask', None)
    nlargest = pars.get('nlargest', None)
    # apply any provided dqmask for segmentation only
    if dqmask is not None:
        imgarr = img.copy()
        imgarr[dqmask] = 0
    else:
        imgarr = img

    bkg_estimator = MedianBackground()
    bkg = None

    exclude_percentiles = [10, 25, 50, 75]
    for percentile in exclude_percentiles:
        try:
            bkg = Background2D(imgarr, (50, 50), filter_size=(3, 3),
                               bkg_estimator=bkg_estimator,
                               exclude_percentile=percentile)
            # If it succeeds, stop and use that value
            bkg_rms = (5. * bkg.background_rms)
            bkg_rms_mean = bkg.background.mean() + 5. * bkg_rms.std()
            default_threshold = bkg.background + bkg_rms
            if threshold is None or threshold < 0.0:
                if threshold is not None and threshold < 0.0:
                    threshold = -1 * threshold * default_threshold
                    log.info("{} based on {}".format(threshold.max(), default_threshold.max()))
                    bkg_rms_mean = threshold.max()
                else:
                    threshold = default_threshold
            else:
                bkg_rms_mean = 3. * threshold
            if bkg_rms_mean < 0:
                bkg_rms_mean = 0.
            break
        except Exception:
            bkg = None

    # If Background2D does not work at all, define default scalar values for
    # the background to be used in source identification
    if bkg is None:
        bkg_rms_mean = max(0.01, imgarr.min())
        bkg_rms = bkg_rms_mean * 5

    sigma = fwhm * gaussian_fwhm_to_sigma
    kernel = Gaussian2DKernel(sigma, x_size=source_box, y_size=source_box)
    kernel.normalize()
    segm = detect_sources(imgarr, threshold, npixels=source_box,
                          filter_kernel=kernel)
    if deblend:
        segm = deblend_sources(imgarr, segm, npixels=5,
                               filter_kernel=kernel, nlevels=16,
                               contrast=0.01)
    # If classify is turned on, it should modify the segmentation map
    if classify:
        cat = source_properties(imgarr, segm)
        if len(cat) > 0:
            # Remove likely cosmic-rays based on central_moments classification
            bad_srcs = np.where(classify_sources(cat) == 0)[0] + 1
            segm.remove_labels(bad_srcs)  # CAUTION: May be time-consuming!!!

    # convert segm to mask for daofind
    if centering_mode == 'starfind':
        src_table = None
        # daofind = IRAFStarFinder(fwhm=fwhm, threshold=5.*bkg.background_rms_median)
        log.info("Setting up DAOStarFinder with: \n    fwhm={}  threshold={}".format(fwhm, bkg_rms_mean))
        daofind = DAOStarFinder(fwhm=fwhm, threshold=bkg_rms_mean)
        # Identify nbrightest/largest sources
        if nlargest is not None:
            if nlargest > len(segm.labels):
                nlargest = len(segm.labels)
            large_labels = np.flip(np.argsort(segm.areas) + 1)[: nlargest]
        log.info("Looking for sources in {} segments".format(len(segm.labels)))

        for label in segm.labels:
            if nlargest is not None and label not in large_labels:
                continue  # Move on to the next segment
            # Get slice definition for the segment with this label
            seg_slice = segm.segments[label - 1].slices
            seg_yoffset = seg_slice[0].start
            seg_xoffset = seg_slice[1].start

            # Define raw data from this slice
            detection_img = img[seg_slice]
            # zero out any pixels which do not have this segments label
            detection_img[np.where(segm.data[seg_slice] == 0)] = 0

            # Detect sources in this specific segment
            seg_table = daofind(detection_img)
            # Pick out brightest source only
            if src_table is None and len(seg_table) > 0:
                # Initialize final master source list catalog
                src_table = Table(names=seg_table.colnames,
                                  dtype=[dt[1] for dt in seg_table.dtype.descr])
            if len(seg_table) > 0:
                max_row = np.where(seg_table['peak'] == seg_table['peak'].max())[0][0]
                # Add row for detected source to master catalog
                # apply offset to slice to convert positions into full-frame coordinates
                seg_table['xcentroid'] += seg_xoffset
                seg_table['ycentroid'] += seg_yoffset
                src_table.add_row(seg_table[max_row])

    else:
        cat = source_properties(img, segm)
        src_table = cat.to_table()
        # Make column names consistent with IRAFStarFinder column names
        src_table.rename_column('source_sum', 'flux')
        src_table.rename_column('source_sum_err', 'flux_err')

    if src_table is not None:
        log.info("Total Number of detected sources: {}".format(len(src_table)))
    else:
        log.info("No detected sources!")
        return None, None

    # Move 'id' column from first to last position
    # Makes it consistent for remainder of code
    cnames = src_table.colnames
    cnames.append(cnames[0])
    del cnames[0]
    tbl = src_table[cnames]

    if output:
        tbl['xcentroid'].info.format = '.10f'  # optional format
        tbl['ycentroid'].info.format = '.10f'
        tbl['flux'].info.format = '.10f'
        if not output.endswith('.cat'):
            output += '.cat'
        tbl.write(output, format='ascii.commented_header')
        log.info("Wrote source catalog: {}".format(output))

    if plot and plt is not None:
        norm = None
        if vmax is None:
            norm = ImageNormalize(stretch=SqrtStretch())
        fig, ax = plt.subplots(2, 2, figsize=(8, 8))
        ax[0][0].imshow(imgarr, origin='lower', cmap='Greys_r', norm=norm, vmax=vmax)
        ax[0][1].imshow(segm, origin='lower', cmap=segm.cmap(random_state=12345))
        ax[0][1].set_title('Segmentation Map')
        ax[1][0].imshow(bkg.background, origin='lower')
        if not isinstance(threshold, float):
            ax[1][1].imshow(threshold, origin='lower')
    return tbl, segm


Instruction:
Can you generate the documentation for the following Python 3 function
def classify_sources(catalog, sources=None):
    moments = catalog.moments_central
    if sources is None:
        sources = (0, len(moments))
    num_sources = sources[1] - sources[0]
    srctype = np.zeros((num_sources,), np.int32)
    for src in range(sources[0], sources[1]):
        # Protect against spurious detections
        src_x = catalog[src].xcentroid
        src_y = catalog[src].ycentroid
        if np.isnan(src_x) or np.isnan(src_y):
            continue
        x, y = np.where(moments[src] == moments[src].max())
        if (x[0] > 1) and (y[0] > 1):
            srctype[src] = 1

    return srctype

Response: This function converts moments_central attribute for source catalog into star flag.


Instruction:
How would you explain what the following Python 3 function does
def generate_source_catalog(image, **kwargs):
    if not isinstance(image, pf.HDUList):
        raise ValueError("Input {} not fits.HDUList object".format(image))
    dqname = kwargs.get('dqname', 'DQ')
    output = kwargs.get('output', None)
    # Build source catalog for entire image
    source_cats = {}
    numSci = countExtn(image, extname='SCI')

    for chip in range(numSci):
        chip += 1
        # find sources in image
        if output:
            rootname = image[0].header['rootname']
            outroot = '{}_sci{}_src'.format(rootname, chip)
            kwargs['output'] = outroot
        imgarr = image['sci', chip].data

        # apply any DQ array, if available
        dqmask = None
        if image.index_of(dqname):
            dqarr = image[dqname, chip].data

            # "grow out" regions in DQ mask flagged as saturated by several
            # pixels in every direction to prevent the
            # source match algorithm from trying to match multiple sources
            # from one image to a single source in the
            # other or vice-versa.
            # Create temp DQ mask containing all pixels flagged with any value EXCEPT 256
            non_sat_mask = bitfield_to_boolean_mask(dqarr, ignore_flags=256)

            # Create temp DQ mask containing saturated pixels ONLY
            sat_mask = bitfield_to_boolean_mask(dqarr, ignore_flags=~256)

            # Grow out saturated pixels by a few pixels in every direction
            grown_sat_mask = ndimage.binary_dilation(sat_mask, iterations=5)

            # combine the two temporary DQ masks into a single composite DQ mask.
            dqmask = np.bitwise_or(non_sat_mask, grown_sat_mask)

            # dqmask = bitfield_to_boolean_mask(dqarr, good_mask_value=False)
            # TODO: <---Remove this old no-sat bit grow line once this
            # thing works

        seg_tab, segmap = extract_sources(imgarr, dqmask=dqmask, **kwargs)
        seg_tab_phot = seg_tab

        source_cats[chip] = seg_tab_phot

    return source_cats

Response: Generates source catalogs for each chip in the input image.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def generate_sky_catalog(image, refwcs, **kwargs):
    # Extract source catalogs for each chip
    source_cats = generate_source_catalog(image, **kwargs)

    # Build source catalog for entire image
    master_cat = None
    numSci = countExtn(image, extname='SCI')
    # if no refwcs specified, build one now...
    if refwcs is None:
        refwcs = build_reference_wcs([image])
    for chip in range(numSci):
        chip += 1
        # work with sources identified from this specific chip
        seg_tab_phot = source_cats[chip]
        if seg_tab_phot is None:
            continue
        # Convert pixel coordinates from this chip to sky coordinates
        chip_wcs = wcsutil.HSTWCS(image, ext=('sci', chip))
        seg_ra, seg_dec = chip_wcs.all_pix2world(seg_tab_phot['xcentroid'], seg_tab_phot['ycentroid'], 1)
        # Convert sky positions to pixel positions in the reference WCS frame
        seg_xy_out = refwcs.all_world2pix(seg_ra, seg_dec, 1)
        seg_tab_phot['xcentroid'] = seg_xy_out[0]
        seg_tab_phot['ycentroid'] = seg_xy_out[1]
        if master_cat is None:
            master_cat = seg_tab_phot
        else:
            master_cat = vstack([master_cat, seg_tab_phot])

    return master_cat

Response: Generates a source catalog from input image using photutils.


Instruction:
Can you tell what is the following Python 3 function doing
def compute_photometry(catalog, photmode):
    # Determine VEGAMAG zero-point using pysynphot for this photmode
    photmode = photmode.replace(' ', ', ')
    vega = S.FileSpectrum(VEGASPEC)
    bp = S.ObsBandpass(photmode)
    vegauvis = S.Observation(vega, bp)
    vegazpt = 2.5 * np.log10(vegauvis.countrate())

    # Use zero-point to convert flux values from catalog into magnitudes
    # source_phot = vegazpt - 2.5*np.log10(catalog['source_sum'])
    source_phot = vegazpt - 2.5 * np.log10(catalog['flux'])
    source_phot.name = 'vegamag'
    # Now add this new column to the catalog table
    catalog.add_column(source_phot)

    return catalog

Response: Compute magnitudes for sources based on observations photmode.


Instruction:
Implement a function in Python 3 to
filter the input catalog by photometry.

Response:
def filter_catalog(catalog, **kwargs):
    """ Create a new catalog selected from input based on photometry.

    Parameters
    ----------
    bright_limit : float
        Fraction of catalog based on brightness that should be retained.
        Value of 1.00 means full catalog.

    max_bright : int
        Maximum number of sources to keep regardless of `bright_limit`.

    min_bright : int
        Minimum number of sources to keep regardless of `bright_limit`.

    colname : str
        Name of column to use for selection/sorting.

    Returns
    -------
    new_catalog : `~astropy.table.Table`
        New table which only has the sources that meet the selection criteria.
    """
    # interpret input pars
    bright_limit = kwargs.get('bright_limit', 1.00)
    max_bright = kwargs.get('max_bright', None)
    min_bright = kwargs.get('min_bright', 20)
    colname = kwargs.get('colname', 'vegamag')

    # sort by magnitude
    phot_column = catalog[colname]
    num_sources = len(phot_column)
    sort_indx = np.argsort(phot_column)
    if max_bright is None:
        max_bright = num_sources

    # apply limits, insuring no more than full catalog gets selected
    limit_num = max(int(num_sources * bright_limit), min_bright)
    limit_num = min(max_bright, limit_num, num_sources)

    # Extract sources identified by selection
    new_catalog = catalog[sort_indx[:limit_num]]

    return new_catalog


Instruction:
Can you tell what is the following Python 3 function doing
def read_hlet_wcs(filename, ext):
    hstwcs = wcsutil.HSTWCS(filename, ext=ext)
    if hstwcs.naxis1 is None:
        hstwcs.naxis1 = int(hstwcs.wcs.crpix[0] * 2.)  # Assume crpix is center of chip
        hstwcs.naxis2 = int(hstwcs.wcs.crpix[1] * 2.)

    return hstwcs

Response: Read a HSTWCS file and return a WCS object.


Instruction:
Here you have a function in Python 3, explain what it does
def build_hstwcs(crval1, crval2, crpix1, crpix2, naxis1, naxis2, pscale, orientat):
    wcsout = wcsutil.HSTWCS()
    wcsout.wcs.crval = np.array([crval1, crval2])
    wcsout.wcs.crpix = np.array([crpix1, crpix2])
    wcsout.naxis1 = naxis1
    wcsout.naxis2 = naxis2
    wcsout.wcs.cd = buildRotMatrix(orientat) * [-1, 1] * pscale / 3600.0
    # Synchronize updates with astropy.wcs objects
    wcsout.wcs.set()
    wcsout.setPscale()
    wcsout.setOrient()
    wcsout.wcs.ctype = ['RA---TAN', 'DEC--TAN']

    return wcsout

Response: Build an astropy. wcsutil. HSTWCS object for a default instrument with the given crval pix1 and pix2.


Instruction:
How would you explain what the following Python 3 function does
def within_footprint(img, wcs, x, y):
    # start with limits of WCS shape
    if hasattr(wcs, 'naxis1'):
        naxis1 = wcs.naxis1
        naxis2 = wcs.naxis2
    elif hasattr(wcs, 'pixel_shape'):
        naxis1, naxis2 = wcs.pixel_shape
    else:
        naxis1 = wcs._naxis1
        naxis2 = wcs._naxis2
    maskx = np.bitwise_or(x < 0, x > naxis1)
    masky = np.bitwise_or(y < 0, y > naxis2)
    mask = ~np.bitwise_or(maskx, masky)
    x = x[mask]
    y = y[mask]

    # Now, confirm that these points fall within actual science area of WCS
    img_mask = create_image_footprint(img, wcs, border=1.0)
    inmask = np.where(img_mask[y.astype(np.int32), x.astype(np.int32)])[0]
    x = x[inmask]
    y = y[inmask]
    return x, y

Response: Determine whether input x y fall within the science area of the image.


Instruction:
Write a Python 3 script for
creating the footprint of the image in the reference WCS frame.

Response:
def create_image_footprint(image, refwcs, border=0.):
    """ Create the footprint of the image in the reference WCS frame.

    Parameters
    ----------
    image : `astropy.io.fits.HDUList` or str
        Image to extract sources for matching to
        the external astrometric catalog.

    refwcs : `stwcs.wcsutil.HSTWCS`
        Reference WCS for coordinate frame of image.

    border : float
        Buffer (in arcseconds) around edge of image to exclude astrometric
        sources.

    """
    # Interpret input image to generate initial source catalog and WCS
    if isinstance(image, str):
        image = pf.open(image)
    numSci = countExtn(image, extname='SCI')
    ref_x = refwcs._naxis1
    ref_y = refwcs._naxis2
    # convert border value into pixels
    border_pixels = int(border / refwcs.pscale)

    mask_arr = np.zeros((ref_y, ref_x), dtype=int)

    for chip in range(numSci):
        chip += 1
        # Build arrays of pixel positions for all edges of chip
        chip_y, chip_x = image['sci', chip].data.shape
        chipwcs = wcsutil.HSTWCS(image, ext=('sci', chip))
        xpix = np.arange(chip_x) + 1
        ypix = np.arange(chip_y) + 1
        edge_x = np.hstack([[1] * chip_y, xpix, [chip_x] * chip_y, xpix])
        edge_y = np.hstack([ypix, [1] * chip_x, ypix, [chip_y] * chip_x])
        edge_ra, edge_dec = chipwcs.all_pix2world(edge_x, edge_y, 1)
        edge_x_out, edge_y_out = refwcs.all_world2pix(edge_ra, edge_dec, 0)
        edge_x_out = np.clip(edge_x_out.astype(np.int32), 0, ref_x - 1)
        edge_y_out = np.clip(edge_y_out.astype(np.int32), 0, ref_y - 1)
        mask_arr[edge_y_out, edge_x_out] = 1

    # Fill in outline of each chip
    mask_arr = ndimage.binary_fill_holes(ndimage.binary_dilation(mask_arr, iterations=2))

    if border > 0.:
        mask_arr = ndimage.binary_erosion(mask_arr, iterations=border_pixels)

    return mask_arr


Instruction:
How would you code a function in Python 3 to
build a list of WCS objects for all chips in an image and a set of source catalogs.

Response:
def build_wcscat(image, group_id, source_catalog):
    """ Return a list of `~tweakwcs.tpwcs.FITSWCS` objects for all chips in an image.

    Parameters
    ----------
    image : str, ~astropy.io.fits.HDUList`
        Either filename or HDUList of a single HST observation.

    group_id : int
        Integer ID for group this image should be associated with; primarily
        used when separate chips are in separate files to treat them all as one
        exposure.

    source_catalog : dict
        If provided, these catalogs will be attached as `catalog`
        entries in each chip's ``FITSWCS`` object.  It should be provided as a
        dict of astropy Tables identified by chip number with
        each table containing sources from image extension ``('sci', chip)`` as
        generated by `generate_source_catalog()`.

    Returns
    -------
    wcs_catalogs : list of `~tweakwcs.tpwcs.FITSWCS`
        List of `~tweakwcs.tpwcs.FITSWCS` objects defined for all chips in input image.

    """
    open_file = False
    if isinstance(image, str):
        hdulist = pf.open(image)
        open_file = True
    elif isinstance(image, pf.HDUList):
        hdulist = image
    else:
        log.info("Wrong type of input, {}, for build_wcscat...".format(type(image)))
        raise ValueError

    wcs_catalogs = []
    numsci = countExtn(hdulist)
    for chip in range(1, numsci + 1):
        w = wcsutil.HSTWCS(hdulist, ('SCI', chip))

        imcat = source_catalog[chip]
        # rename xcentroid/ycentroid columns, if necessary, to be consistent with tweakwcs
        if 'xcentroid' in imcat.colnames:
            imcat.rename_column('xcentroid', 'x')
            imcat.rename_column('ycentroid', 'y')

        wcscat = FITSWCS(
            w,
            meta={
                'chip': chip,
                'group_id': group_id,
                'filename': image,
                'catalog': imcat,
                'name': image
            }
        )

        wcs_catalogs.append(wcscat)

    if open_file:
        hdulist.close()

    return wcs_catalogs


Instruction:
Write a Python 3 function that can
update headers of all images specified in shiftfile with shifts from shiftfile.

Response:
def update_from_shiftfile(shiftfile,wcsname=None,force=False):
    """
    Update headers of all images specified in shiftfile with shifts
    from shiftfile.

    Parameters
    ----------
    shiftfile : str
        Filename of shiftfile.

    wcsname : str
        Label to give to new WCS solution being created by this fit. If
        a value of None is given, it will automatically use 'TWEAK' as the
        label. [Default =None]

    force : bool
        Update header even though WCS already exists with this solution or
        wcsname? [Default=False]

    """
    f = open(fileutil.osfn(shiftfile))
    shift_lines = [x.strip() for x in f.readlines()]
    f.close()

    # interpret header of shift file
    for line in shift_lines:
        if 'refimage' in line or 'reference' in line:
            refimage = line.split(':')[-1]
            refimage = refimage[:refimage.find('[wcs]')].lstrip()
            break

    # Determine the max length in the first column (filenames)
    fnames = []
    for row in shift_lines:
        if row[0] == '#': continue
        fnames.append(len(row.split(' ')[0]))
    fname_fmt = 'S{0}'.format(max(fnames))

    # Now read in numerical values from shiftfile
    type_list = {'names':('fnames','xsh','ysh','rot','scale','xrms','yrms'),
                 'formats':(fname_fmt,'f4','f4','f4','f4','f4','f4')}
    try:
        sdict = np.loadtxt(shiftfile,dtype=type_list,unpack=False)
    except IndexError:
        tlist = {'names':('fnames','xsh','ysh','rot','scale'),
                     'formats':(fname_fmt,'f4','f4','f4','f4')}
        s = np.loadtxt(shiftfile,dtype=tlist,unpack=False)
        sdict = np.zeros([s['fnames'].shape[0],],dtype=type_list)
        for sname in s.dtype.names:
            sdict[sname] = s[sname]

    for img in sdict:
        updatewcs_with_shift(img['fnames'], refimage, wcsname=wcsname,
                rot=img['rot'], scale=img['scale'],
                xsh=img['xsh'], ysh=img['ysh'],
                xrms=img['xrms'], yrms=img['yrms'],
                force=force)


Instruction:
Here you have a function in Python 3, explain what it does
def updatewcs_with_shift(image,reference,wcsname=None, reusename=False,
                         fitgeom='rscale',
                         rot=0.0,scale=1.0,xsh=0.0,ysh=0.0,fit=None,
                         xrms=None, yrms = None,
                         verbose=False,force=False,sciext='SCI'):

    """
    Update the SCI headers in 'image' based on the fit provided as determined
    in the WCS specified by 'reference'.  The fit should be a 2-D matrix as
    generated for use with 'make_vector_plot()'.

    Notes
    -----
    The algorithm used to apply the provided fit solution to the image
    involves applying the following steps to the WCS of each of the
    input image's chips:

    1. compute RA/Dec with full distortion correction for
            reference point as (Rc_i,Dc_i)

    2. find the Xc,Yc for each Rc_i,Dc_i and get the difference from the
            CRPIX position for the reference WCS as (dXc_i,dYc_i)

    3. apply fit (rot&scale) to (dXc_i,dYc_i) then apply shift, then add
            CRPIX back to get new (Xcs_i,Ycs_i) position

    4. compute (Rcs_i,Dcs_i) as the sky coordinates for (Xcs_i,Ycs_i)

    5. compute delta of (Rcs_i-Rc_i, Dcs_i-Dcs_i) as (dRcs_i,dDcs_i)

    6. apply the fit to the chip's undistorted CD matrix, the apply linear
            distortion terms back in to create a new CD matrix

    7. add (dRcs_i,dDcs_i) to CRVAL of the reference chip's WCS

    8. update header with new WCS values

    Parameters
    ----------
    image : str or PyFITS.HDUList object
        Filename, or PyFITS object, of image with WCS to be updated.
        All extensions with EXTNAME matches the value of the 'sciext'
        parameter value (by default, all 'SCI' extensions) will be updated.

    reference : str
        Filename of image/headerlet (FITS file) which contains the WCS
        used to define the tangent plane in which all the fit parameters
        (shift, rot, scale) were measured.

    wcsname : str
        Label to give to new WCS solution being created by this fit. If
        a value of None is given, it will automatically use 'TWEAK' as the
        label. If a WCS has a name with this specific value, the code will
        automatically append a version ID using the format '_n', such as
        'TWEAK_1', 'TWEAK_2',or 'TWEAK_update_1'.
        [Default =None]

    reusename : bool
        User can specify whether or not to over-write WCS with same name.
        [Default: False]

    rot : float
        Amount of rotation measured in fit to be applied.
        [Default=0.0]

    scale : float
        Amount of scale change measured in fit to be applied.
        [Default=1.0]

    xsh : float
        Offset in X pixels from defined tangent plane to be applied to image.
        [Default=0.0]

    ysh : float
        Offset in Y pixels from defined tangent plane to be applied to image.
        [Default=0.0]

    fit : arr
        Linear coefficients for fit
        [Default = None]

    xrms : float
        RMS of fit in RA (in decimal degrees) that will be recorded as
        CRDER1 in WCS and header
        [Default = None]

    yrms : float
        RMS of fit in Dec (in decimal degrees) that will be recorded as
        CRDER2 in WCS and header
        [Default = None]

    verbose : bool
        Print extra messages during processing? [Default=False]

    force : bool
        Update header even though WCS already exists with this solution or
        wcsname? [Default=False]

    sciext : string
        Value of FITS EXTNAME keyword for extensions with WCS headers to
        be updated with the fit values. [Default='SCI']

    """
    # if input reference is a ref_wcs file from tweakshifts, use it
    if isinstance(reference, wcsutil.HSTWCS) or isinstance(reference, pywcs.WCS):
        wref = reference
    else:
        refimg = fits.open(reference, memmap=False)
        wref = None
        for extn in refimg:
            if 'extname' in extn.header and extn.header['extname'] == 'WCS':
                wref = pywcs.WCS(refimg['wcs'].header)
                break
        refimg.close()
        # else, we have presumably been provided a full undistorted image
        # as a reference, so use it with HSTWCS instead
        if wref is None:
            wref = wcsutil.HSTWCS(reference)

    if isinstance(image, fits.HDUList):
        open_image = False
        filename = image.filename()
        if image.fileinfo(0)['filemode'] is 'update':
            image_update = True
        else:
            image_update = False
    else:
        open_image = True
        filename = image
        image_update = None

    # Now that we are sure we have a good reference WCS to use,
    # continue with the update
    logstr = "....Updating header for {:s}...".format(filename)
    if verbose:
        print("\n{:s}\n".format(logstr))
    else:
        log.info(logstr)

    # reset header WCS keywords to original (OPUS generated) values
    extlist = get_ext_list(image, extname='SCI')
    if extlist:
        if image_update:
            # Create initial WCSCORR extension
            wcscorr.init_wcscorr(image,force=force)
    else:
        extlist = [0]

    # insure that input PRIMARY WCS has been archived before overwriting
    # with new solution
    if open_image:
        fimg = fits.open(image, mode='update', memmap=False)
        image_update = True
    else:
        fimg = image

    if image_update:
        wcsutil.altwcs.archiveWCS(fimg,extlist,reusekey=True)

    # Process MEF images...
    for ext in extlist:
        logstr = "Processing {:s}[{:s}]".format(fimg.filename(),
                                                ext2str(ext))
        if verbose:
            print("\n{:s}\n".format(logstr))
        else:
            log.info(logstr)
        chip_wcs = wcsutil.HSTWCS(fimg,ext=ext)

        update_refchip_with_shift(chip_wcs, wref, fitgeom=fitgeom,
                    rot=rot, scale=scale, xsh=xsh, ysh=ysh,
                    fit=fit, xrms=xrms, yrms=yrms)
        #if util.is_blank(wcsname):
            #wcsname = 'TWEAK'

        # Update FITS file with newly updated WCS for this chip
        extnum = fimg.index(fimg[ext])
        update_wcs(fimg, extnum, chip_wcs, wcsname=wcsname,
                   reusename=reusename, verbose=verbose)

    if open_image:
        fimg.close()

Response: Update the WCS headers in image with the values of the WCS specified by reference.


Instruction:
Explain what the following Python 3 code does
def update_refchip_with_shift(chip_wcs, wcslin, fitgeom='rscale',
                              rot=0.0, scale=1.0, xsh=0.0, ysh=0.0,
                              fit=None, xrms=None, yrms=None):
    """ Compute the matrix for the scale and rotation correction

    Parameters
    ----------
    chip_wcs: wcs object
        HST of the input image
    wcslin: wcs object
        Reference WCS from which the offsets/rotations are determined
    fitgeom: str
        NOT USED
    rot : float
        Amount of rotation measured in fit to be applied.
        [Default=0.0]
    scale : float
        Amount of scale change measured in fit to be applied.
        [Default=1.0]
    xsh : float
        Offset in X pixels from defined tangent plane to be applied to image.
        [Default=0.0]
    ysh : float
        Offset in Y pixels from defined tangent plane to be applied to image.
        [Default=0.0]
    fit : arr
        Linear coefficients for fit
        [Default = None]
    xrms : float
        RMS of fit in RA (in decimal degrees) that will be recorded as
        CRDER1 in WCS and header
        [Default = None]
    yrms : float
        RMS of fit in Dec (in decimal degrees) that will be recorded as
        CRDER2 in WCS and header
        [Default = None]
        """
    # compute the matrix for the scale and rotation correction
    if fit is None:
        fit = linearfit.buildFitMatrix(rot, scale)

    shift = np.asarray([xsh, ysh]) - np.dot(wcslin.wcs.crpix, fit) + wcslin.wcs.crpix

    fit = np.linalg.inv(fit).T

    cwcs = chip_wcs.deepcopy()
    cd_eye = np.eye(chip_wcs.wcs.cd.shape[0], dtype=ndfloat128)
    zero_shift = np.zeros(2, dtype=ndfloat128)

    naxis1, naxis2 = chip_wcs.pixel_shape

    # estimate precision necessary for iterative processes:
    maxiter = 100
    crpix2corners = np.dstack([i.flatten() for i in np.meshgrid(
        [1, naxis1], [1, naxis2])])[0] - chip_wcs.wcs.crpix
    maxUerr = 1.0e-5 / np.amax(np.linalg.norm(crpix2corners, axis=1))

    # estimate step for numerical differentiation. We need a step
    # large enough to avoid rounding errors and small enough to get a
    # better precision for numerical differentiation.
    # TODO: The logic below should be revised at a later time so that it
    # better takes into account the two competing requirements.
    hx = max(1.0, min(20.0, (chip_wcs.wcs.crpix[0] - 1.0) / 100.0,
                      (naxis1 - chip_wcs.wcs.crpix[0]) / 100.0))
    hy = max(1.0, min(20.0, (chip_wcs.wcs.crpix[1] - 1.0) / 100.0,
                      (naxis2 - chip_wcs.wcs.crpix[1]) / 100.0))

    # compute new CRVAL for the image WCS:
    crpixinref = wcslin.wcs_world2pix(
        chip_wcs.wcs_pix2world([chip_wcs.wcs.crpix],1),1)
    crpixinref = np.dot(fit, (crpixinref - shift).T).T
    chip_wcs.wcs.crval = wcslin.wcs_pix2world(crpixinref, 1)[0]
    chip_wcs.wcs.set()

    # initial approximation for CD matrix of the image WCS:
    (U, u) = linearize(cwcs, chip_wcs, wcslin, chip_wcs.wcs.crpix,
                       fit, shift, hx=hx, hy=hy)
    err0 = np.amax(np.abs(U-cd_eye)).astype(np.float64)
    chip_wcs.wcs.cd = np.dot(chip_wcs.wcs.cd.astype(ndfloat128), U).astype(np.float64)
    chip_wcs.wcs.set()

    # NOTE: initial solution is the exact mathematical solution (modulo numeric
    # differentiation). However, e.g., due to rounding errors, approximate
    # numerical differentiation, the solution may be improved by performing
    # several iterations. The next step will try to perform
    # fixed-point iterations to "improve" the solution
    # but this is not really required.

    # Perform fixed-point iterations to improve the approximation
    # for CD matrix of the image WCS (actually for the U matrix).
    for i in range(maxiter):
        (U, u) = linearize(chip_wcs, chip_wcs, wcslin, chip_wcs.wcs.crpix,
                           cd_eye, zero_shift, hx=hx, hy=hy)
        err = np.amax(np.abs(U-cd_eye)).astype(np.float64)
        if err > err0:
            break
        chip_wcs.wcs.cd = np.dot(chip_wcs.wcs.cd, U).astype(np.float64)
        chip_wcs.wcs.set()
        if err < maxUerr:
            break
        err0 = err

    if xrms is not None:
        chip_wcs.wcs.crder = np.array([xrms,yrms])

Response: Update the refchip with the shift of the input image.


Instruction:
Can you generate the documentation for the following Python 3 function
def update_wcs(image,extnum,new_wcs,wcsname="",reusename=False,verbose=False):
    # Start by insuring that the correct value of 'orientat' has been computed
    new_wcs.setOrient()

    fimg_open=False
    if not isinstance(image, fits.HDUList):
        fimg = fits.open(image, mode='update', memmap=False)
        fimg_open = True
        fimg_update = True
    else:
        fimg = image
        if fimg.fileinfo(0)['filemode'] is 'update':
            fimg_update = True
        else:
            fimg_update = False

    # Determine final (unique) WCSNAME value, either based on the default or
    # user-provided name
    if util.is_blank(wcsname):
        wcsname = 'TWEAK'
    if not reusename:
        wcsname = create_unique_wcsname(fimg, extnum, wcsname)

    idchdr = True
    if new_wcs.idcscale is None:
        idchdr = False
    # Open the file for updating the WCS
    try:
        logstr = 'Updating header for %s[%s]'%(fimg.filename(),str(extnum))
        if verbose:
            print(logstr)
        else:
            log.info(logstr)

        hdr = fimg[extnum].header

        if verbose:
            log.info('    with WCS of')
            new_wcs.printwcs()
            print("WCSNAME  : ",wcsname)

        # Insure that if a copy of the WCS has not been created yet, it will be now
        wcs_hdr = new_wcs.wcs2header(idc2hdr=idchdr, relax=True)

        for key in wcs_hdr:
            hdr[key] = wcs_hdr[key]
        hdr['ORIENTAT'] = new_wcs.orientat
        hdr['WCSNAME'] = wcsname
        util.updateNEXTENDKw(fimg)

        # Only if this image was opened in update mode should this
        # newly updated WCS be archived, as it will never be written out
        # to a file otherwise.
        if fimg_update:
            if not reusename:
                # Save the newly updated WCS as an alternate WCS as well
                wkey = wcsutil.altwcs.next_wcskey(fimg,ext=extnum)
            else:
                wkey = wcsutil.altwcs.getKeyFromName(hdr,wcsname)

            # wcskey needs to be specified so that archiveWCS will create a
            # duplicate WCS with the same WCSNAME as the Primary WCS
            wcsutil.altwcs.archiveWCS(fimg,[extnum],wcsname=wcsname,
                wcskey=wkey, reusekey=reusename)
    finally:
        if fimg_open:
            # finish up by closing the file now
            fimg.close()

Response: Updates the WCS of the specified extension number with the new WCS object.


Instruction:
Implement a Python 3 function for
determining the size of the thread pool for the user - specified cfg value.

Response:
def get_pool_size(usr_config_value, num_tasks):
    """ Determine size of thread/process-pool for parallel processing.
    This examines the cpu_count to decide and return the right pool
    size to use.  Also take into account the user's wishes via the config
    object value, if specified.  On top of that, don't allow the pool size
    returned to be any higher than the number of parallel tasks, if specified.
    Only use what we need (mp.Pool starts pool_size processes, needed or not).
    If number of tasks is unknown, call this with "num_tasks" set to None.
    Returns 1 when indicating that parallel processing should not be used.
    Consolidate all such logic here, not in the caller. """

    if not can_parallel:
        return 1
    # Give priority to their specified cfg value, over the actual cpu count
    if usr_config_value is not None:
        if num_tasks is None:
            return usr_config_value
        else:
            # usr_config_value may be needlessly high
            return min(usr_config_value, num_tasks)
    # they haven't specified a cfg value, so go with the cpu_count
    if num_tasks is None:
        return _cpu_count
    else:
        # run no more workers than tasks
        return min(_cpu_count, num_tasks)


Instruction:
How would you explain what the following Python 3 function does
def init_logging(logfile=DEFAULT_LOGNAME, default=None, level=logging.INFO):

    if logfile == "INDEF":
        if not is_blank(default):
            logname = fileutil.buildNewRootname(default, '.log')
        else:
            logname = DEFAULT_LOGNAME
    elif logfile not in [None, "" , " "]:
        if logfile.endswith('.log'):
            logname = logfile
        else:
            logname = logfile + '.log'
    else:
        logname = None

    if logname is not None:
        logutil.setup_global_logging()
        # Don't use logging.basicConfig since it can only be called once in a
        # session
        # TODO: Would be fine to use logging.config.dictConfig, but it's not
        # available in Python 2.5
        global _log_file_handler
        root_logger = logging.getLogger()
        if _log_file_handler:
            root_logger.removeHandler(_log_file_handler)
        # Default mode is 'a' which is fine
        _log_file_handler = logging.FileHandler(logname)
        # TODO: Make the default level configurable in the task parameters
        _log_file_handler.setLevel(level)
        _log_file_handler.setFormatter(
            logging.Formatter('[%(levelname)-8s] %(message)s'))
        root_logger.setLevel(level)
        root_logger.addHandler(_log_file_handler)

        print('Setting up logfile : ', logname)

        #stdout_logger = logging.getLogger('stsci.tools.logutil.stdout')
        # Disable display of prints to stdout from all packages except
        # drizzlepac
        #stdout_logger.addFilter(logutil.EchoFilter(include=['drizzlepac']))
    else:
        print('No trailer file created...')

Response: Initialize logging for the current thread.


Instruction:
How would you explain what the following Python 3 function does
def end_logging(filename=None):

    if logutil.global_logging_started:
        if filename:
            print('Trailer file written to: ', filename)
        else:
            # This generally shouldn't happen if logging was started with
            # init_logging and a filename was given...
            print('No trailer file saved...')

        logutil.teardown_global_logging()
    else:
        print('No trailer file saved...')

Response: Ends logging and restores system defaults.


Instruction:
Create a Python 3 function to
find the rootname of the given file.

Response:
def findrootname(filename):
    """
    Return the rootname of the given file.
    """

    puncloc = [filename.find(char) for char in string.punctuation]
    if sys.version_info[0] >= 3:
        val = sys.maxsize
    else:
        val = sys.maxint
    for num in puncloc:
        if num !=-1 and num < val:
            val = num
    return filename[0:val]


Instruction:
Here you have a function in Python 3, explain what it does
def removeFileSafely(filename,clobber=True):
    if filename is not None and filename.strip() != '':
        if os.path.exists(filename) and clobber: os.remove(filename)

Response: Delete the file specified but only if it exists and clobber is True.


Instruction:
Create a Python 3 function for
displaying a warning box for the input parameter.

Response:
def displayEmptyInputWarningBox(display=True, parent=None):
    """ Displays a warning box for the 'input' parameter.
    """
    if sys.version_info[0] >= 3:
        from tkinter.messagebox import showwarning
    else:
        from tkMessageBox import showwarning

    if display:
        msg = 'No valid input files found! '+\
        'Please check the value for the "input" parameter.'
        showwarning(parent=parent,message=msg, title="No valid inputs!")
    return "yes"


Instruction:
Can you create a Python 3 function that
returns the number of SCI extensions and the EXTNAME from a input MEF file.

Response:
def count_sci_extensions(filename):
    """ Return the number of SCI extensions and the EXTNAME from a input MEF file.
    """
    num_sci = 0
    extname = 'SCI'

    hdu_list = fileutil.openImage(filename, memmap=False)

    for extn in hdu_list:
        if 'extname' in extn.header and extn.header['extname'] == extname:
            num_sci += 1

    if num_sci == 0:
        extname = 'PRIMARY'
        num_sci = 1

    hdu_list.close()

    return num_sci,extname


Instruction:
Implement a function in Python 3 to
check whether or not the specified WCSNAME already exists in the file fname.

Response:
def verifyUniqueWcsname(fname,wcsname):
    """
    Report whether or not the specified WCSNAME already exists in the file
    """
    uniq = True
    numsci,extname = count_sci_extensions(fname)
    wnames = altwcs.wcsnames(fname,ext=(extname,1))

    if wcsname in wnames.values():
        uniq = False

    return uniq


Instruction:
How would you code a function in Python 3 to
verify that WCSNAME is present in the file and if it is not present in all SCI extensions and return True if it is present.

Response:
def verifyUpdatewcs(fname):
    """
    Verify the existence of WCSNAME in the file.  If it is not present,
    report this to the user and raise an exception.  Returns True if WCSNAME
    was found in all SCI extensions.
    """
    updated = True
    numsci,extname = count_sci_extensions(fname)
    for n in range(1,numsci+1):
        hdr = fits.getheader(fname, extname=extname, extver=n, memmap=False)
        if 'wcsname' not in hdr:
            updated = False
            break
    return updated


Instruction:
How would you explain what the following Python 3 function does
def verifyRefimage(refimage):
    valid = True

    # start by trying to see whether the code can even find the file
    if is_blank(refimage):
        valid=True
        return valid

    refroot,extroot = fileutil.parseFilename(refimage)
    if not os.path.exists(refroot):
        valid = False
        return valid

    # if a MEF has been specified, make sure extension contains a valid WCS
    if valid:
        if extroot is None:
            extn = findWCSExtn(refimage)
            if extn is None:
                valid = False
            else:
                valid = True
        else:
            # check for CD matrix in WCS object
            refwcs = wcsutil.HSTWCS(refimage)
            if not refwcs.wcs.has_cd():
                valid = False
            else:
                valid = True
            del refwcs

    return valid

Response: Verify that the value of refimage is a valid WCS object.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def findWCSExtn(filename):
    rootname,extroot = fileutil.parseFilename(filename)
    extnum = None
    if extroot is None:
        fimg = fits.open(rootname, memmap=False)
        for i,extn in enumerate(fimg):
            if 'crval1' in extn.header:
                refwcs = wcsutil.HSTWCS('{}[{}]'.format(rootname,i))
                if refwcs.wcs.has_cd():
                    extnum = '{}'.format(i)
                    break
        fimg.close()
    else:
        try:
            refwcs = wcsutil.HSTWCS(filename)
            if refwcs.wcs.has_cd():
                extnum = extroot
        except:
            extnum = None

    return extnum

Response: Find the first valid WCS object in a file with the same name as the user - supplied filename.


Instruction:
Write a Python 3 function that can
verify that images specified in filelist can be updated.

Response:
def verifyFilePermissions(filelist, chmod=True):
    """ Verify that images specified in 'filelist' can be updated.

    A message will be printed reporting the names of any images which
    do not have write-permission, then quit.
    """
    badfiles = []
    archive_dir = False
    for img in filelist:
        fname = fileutil.osfn(img)
        if 'OrIg_files' in os.path.split(fname)[0]:
            archive_dir = True
        try:
            fp = open(fname,mode='a')
            fp.close()
        except IOError as e:
            if e.errno == errno.EACCES:
                badfiles.append(img)
            # Not a permission error.
            pass

    num_bad = len(badfiles)
    if num_bad > 0:
        if archive_dir:
            print('\n')
            print('#'*40)
            print('    Working in "OrIg_files" (archive) directory. ')
            print('    This directory has been created to serve as an archive')
            print('    for the original input images. ')
            print('\n    These files should be copied into another directory')
            print('     for processing. ')
            print('#'*40)

        print('\n')
        print('#'*40)
        print('Found %d files which can not be updated!'%(num_bad))
        for img in badfiles:
            print('    %s'%(img))
        print('\nPlease reset permissions for these files and restart...')
        print('#'*40)
        print('\n')
        filelist = None

    return filelist


Instruction:
How would you code a function in Python 3 to
return a list of all parameter names included in the configObj regardless of which section the parameter was stored in the configObj.

Response:
def getFullParList(configObj):
    """
    Return a single list of all parameter names included in the configObj
    regardless of which section the parameter was stored
    """
    plist = []
    for par in configObj.keys():
        if isinstance(configObj[par],configobj.Section):
            plist.extend(getFullParList(configObj[par]))
        else:
            plist.append(par)
    return plist


Instruction:
Can you create a Python 3 function that
validates the input parameters of the user.

Response:
def validateUserPars(configObj,input_dict):
    """ Compares input parameter names specified by user with those already
        recognized by the task.

        Any parameters provided by the user that does not match a known
        task parameter will be reported and a ValueError exception will be
        raised.
    """
    # check to see whether any input parameters are unexpected.
    # Any unexpected parameters provided on input should be reported and
    # the code should stop
    plist = getFullParList(configObj)
    extra_pars = []
    for kw in input_dict:
        if kw not in plist:
            extra_pars.append(kw)
    if len(extra_pars) > 0:
        print ('='*40)
        print ('The following input parameters were not recognized as valid inputs:')
        for p in extra_pars:
            print("    %s"%(p))
        print('\nPlease check the spelling of the parameter(s) and try again...')
        print('='*40)
        raise ValueError


Instruction:
How would you implement a function in Python 3 that
applies logic to turn on use of user - specified output WCS if user provides any parameter on command - line regardless of how final_wcs was set.

Response:
def applyUserPars_steps(configObj, input_dict, step='3a'):
    """ Apply logic to turn on use of user-specified output WCS if user provides
        any parameter on command-line regardless of how final_wcs was set.
    """
    step_kws = {'7a': 'final_wcs', '3a': 'driz_sep_wcs'}
    stepname = getSectionName(configObj,step)
    finalParDict = configObj[stepname].copy()
    del finalParDict[step_kws[step]]

    # interpret input_dict to find any parameters for this step specified by the user
    user_pars = {}
    for kw in finalParDict:
        if kw in input_dict: user_pars[kw] = input_dict[kw]
    if len(user_pars) > 0:
        configObj[stepname][step_kws[step]] = True


Instruction:
Can you generate a brief explanation for the following Python 3 code
def getDefaultConfigObj(taskname,configObj,input_dict={},loadOnly=True):
    if configObj is None:
        # Start by grabbing the default values without using the GUI
        # This insures that all subsequent use of the configObj includes
        # all parameters and their last saved values
        configObj = teal.load(taskname)
    elif isinstance(configObj,str):
        if configObj.lower().strip() == 'defaults':
            # Load task default .cfg file with all default values
            configObj = teal.load(taskname,defaults=True)
            # define default filename for configObj
            configObj.filename = taskname.lower()+'.cfg'
        else:
            # Load user-specified .cfg file with its special default values
            # we need to call 'fileutil.osfn()' to insure all environment
            # variables specified by the user in the configObj filename are
            # expanded to the full path
            configObj = teal.load(fileutil.osfn(configObj))

    # merge in the user values for this run
    # this, though, does not save the results for use later
    if input_dict not in [None,{}]:# and configObj not in [None, {}]:
        # check to see whether any input parameters are unexpected.
        # Any unexpected parameters provided on input should be reported and
        # the code should stop
        validateUserPars(configObj,input_dict)

        # If everything looks good, merge user inputs with configObj and continue
        cfgpars.mergeConfigObj(configObj, input_dict)
        # Update the input .cfg file with the updated parameter values
        #configObj.filename = os.path.join(cfgpars.getAppDir(),os.path.basename(configObj.filename))
        #configObj.write()

    if not loadOnly:
    # We want to run the GUI AFTER merging in any parameters
    # specified by the user on the command-line and provided in
    # input_dict
        configObj = teal.teal(configObj,loadOnly=False)

    return configObj

Response: Returns a configObj instance for the given task and the given configObj.


Instruction:
Write a Python 3 function that can
return section name based on step number.

Response:
def getSectionName(configObj,stepnum):
    """ Return section label based on step number.
    """
    for key in configObj.keys():
        if key.find('STEP '+str(stepnum)+':') >= 0:
            return key


Instruction:
Can you generate a brief explanation for the following Python 3 code
def displayMakewcsWarningBox(display=True, parent=None):
    if sys.version_info[0] >= 3:
        from tkinter.messagebox import showwarning
    else:
        from tkMessageBox import showwarning

    ans = {'yes':True,'no':False}
    if ans[display]:
        msg = 'Setting "updatewcs=yes" will result '+ \
              'in all input WCS values to be recomputed '+ \
              'using the original distortion model and alignment.'
        showwarning(parent=parent,message=msg, title="WCS will be overwritten!")
    return True

Response: Displays a warning box for the makewcs parameter.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def printParams(paramDictionary, all=False, log=None):

    if log is not None:
        def output(msg):
            log.info(msg)
    else:
        def output(msg):
            print(msg)

    if not paramDictionary:
        output('No parameters were supplied')
    else:
        for key in sorted(paramDictionary):
            if all or (not isinstance(paramDictionary[key], dict)) \
            and key[0] != '_':
                output('\t' + '\t'.join([str(key) + ' :',
                                         str(paramDictionary[key])]))
        if log is None:
            output('\n')

Response: Print nicely the parameters from the dictionary.


Instruction:
Write a Python 3 script for
returning True if the input is a comma separated list of names.

Response:
def isCommaList(inputFilelist):
    """Return True if the input is a comma separated list of names."""
    if isinstance(inputFilelist, int) or isinstance(inputFilelist, np.int32):
        ilist = str(inputFilelist)
    else:
        ilist = inputFilelist
    if "," in ilist:
        return True
    return False


Instruction:
Can you generate a brief explanation for the following Python 3 code
def loadFileList(inputFilelist):
    f = open(inputFilelist[1:])
    # check the first line in order to determine whether
    # IVM files have been specified in a second column...
    lines = f.readline()
    f.close()

    # If there is a second column...
    if len(line.split()) == 2:
        # ...parse out the names of the IVM files as well
        ivmlist = irafglob.irafglob(input, atfile=atfile_ivm)

    # Parse the @-file with irafglob to extract the input filename
    filelist = irafglob.irafglob(input, atfile=atfile_sci)
    return filelist

Response: Load the IVM files from the first two columns and return the list of IVM files.


Instruction:
Given the following Python 3 function, write the documentation
def readCommaList(fileList):
    names=fileList.split(',')
    fileList=[]
    for item in names:
        fileList.append(item)
    return fileList

Response: Return a list of the files with the commas removed.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def update_input(filelist, ivmlist=None, removed_files=None):
    newfilelist = []

    if removed_files == []:
        return filelist, ivmlist
    else:
        sci_ivm = list(zip(filelist, ivmlist))
        for f in removed_files:
            result=[sci_ivm.remove(t) for t in sci_ivm if t[0] == f ]
        ivmlist = [el[1] for el in sci_ivm]
        newfilelist = [el[0] for el in sci_ivm]
        return newfilelist, ivmlist

Response: Updates the input list with the files removed from the input list.


Instruction:
Implement a Python 3 function for
getting the expstart and exppend from the header

Response:
def get_expstart(header,primary_hdr):
    """shouldn't this just be defined in the instrument subclass of imageobject?"""

    if 'expstart' in primary_hdr:
        exphdr = primary_hdr
    else:
        exphdr = header

    if 'EXPSTART' in exphdr:
        expstart = float(exphdr['EXPSTART'])
        expend = float(exphdr['EXPEND'])
    else:
        expstart = 0.
        expend = 0.0

    return (expstart,expend)


Instruction:
Here you have a function in Python 3, explain what it does
def compute_texptime(imageObjectList):
    expnames = []
    exptimes = []
    start = []
    end = []
    for img in imageObjectList:
        expnames += img.getKeywordList('_expname')
        exptimes += img.getKeywordList('_exptime')
        start += img.getKeywordList('_expstart')
        end += img.getKeywordList('_expend')

    exptime = 0.
    expstart = min(start)
    expend = max(end)
    exposure = None
    for n in range(len(expnames)):
        if expnames[n] != exposure:
            exposure = expnames[n]
            exptime += exptimes[n]

    return (exptime,expstart,expend)

Response: Compute the exposure time for all the members in the specified imageObjectList.


Instruction:
Can you generate the documentation for the following Python 3 function
def computeRange(corners):
    x = corners[:, 0]
    y = corners[:, 1]
    _xrange = (np.minimum.reduce(x), np.maximum.reduce(x))
    _yrange = (np.minimum.reduce(y), np.maximum.reduce(y))
    return _xrange, _yrange

Response: Compute the range spanned by an array of pixel positions.


Instruction:
Explain what the following Python 3 code does
def getRotatedSize(corners, angle):
    if angle:
        _rotm = fileutil.buildRotMatrix(angle)
        # Rotate about the center
        _corners = np.dot(corners, _rotm)
    else:
        # If there is no rotation, simply return original values
        _corners = corners

    return computeRange(_corners)

Response: Determine the size of a rotated meta image.


Instruction:
Here you have a function in Python 3, explain what it does
def readcols(infile, cols=[0, 1, 2, 3], hms=False):

    fin = open(infile,'r')
    outarr = []
    for l in fin.readlines():
        l = l.strip()
        if len(l) == 0 or len(l.split()) < len(cols) or (len(l) > 0 and l[0] == '#' or (l.find("INDEF") > -1)): continue
        for i in range(10):
            lnew = l.replace("  "," ")
            if lnew == l: break
            else: l = lnew
        lspl = lnew.split(" ")

        if len(outarr) == 0:
            for c in range(len(cols)): outarr.append([])

        for c,n in zip(cols,list(range(len(cols)))):
            if not hms:
                val = float(lspl[c])
            else:
                val = lspl[c]
            outarr[n].append(val)
    fin.close()
    for n in range(len(cols)):
        outarr[n] = np.array(outarr[n])
    return outarr

Response: Read the columns from an ASCII file as numpy arrays.


Instruction:
Here you have a function in Python 3, explain what it does
def parse_colnames(colnames,coords=None):
    cols = []
    if not isinstance(colnames,list):
        colnames = colnames.split(',')
    # parse column names from coords file and match to input values
    if coords is not None and fileutil.isFits(coords)[0]:
        # Open FITS file with table
        ftab = fits.open(coords, memmap=False)
        # determine which extension has the table
        for extn in ftab:
            if isinstance(extn, fits.BinTableHDU):
                # parse column names from table and match to inputs
                cnames = extn.columns.names
                if colnames is not None:
                    for c in colnames:
                        for name,i in zip(cnames,list(range(len(cnames)))):
                            if c == name.lower(): cols.append(i)
                    if len(cols) < len(colnames):
                        errmsg = "Not all input columns found in table..."
                        ftab.close()
                        raise ValueError(errmsg)
                else:
                    cols = cnames[:2]
                break
        ftab.close()
    else:
        for c in colnames:
            if isinstance(c, str):
                if c[0].lower() == 'c': cols.append(int(c[1:])-1)
                else:
                    cols.append(int(c))
            else:
                if isinstance(c, int):
                    cols.append(c)
                else:
                    errmsg = "Unsupported column names..."
                    raise ValueError(errmsg)
    return cols

Response: Convert colnames input into list of column numbers.


Instruction:
Given the following Python 3 function, write the documentation
def createFile(dataArray=None, outfile=None, header=None):
    # Insure that at least a data-array has been provided to create the file
    assert(dataArray is not None), "Please supply a data array for createFiles"

    try:
        # Create the output file
        fitsobj = fits.HDUList()
        if header is not None:
            try:
                del(header['NAXIS1'])
                del(header['NAXIS2'])
                if 'XTENSION' in header:
                    del(header['XTENSION'])
                if 'EXTNAME' in header:
                    del(header['EXTNAME'])
                if 'EXTVER' in header:
                    del(header['EXTVER'])
            except KeyError:
                pass

            if 'NEXTEND' in header:
                header['NEXTEND'] = 0

            hdu = fits.PrimaryHDU(data=dataArray, header=header)
            try:
                del hdu.header['PCOUNT']
                del hdu.header['GCOUNT']
            except KeyError:
                pass

        else:
            hdu = fits.PrimaryHDU(data=dataArray)

        fitsobj.append(hdu)
        if outfile is not None:
            fitsobj.writeto(outfile)
    finally:
        # CLOSE THE IMAGE FILES
        fitsobj.close()

        if outfile is not None:
            del fitsobj
            fitsobj = None
    return fitsobj

Response: Create a FITS file for the given data array and header.


Instruction:
Given the following Python 3 function, write the documentation
def base_taskname(taskname, packagename=None):
    if not isinstance(taskname, str):
        return taskname

    indx = taskname.rfind('.')

    if indx >= 0:
        base_taskname = taskname[(indx+1):]
        pkg_name      = taskname[:indx]
    else:
        base_taskname = taskname
        pkg_name      = ''

    assert(True if packagename is None else (packagename == pkg_name))

    return base_taskname

Response: Returns the base name of the task.


Instruction:
Make a summary of the following Python 3 code
def addStep(self,key):
        ptime = _ptime()
        print('==== Processing Step ',key,' started at ',ptime[0])
        self.steps[key] = {'start':ptime}
        self.order.append(key)

Response: Add information about a new step to the dict of steps that are available for this log entry


Instruction:
Create a Python 3 function for
recording the end time for the step. If key==None, simply record ptime as end time for class to represent the overall runtime since the initialization of the class.

Response:
def endStep(self,key):
        """
        Record the end time for the step.

        If key==None, simply record ptime as end time for class to represent
        the overall runtime since the initialization of the class.
        """
        ptime = _ptime()
        if key is not None:
            self.steps[key]['end'] = ptime
            self.steps[key]['elapsed'] = ptime[1] - self.steps[key]['start'][1]
        self.end = ptime

        print('==== Processing Step ',key,' finished at ',ptime[0])
        print('')


Instruction:
Explain what the following Python 3 code does
def reportTimes(self):

        self.end = _ptime()
        total_time = 0
        print(ProcSteps.__report_header)
        for step in self.order:
            if 'elapsed' in self.steps[step]:
                _time = self.steps[step]['elapsed']
            else:
                _time = 0.0
            total_time += _time
            print('   %20s          %0.4f sec.' % (step, _time))

        print('   %20s          %s' % ('=' * 20, '=' * 20))
        print('   %20s          %0.4f sec.' % ('Total', total_time))

Response:
Print out a formatted summary of the elapsed times for all the the
        performed steps.


Instruction:
Make a summary of the following Python 3 code
def run(configObj=None, input_dict={}, loadOnly=False):
    # If called from interactive user-interface, configObj will not be
    # defined yet, so get defaults using EPAR/TEAL.
    #
    # Also insure that the input_dict (user-specified values) are folded in
    # with a fully populated configObj instance.
    configObj = util.getDefaultConfigObj(__taskname__,configObj,input_dict,loadOnly=loadOnly)
    if configObj is None:
        return
    # Define list of imageObject instances and output WCSObject instance
    # based on input paramters
    imgObjList,outwcs = processInput.setCommonInput(configObj)

    # Build DQ masks for all input images.
    buildMask(imgObjList,configObj)

Response: Build DQ masks from all input images then apply static mask ( s.


Instruction:
Given the following Python 3 function, write the documentation
def buildDQMasks(imageObjectList,configObj):
    # Insure that input imageObject is a list
    if not isinstance(imageObjectList, list):
        imageObjectList = [imageObjectList]

    for img in imageObjectList:
        img.buildMask(configObj['single'], configObj['bits'])

Response: Builds DQ masks for all input images.


Instruction:
Can you tell what is the following Python 3 function doing
def buildMask(dqarr, bitvalue):
    return bitfield_to_boolean_mask(dqarr, bitvalue, good_mask_value=1,
                                    dtype=np.uint8)

Response: Builds a bit - mask from an input DQ array and a bitvalue flag


Instruction:
Can you implement a function in Python 3 that
builds a mask image from a rootname s DQ array and returns the name of the mask image.

Response:
def buildMaskImage(rootname, bitvalue, output, extname='DQ', extver=1):
    """ Builds mask image from rootname's DQ array
        If there is no valid 'DQ' array in image, then return
        an empty string.
    """

    # If no bitvalue is set or rootname given, assume no mask is desired
    # However, this name would be useful as the output mask from
    # other processing, such as MultiDrizzle, so return it anyway.
    #if bitvalue == None or rootname == None:
    #    return None

    # build output name
    maskname = output

    # If an old version of the maskfile was present, remove it and rebuild it.
    if fileutil.findFile(maskname):
        fileutil.removeFile(maskname)

    # Open input file with DQ array
    fdq = fileutil.openImage(rootname, mode='readonly', memmap=False)
    try:
        _extn = fileutil.findExtname(fdq, extname, extver=extver)
        if _extn is not None:
            # Read in DQ array
            dqarr = fdq[_extn].data
        else:
            dqarr = None

        # For the case where there is no DQ array,
        # create a mask image of all ones.
        if dqarr is None:
            # We need to get the dimensions of the output DQ array
            # Since the DQ array is non-existent, look for the SCI extension
            _sci_extn = fileutil.findExtname(fdq,'SCI',extver=extver)
            if _sci_extn is not None:
                _shape = fdq[_sci_extn].data.shape
                dqarr = np.zeros(_shape,dtype=np.uint16)
            else:
                raise Exception
        # Build mask array from DQ array
        maskarr = buildMask(dqarr,bitvalue)
        #Write out the mask file as simple FITS file
        fmask = fits.open(maskname, mode='append', memmap=False)
        maskhdu = fits.PrimaryHDU(data = maskarr)
        fmask.append(maskhdu)

        #Close files
        fmask.close()
        del fmask
        fdq.close()
        del fdq

    except:
        fdq.close()
        del fdq
        # Safeguard against leaving behind an incomplete file
        if fileutil.findFile(maskname):
            os.remove(maskname)
        _errstr = "\nWarning: Problem creating MASK file for "+rootname+".\n"
        #raise IOError, _errstr
        print(_errstr)
        return None

    # Return the name of the mask image written out
    return maskname


Instruction:
Given the following Python 3 function, write the documentation
def buildShadowMaskImage(dqfile,detnum,extnum,maskname,bitvalue=None,binned=1):
    # insure detnum is a string
    if type(detnum) != type(''):
        detnum = repr(detnum)

    _funcroot = '_func_Shadow_WF'

    # build template shadow mask's filename

    # If an old version of the maskfile was present, remove it and rebuild it.
    if fileutil.findFile(maskname):
        fileutil.removeFile(maskname)

    _use_inmask = not fileutil.findFile(dqfile) or bitvalue is None

    # Check for existance of input .c1h file for use in making inmask file
    if _use_inmask:
        #_mask = 'wfpc2_inmask'+detnum+'.fits'
        _mask = maskname
        # Check to see if file exists...
        if not fileutil.findFile(_mask):
        # If not, create the file.
        # This takes a long time to run, so it should be done
        # only when absolutely necessary...
            try:
                _funcx = _funcroot+detnum+'x'
                _funcy = _funcroot+detnum+'y'

                _xarr = np.clip(np.fromfunction(eval(_funcx),(800,800)),0.0,1.0).astype(np.uint8)
                _yarr = np.clip(np.fromfunction(eval(_funcy),(800,800)),0.0,1.0).astype(np.uint8)
                maskarr = _xarr * _yarr

                if binned !=1:
                    bmaskarr = maskarr[::2,::2]
                    bmaskarr *= maskarr[1::2,::2]
                    bmaskarr *= maskarr[::2,1::2]
                    bmaskarr *= maskarr[1::2,1::2]
                    maskarr = bmaskarr.copy()
                    del bmaskarr

                #Write out the mask file as simple FITS file
                fmask = fits.open(_mask, mode='append', memmap=False)
                maskhdu = fits.PrimaryHDU(data=maskarr)
                fmask.append(maskhdu)

                #Close files
                fmask.close()
                del fmask
            except:
                return None

    else:
        #
        # Build full mask based on .c1h and shadow mask
        #
        fdq = fileutil.openImage(dqfile, mode='readonly', memmap=False)
        try:
            # Read in DQ array from .c1h and from shadow mask files
            dqarr = fdq[int(extnum)].data
            #maskarr = fsmask[0].data

            # Build mask array from DQ array
            dqmaskarr = buildMask(dqarr,bitvalue)

            #Write out the mask file as simple FITS file
            fdqmask = fits.open(maskname, mode='append', memmap=False)
            maskhdu = fits.PrimaryHDU(data=dqmaskarr)
            fdqmask.append(maskhdu)

            #Close files
            fdqmask.close()
            del fdqmask
            fdq.close()
            del fdq

        except:
            fdq.close()
            del fdq
            # Safeguard against leaving behind an incomplete file
            if fileutil.findFile(maskname):
                os.remove(maskname)
            _errstr = "\nWarning: Problem creating DQMASK file for "+rootname+".\n"
            #raise IOError, _errstr
            print(_errstr)
            return None

    # Return the name of the mask image written out
    return maskname

Response: Builds a mask image from a detector and a mask file.