def hist_bins(self, channels=None, nbins=None, scale='logicle', **kwargs):
        """
        Get histogram bin edges for the specified channel(s).

        These cover the range specified in ``FCSData.range(channels)`` with
        a number of bins `nbins`, with linear, logarithmic, or logicle
        spacing.

        Parameters
        ----------
        channels : int, str, list of int, list of str
            Channel(s) for which to generate histogram bins. If None,
            return a list with bins for all channels, in the order of
            ``FCSData.channels``.
        nbins : int or list of ints, optional
            The number of bins to calculate. If `channels` specifies a list
            of channels, `nbins` should be a list of integers. If `nbins`
            is None, use ``FCSData.resolution(channel)``.
        scale : str, optional
            Scale in which to generate bins. Can be either ``linear``,
            ``log``, or ``logicle``.
        kwargs : optional
            Keyword arguments specific to the selected bin scaling. Linear
            and logarithmic scaling do not use additional arguments.
            For logicle scaling, the following parameters can be provided:

            T : float, optional
                Maximum range of data. If not provided, use ``range[1]``.
            M : float, optional
                (Asymptotic) number of decades in scaled units. If not
                provided, calculate from the following::

                    max(4.5, 4.5 / np.log10(262144) * np.log10(T))

            W : float, optional
                Width of linear range in scaled units. If not provided,
                calculate using the following relationship::

                    W = (M - log10(T / abs(r))) / 2

                Where ``r`` is the minimum negative event. If no negative
                events are present, W is set to zero.

        Return
        ------
        array or list of arrays
            Histogram bin edges for the specified channel(s).

        Notes
        -----
        If ``range[0]`` is equal or less than zero and `scale` is  ``log``,
        the lower limit of the range is replaced with one.

        Logicle scaling uses the LogicleTransform class in the plot module.

        References
        ----------
        .. [1] D.R. Parks, M. Roederer, W.A. Moore, "A New Logicle Display
        Method Avoids Deceptive Effects of Logarithmic Scaling for Low
        Signals and Compensated Data," Cytometry Part A 69A:541-551, 2006,
        PMID 16604519.

        """
        # Default: all channels
        if channels is None:
            channels = list(self._channels)

        # Get numerical indices of channels
        channels = self._name_to_index(channels)

        # Convert to list if necessary
        channel_list = channels
        if not isinstance(channel_list, list):
            channel_list = [channel_list]
        if not isinstance(nbins, list):
            nbins = [nbins]*len(channel_list)
        if not isinstance(scale, list):
            scale = [scale]*len(channel_list)

        # Iterate
        bins = []
        for channel, nbins_channel, scale_channel in \
                zip(channel_list, nbins, scale):
            # Get channel resolution
            res_channel = self.resolution(channel)
            # Get default nbins
            if nbins_channel is None:
                nbins_channel = res_channel
            # Get range of channel
            range_channel = self.range(channel)
            # Generate bins according to specified scale
            if scale_channel == 'linear':
                # We will now generate ``nbins`` uniformly spaced bins centered
                # at ``linspace(range_channel[0], range_channel[1], nbins)``. To
                # do so, we need to generate ``nbins + 1`` uniformly spaced
                # points.
                delta_res = (range_channel[1] - range_channel[0]) / \
                    (res_channel - 1)
                bins_channel = np.linspace(range_channel[0] - delta_res/2,
                                           range_channel[1] + delta_res/2,
                                           nbins_channel + 1)

            elif scale_channel == 'log':
                # Check if the lower limit is equal or less than zero. If so,
                # change the lower limit to one or some lower value, such that
                # the range covers at least five decades.
                if range_channel[0] <= 0:
                    range_channel[0] = min(1., range_channel[1]/1e5)
                # Log range
                range_channel = [np.log10(range_channel[0]),
                                 np.log10(range_channel[1])]
                # We will now generate ``nbins`` uniformly spaced bins centered
                # at ``linspace(range_channel[0], range_channel[1], nbins)``. To
                # do so, we need to generate ``nbins + 1`` uniformly spaced
                # points.
                delta_res = (range_channel[1] - range_channel[0]) / \
                    (res_channel - 1)
                bins_channel = np.linspace(range_channel[0] - delta_res/2,
                                           range_channel[1] + delta_res/2,
                                           nbins_channel + 1)
                # Exponentiate bins
                bins_channel = 10**(bins_channel)

            elif scale_channel == 'logicle':
                # Create transform class
                # Use the LogicleTransform class from the plot module
                t = FlowCal.plot._LogicleTransform(data=self,
                                                   channel=channel,
                                                   **kwargs)
                # We now generate ``nbins`` uniformly spaced bins centered at
                # ``linspace(0, M, nbins)``. To do so, we need to generate
                # ``nbins + 1`` uniformly spaced points.
                delta_res = float(t.M) / (res_channel - 1)
                s = np.linspace(- delta_res/2.,
                                t.M + delta_res/2.,
                                nbins_channel + 1)
                # Finally, apply the logicle transformation to generate bins
                bins_channel = t.transform_non_affine(s)

            else:
                # Scale not supported
                raise ValueError('scale "{}" not supported'.format(
                    scale_channel))
            # Accumulate
            bins.append(bins_channel)

        # Extract from list if channels was not a list
        if not isinstance(channels, list):
            bins = bins[0]

        return bins