def mlem(op, x, data, niter, callback=None, **kwargs):

    """Maximum Likelihood Expectation Maximation algorithm.

    Attempts to solve::

        max_x L(x | data)

    where ``L(x | data)`` is the Poisson likelihood of ``x`` given ``data``.
    The likelihood depends on the forward operator ``op`` such that
    (approximately)::

        op(x) = data


    Parameters
    ----------
    op : `Operator`
        Forward operator in the inverse problem.
    x : ``op.domain`` element
        Vector to which the result is written. Its initial value is
        used as starting point of the iteration, and its values are
        updated in each iteration step.
        The initial value of ``x`` should be non-negative.
    data : ``op.range`` `element-like`
        Right-hand side of the equation defining the inverse problem.
    niter : int
        Number of iterations.
    callback : callable, optional
        Function called with the current iterate after each iteration.

    Other Parameters
    ----------------
    sensitivities : float or ``op.domain`` `element-like`, optional
        The algorithm contains a ``A^T 1``
        term, if this parameter is given, it is replaced by it.
        Default: ``op.adjoint(op.range.one())``

    Notes
    -----
    Given a forward model :math:`A` and data :math:`g`,
    the algorithm attempts to find an :math:`x` that maximizes:

    .. math::
        P(g | g \text{ is } Poisson(A(x)) \text{ distributed}).

    The algorithm is explicitly given by:

    .. math::
       x_{n+1} = \frac{x_n}{A^* 1} A^* (g / A(x_n))

    See Also
    --------
    osmlem : Ordered subsets MLEM
    loglikelihood : Function for calculating the logarithm of the likelihood
    """
    osmlem([op], x, [data], niter=niter, callback=callback,
           **kwargs)