<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def writefits(self, filename, clobber=True, trimzero=True, binned=False, precision=None, hkeys=None):
 """Write the spectrum to a FITS table. Primary header in EXT 0. ``FILENAME``, ``ORIGIN``, and any extra keyword(s) from ``hkeys`` will also be added. Table header and data are in EXT 1. The table has 2 columns, i.e., ``WAVELENGTH`` and ``FLUX``. Data are stored in user units. Its header also will have these additional keywords: * ``EXPR`` - Description of the spectrum. * ``TDISP1`` and ``TDISP2`` - Columns display format, always "G15.7". * ``GRFTABLE`` and ``CMPTABLE`` - Graph and component table names to use with associated observation mode. These are only added if applicable. If data is already double-precision but user explicitly set output precision to single, ``pysynphot.spectrum.syn_epsilon`` defines the allowed minimum wavelength separation. This limit (:math:`3.2 \\times 10^{-4}`) was taken from IRAF STSDAS SYNPHOT FAQ. Values equal or smaller than this limit are considered as the same, and duplicates are ignored, resulting in data loss. In the way that this comparison is coded, when such precision clash happens, even when no duplicates are detected, the last row is always omitted (also data loss). Therefore, it is *not* recommended for user to force single-precision when the data is in double-precision. Parameters filename : str Output filename. clobber : bool Overwrite existing file. Default is `True`. trimzero : bool Trim off duplicate rows with flux values of zero from both ends of the spectrum. This keeps one row of zero-flux at each end, if it exists; However, it does not add a zero-flux row if it does not. Default is `True`. binned : bool Write ``self.binwave`` and ``self.binflux`` (binned) dataset, instead of ``self.wave`` and ``self.flux`` (native). Using this option when object does not have binned data will cause an exception to be raised. Default is `False`. precision : {'s', 'd', `None`} Write data out in single (``'s'``) or double (``'d'``) precision. Default is `None`, which will enforce native precision from ``self.flux``. hkeys : dict Additional keyword(s) to be added to primary FITS header, in the format of ``{keyword:(value,comment)}``. """

        pcodes={'d':'D', 's':'E'}
        if precision is None:
            precision = self.flux.dtype.char
        _precision = precision.lower()[0]
        pcodes = {'d':'D','s':'E','f':'E'}

        if clobber:
            try:
                os.remove(filename)
            except OSError:
                pass

        if binned:
            wave = self.binwave
            flux = self.binflux
        else:
            wave = self.wave
            flux = self.flux

        # Add a check for single/double precision clash, so
        # that if written out in single precision, the wavelength table
        # will still be sorted with no duplicates
        # The value of epsilon is taken from the Synphot FAQ.

        if wave.dtype == N.float64 and _precision == 's':
            idx = N.where(abs(wave[1:]-wave[:-1]) > syn_epsilon)
        else:
            idx = N.where(wave) #=> idx=[:]

        wave = wave[idx]
        flux = flux[idx]

        first, last = 0, len(flux)

        if trimzero:
            # Keep one zero at each end
            nz = flux.nonzero()[0]
            try:
                first = max(nz[0] - 1, first)
                last = min(nz[-1] + 2, last)
            except IndexError:
                pass

        # Construct the columns and HDUlist
        cw = pyfits.Column(name='WAVELENGTH',
                           array=wave[first:last],
                           unit=self.waveunits.name,
                           format=pcodes[_precision])
        cf = pyfits.Column(name='FLUX',
                           array=flux[first:last],
                           unit=self.fluxunits.name,
                           format=pcodes[_precision])

        # Make the primary header
        hdu = pyfits.PrimaryHDU()
        hdulist = pyfits.HDUList([hdu])

        # User-provided keys are written to the primary header
        # so are filename and origin
        bkeys = dict(filename=(os.path.basename(filename), 'name of file'),
                     origin=('pysynphot', 'Version (%s, %s)' %
                             (__version__, __svn_revision__)))
        # User-values if present may override default values
        if hkeys is not None:
            bkeys.update(hkeys)

        # Now update the primary header
        for key, val in bkeys.items():
            hdu.header[key] = val

        # Make the extension HDU
        cols = pyfits.ColDefs([cw, cf])
        hdu = pyfits.BinTableHDU.from_columns(cols)

        # There are some standard keywords that should be added
        # to the extension header.
        bkeys = dict(expr=(str(self), 'pysyn expression'),
                     tdisp1=('G15.7',),
                     tdisp2=('G15.7',))

        try:
            bkeys['grftable'] = (self.bandpass.obsmode.gtname,)
            bkeys['cmptable'] = (self.bandpass.obsmode.ctname,)
        except AttributeError:
            pass  # Not all spectra have these

        for key, val in bkeys.items():
            hdu.header[key] = val

        # Add the header to the list, and write the file
        hdulist.append(hdu)
        hdulist.writeto(filename)