<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def build(outname, wcsname, refimage, undistort=False, applycoeffs=False, coeffsfile=None, **wcspars):
 """ Core functionality to create a WCS instance from a reference image WCS, user supplied parameters or user adjusted reference WCS. The distortion information can either be read in as part of the reference image WCS or given in 'coeffsfile'. Parameters outname : string filename of output WCS wcsname : string WCSNAME ID for generated WCS refimage : string filename of image with source WCS used as basis for output WCS undistort : bool Create an undistorted WCS? applycoeffs : bool Apply coefficients from refimage to generate undistorted WCS? coeffsfile : string If specified, read distortion coeffs from separate file """


    # Insure that the User WCS parameters have values for all the parameters,
    # even if that value is 'None'
    user_wcs_pars = convert_user_pars(wcspars)
    userwcs = wcspars['userwcs']

    """
    Use cases to document the logic required to interpret the parameters

    WCS generation based on refimage/userwcs parameters
    -------------------------------------------------------------
    refimage == None, userwcs == False:
        *NO WCS specified*
        => print a WARNING message and return without doing anything
    refimage == None, userwcs == True:
        => Create WCS without a distortion model entirely from user parameters*
    refimage != None, userwcs == False:
        => No user WCS parameters specified
        => Simply use refimage WCS as specified
    refimage != None, userwcs == True:
        => Update refimage WCS with user specified values*

    Apply distortion and generate final headerlet using processed WCS
    -----------------------------------------------------------------
    refimage == None, userwcs == True:
        *Output WCS generated entirely from user supplied parameters*
        Case 1: applycoeffs == False, undistort == True/False (ignored)
            => no distortion model to interpret
            => generate undistorted headerlet with no distortion model
        Case 2: applycoeffs == True/False, undistort == True
            => ignore any user specified distortion model
            => generate undistorted headerlet with no distortion model
        Case 3: applycoeffs == True, undistort == False
            => WCS from scratch combined with distortion model from another image
            => generate headerlet with distortion model

    refimage != None, userwcs == True/False:
        *Output WCS generated from reference image possibly modified by user parameters*
        Case 4: applycoeffs == False, undistort == True
            => If refimage has distortion, remove it
            => generate undistorted headerlet with no distortion model
        Case 5: applycoeffs == False, undistort == False
            => Leave refimage distortion model (if any) unmodified
            => generate a headerlet using same distortion model (if any) as refimage
        Case 6: applycoeffs == True, undistort == False
            => Update refimage with distortion model with user-specified model
            => generate a headerlet with a distortion model
        Case 7: applycoeffs == True, undistort == True
            => ignore user specified distortion model and undistort WCS
            => generate a headerlet without a distortion model
    """
    ### Build WCS from refimage and/or user pars
    if util.is_blank(refimage) and not userwcs:
        print('WARNING: No WCS specified... No WCS created!')
        return
    customwcs = None
    if util.is_blank(refimage) and userwcs:
        # create HSTWCS object from user parameters
        complete_wcs = True
        for key in user_wcs_pars:
            if util.is_blank(user_wcs_pars[key]):
                complete_wcs = False
                break
        if complete_wcs:
            customwcs = wcs_functions.build_hstwcs(user_wcs_pars['crval1'],user_wcs_pars['crval2'],
                user_wcs_pars['crpix1'],user_wcs_pars['crpix2'],
                user_wcs_pars['naxis1'],user_wcs_pars['naxis2'],
                user_wcs_pars['pscale'],user_wcs_pars['orientat'])
        else:
            print('WARNING: Not enough WCS information provided by user!')
            raise ValueError

    if not util.is_blank(refimage):
        refwcs = stwcs.wcsutil.HSTWCS(refimage)
    else:
        refwcs = customwcs

    ### Apply distortion model (if any) to update WCS
    if applycoeffs and not util.is_blank(coeffsfile):
        if not util.is_blank(refimage):
            replace_model(refwcs, coeffsfile)
        else:
            if not undistort:
                add_model(refwcs,coeffsfile)
                # Only working with custom WCS from user, no distortion
                # so apply model to WCS, including modifying the CD matrix
                apply_model(refwcs)

    ### Create undistorted WCS, if requested
    if undistort:
        outwcs = undistortWCS(refwcs)
    else:
        outwcs = refwcs

    if userwcs:
        # replace (some/all?) WCS values from refimage with user WCS values
        # by running 'updatewcs' functions on input WCS
        outwcs = mergewcs(outwcs,customwcs,user_wcs_pars)


    ### Create the final headerlet and write it out, if specified
    if not util.is_blank(refimage):
        template = refimage
    elif not util.is_blank(coeffsfile):
        template = coeffsfile
    else:
        template = None


    # create default WCSNAME if None was given
    wcsname = create_WCSname(wcsname)
    print('Creating final headerlet with name ',wcsname,' using template ',template)
    outhdr = generate_headerlet(outwcs,template,wcsname,outname=outname)

    # synchronize this new WCS with the rest of the chips in the image
    for ext in outhdr:
        if 'extname' in ext.header and ext.header['extname'] == 'SIPWCS':
            ext_wcs = wcsutil.HSTWCS(ext)
            stwcs.updatewcs.makewcs.MakeWCS.updateWCS(ext_wcs,outwcs)

    return outwcs