<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def add_bgcolor(self, colname, cmap='copper', mode='absmax', threshold=2):
 """Change column content into HTML paragraph with background color :param colname: :param cmap: a colormap (matplotlib) or created using colormap package (from pypi). :param mode: type of normalisation in 'absmax', 'max', 'clip' (see details below) :param threshold: used if mode is set to 'clip' Colormap have values between 0 and 1 so we need to normalised the data between 0 and 1. There are 3 mode to normalise the data so far. If mode is set to 'absmax', negatives and positives values are expected to be found in a range from -inf to inf. Values are scaled in between [0,1] X' = (X / M +1) /2. where m is the absolute maximum. Ideally a colormap should be made of 3 colors, the first color used for negative values, the second for zeros and third color for positive values. If mode is set to 'clip', values are clipped to a max value (parameter *threshold* and values are normalised by that same threshold. If mode is set to 'max', values are normalised by the max. """

        try:
            # if a cmap is provided, it may be just a known cmap name
            cmap = cmap_builder(cmap)
        except:
            pass

        data = self.df[colname].values

        if len(data) == 0:
            return

        if mode == 'clip':
            data = [min(x, threshold)/float(threshold) for x in data]
        elif mode == 'absmax':
            m = abs(data.min())
            M = abs(data.max())
            M = max([m, M])
            if M != 0:
                data = (data / M + 1)/2.
        elif mode == 'max':
            if data.max() != 0:
                data = data / float(data.max())

        # the expected RGB values for a given data point
        rgbcolors = [cmap(x)[0:3] for x in data]
        hexcolors = [rgb2hex(*x, normalised=True) for x in rgbcolors]

        # need to read original data again
        data = self.df[colname].values
        # need to set precision since this is going to be a text not a number
        # so pandas will not use the precision for those cases:

        def prec(x):
            try:
                # this may fail if for instance x is nan or inf
                x = easydev.precision(x, self.pd_options['precision'])
                return x
            except:
                return x

        data = [prec(x) for x in data]
        html_formatter = '<p style="background-color:{0}">{1}</p>'
        self.df[colname] = [html_formatter.format(x, y)
                for x, y in zip(hexcolors, data)]