def METHOD_NAME(self, niter=1, show_progress=False,
              compute_w=True, compute_h=True, compute_err=True):
    """ Factorize s.t. WH = data
        Parameters
        ----------
        niter : int
                number of iterations.
        show_progress : bool
                print some extra information to stdout.
        compute_h : bool
                iteratively update values for H.
        compute_w : bool
                iteratively update values for W.
        compute_err : bool
                compute Frobenius norm |data-WH| after each update and store
                it to .ferr[k].
        Updated Values
        --------------
        .W : updated values for W.
        .H : updated values for H.
        .ferr : Frobenius norm |data-WH| for each iteration.
    """
    if show_progress:
        self._logger.setLevel(logging.INFO)
    else:
        self._logger.setLevel(logging.ERROR)
    # create W and H if they don't already exist
    # -> any custom initialization to W,H should be done before
    if not hasattr(self,'W'):
           self.init_w()
    if not hasattr(self,'H'):
            self.init_h()
    if compute_err:
        self.ferr = np.zeros(niter)
    for i in range(niter):
        if compute_w:
            self.update_w()
        if compute_h:
            self.update_h()
        if compute_err:
            self.ferr[i] = self.frobenius_norm()
            self._logger.info('Iteration ' + str(i+1) + '/' + str(niter) +
            ' FN:' + str(self.ferr[i]))
        else:
            self._logger.info('Iteration ' + str(i+1) + '/' + str(niter))
        # check if the err is not changing anymore
        if i > 1 and compute_err:
            if self.converged(i):
                # adjust the error measure
                self.ferr = self.ferr[:i]
                break