def performFit(self,**kwargs):
        """ Perform a fit between the matched sources.

            Parameters
            ----------
            kwargs : dict
                Parameter necessary to perform the fit; namely, *fitgeometry*.

            Notes
            -----
            This task still needs to implement (eventually) interactive iteration of
                   the fit to remove outliers.
        """
        assert(self.refWCS is not None)
        pars = kwargs.copy()
        self.fit_pars = pars

        self.fit = {'offset':[0.0,0.0],'rot':0.0,'scale':[1.0],'rms':[0.0,0.0],
                    'rms_keys':{'RMS_RA':0.0,'RMS_DEC':0.0,'NMATCH':0},
                    'fit_matrix':[[1.0,0.0],[0.0,1.0]], 'src_origin':[None]}

        if not self.identityfit:
            if self.matches is not None and self.goodmatch:
                self.fit = linearfit.iter_fit_all(
                    self.matches['image'],self.matches['ref'],
                    self.matches['img_idx'],self.matches['ref_idx'],
                    xyorig=self.matches['img_orig_xy'],
                    uvorig=self.matches['ref_orig_xy'],
                    mode=pars['fitgeometry'],nclip=pars['nclip'],
                    sigma=pars['sigma'],minobj=pars['minobj'],
                    center=self.refWCS.wcs.crpix,
                    verbose=self.verbose)

                self.fit['rms_keys'] = self.compute_fit_rms()
                radec_fit = self.refWCS.all_pix2world(self.fit['fit_xy'],1)
                self.fit['fit_RA'] = radec_fit[:,0]
                self.fit['fit_DEC'] = radec_fit[:,1]
                self.fit['src_origin'] = self.matches['src_origin']

                print('Computed ',pars['fitgeometry'],' fit for ',self.name,': ')
                if pars['fitgeometry'] == 'shift':
                    print("XSH: {:.4f}  YSH: {:.4f}"
                          .format(self.fit['offset'][0],
                                  self.fit['offset'][1]))
                elif pars['fitgeometry'] == 'rscale' and self.fit['proper']:
                    print("XSH: {:.4f}  YSH: {:.4f}    ROT: {:.10g}    "
                          "SCALE: {:.6f}".format(
                              self.fit['offset'][0],
                              self.fit['offset'][1],
                              self.fit['rot'],
                              self.fit['scale'][0]))
                elif pars['fitgeometry'] == 'general' or \
                     (pars['fitgeometry'] == 'rscale' and not self.fit['proper']):
                    print("XSH: {:.4f}  YSH: {:.4f}    PROPER ROT: {:.10g}    "
                          "".format(
                              self.fit['offset'][0],
                              self.fit['offset'][1],
                              self.fit['rot']))
                    print("<ROT>: {:.10g}  SKEW: {:.10g}    ROT_X: {:.10g}  "
                          "ROT_Y: {:.10g}".format(
                              self.fit['rotxy'][2],
                              self.fit['skew'],
                              self.fit['rotxy'][0],
                              self.fit['rotxy'][1]))
                    print("<SCALE>: {:.10g}  SCALE_X: {:.10g}  "
                          "SCALE_Y: {:.10g}".format(
                              self.fit['scale'][0],
                              self.fit['scale'][1],
                              self.fit['scale'][2]))
                else:
                    assert(False)

                print('FIT XRMS: {:<7.2g}    FIT YRMS: {:<7.2g}'
                      .format(*self.fit['rms']))
                print('FIT RMSE: {:<7.2g}    FIT MAE: {:<7.2g}\n'
                      .format(self.fit['rmse'], self.fit['mae']))
                print('RMS_RA: %.2g (deg)   RMS_DEC: %.2g (deg)\n'%(
                        self.fit['rms_keys']['RMS_RA'],
                        self.fit['rms_keys']['RMS_DEC']))
                print('Final solution based on ',self.fit['rms_keys']['NMATCH'],' objects.')

                self.write_fit_catalog()

                # Plot residuals, if requested by the user
                if 'residplot' in pars and "No" not in pars['residplot']:
                    xy = self.fit['img_coords']
                    resids = self.fit['resids']
                    xy_fit = xy + resids
                    title_str = 'Residuals\ for\ {0}\ using\ {1:6d}\ sources'.format(
                        self.name.replace('_','\_'),self.fit['rms_keys']['NMATCH'])
                    if not self.interactive:
                        resid_name = 'residuals_{0}.png'.format(self.rootname)
                        vector_name = resid_name.replace('residuals','vector')
                    else:
                        resid_name = None
                        vector_name = None
                    if pars['residplot'] == 'both':
                        tweakutils.make_vector_plot(None,
                            data=[xy[:,0],xy[:,1],xy_fit[:,0],xy_fit[:,1]],
                            figure_id=self.figure_id, vector=True,
                            labelsize=pars['labelsize'],
                            plotname=vector_name, title=title_str)
                        ptype=False # Setup
                        self.figure_id += 1
                    elif pars['residplot'] == 'vector':
                        ptype = True
                    else:
                        ptype = False

                    # Generate new plot
                    tweakutils.make_vector_plot(None,
                        data=[xy[:,0],xy[:,1],xy_fit[:,0],xy_fit[:,1]],
                        figure_id=self.figure_id, vector=ptype,
                        ylimit=pars['ylimit'], labelsize=pars['labelsize'],
                        plotname=resid_name, title=title_str)
                    if self.interactive:
                        prompt = ("Press ENTER for next image, \n" +
                                  "      'n' to continue without updating header or \n" +
                                  "      'q' to quit immediately...\n")
                        if sys.version_info[0] >= 3:
                            a = input(prompt)
                        else:
                            a = raw_input(prompt)
                    else:
                        a = ' '
                    if 'n' in a.lower():
                        self.perform_update = False
                    if 'q' in a.lower():
                        self.quit_immediately = True
            else:
                self.fit['offset'] = [np.nan,np.nan]
                self.fit['rot'] = np.nan
                self.fit['scale'] = [np.nan]