Instruction:
Explain what the following Python 3 code does
def density2d(data,
              channels=[0,1],
              bins=1024,
              gate_fraction=0.65,
              xscale='logicle',
              yscale='logicle',
              sigma=10.0,
              full_output=False):
    """
    Gate that preserves events in the region with highest density.

    Gate out all events in `data` but those near regions of highest
    density for the two specified channels.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : list of int, list of str, optional
        Two channels on which to perform gating.
    bins : int or array_like or [int, int] or [array, array], optional
        Bins used for gating:

          - If None, use ``data.hist_bins`` to obtain bin edges for both
            axes. None is not allowed if ``data.hist_bins`` is not
            available.
          - If int, `bins` specifies the number of bins to use for both
            axes. If ``data.hist_bins`` exists, it will be used to generate
            a number `bins` of bins.
          - If array_like, `bins` directly specifies the bin edges to use
            for both axes.
          - If [int, int], each element of `bins` specifies the number of
            bins for each axis. If ``data.hist_bins`` exists, use it to
            generate ``bins[0]`` and ``bins[1]`` bin edges, respectively.
          - If [array, array], each element of `bins` directly specifies
            the bin edges to use for each axis.
          - Any combination of the above, such as [int, array], [None,
            int], or [array, int]. In this case, None indicates to generate
            bin edges using ``data.hist_bins`` as above, int indicates the
            number of bins to generate, and an array directly indicates the
            bin edges. Note that None is not allowed if ``data.hist_bins``
            does not exist.
    gate_fraction : float, optional
        Fraction of events to retain after gating. Should be between 0 and
        1, inclusive.
    xscale : str, optional
        Scale of the bins generated for the x axis, either ``linear``,
        ``log``, or ``logicle``. `xscale` is ignored in `bins` is an array
        or a list of arrays.
    yscale : str, optional
        Scale of the bins generated for the y axis, either ``linear``,
        ``log``, or ``logicle``. `yscale` is ignored in `bins` is an array
        or a list of arrays.
    sigma : scalar or sequence of scalars, optional
        Standard deviation for Gaussian kernel used by
        `scipy.ndimage.filters.gaussian_filter` to smooth 2D histogram
        into a density.
    full_output : bool, optional
        Flag specifying to return additional outputs. If true, the outputs
        are given as a namedtuple.

    Returns
    -------
    gated_data : FCSData or numpy array
        Gated flow cytometry data of the same format as `data`.
    mask : numpy array of bool, only if ``full_output==True``
        Boolean gate mask used to gate data such that ``gated_data =
        data[mask]``.
    contour : list of 2D numpy arrays, only if ``full_output==True``
        List of 2D numpy array(s) of x-y coordinates tracing out
        the edge of the gated region.

    Raises
    ------
    ValueError
        If more or less than 2 channels are specified.
    ValueError
        If `data` has less than 2 dimensions or less than 2 events.
    Exception
        If an unrecognized matplotlib Path code is encountered when
        attempting to generate contours.

    Notes
    -----
    The algorithm for gating based on density works as follows:

        1) Calculate 2D histogram of `data` in the specified channels.
        2) Map each event from `data` to its histogram bin (implicitly
           gating out any events which exist outside specified `bins`).
        3) Use `gate_fraction` to determine number of events to retain
           (rounded up). Only events which are not implicitly gated out
           are considered.
        4) Smooth 2D histogram using a 2D Gaussian filter.
        5) Normalize smoothed histogram to obtain valid probability mass
           function (PMF).
        6) Sort bins by probability.
        7) Accumulate events (starting with events belonging to bin with
           highest probability ("densest") and proceeding to events
           belonging to bins with lowest probability) until at least the
           desired number of events is achieved. While the algorithm
           attempts to get as close to `gate_fraction` fraction of events
           as possible, more events may be retained based on how many
           events fall into each histogram bin (since entire bins are
           retained at a time, not individual events).

    """

    # Extract channels in which to gate
    if len(channels) != 2:
        raise ValueError('2 channels should be specified')
    data_ch = data[:,channels]
    if data_ch.ndim == 1:
        data_ch = data_ch.reshape((-1,1))

    # Check gating fraction
    if gate_fraction < 0 or gate_fraction > 1:
        raise ValueError('gate fraction should be between 0 and 1, inclusive')

    # Check dimensions
    if data_ch.ndim < 2:
        raise ValueError('data should have at least 2 dimensions')
    if data_ch.shape[0] <= 1:
        raise ValueError('data should have more than one event')

    # Build output namedtuple if necessary
    if full_output:
        Density2dGateOutput = collections.namedtuple(
            'Density2dGateOutput',
            ['gated_data', 'mask', 'contour'])

    # If ``data_ch.hist_bins()`` exists, obtain bin edges from it if
    # necessary.
    if hasattr(data_ch, 'hist_bins') and \
            hasattr(data_ch.hist_bins, '__call__'):
        # Check whether `bins` contains information for one or two axes
        if hasattr(bins, '__iter__') and len(bins)==2:
            # `bins` contains separate information for both axes
            # If bins for the X axis is not an iterable, get bin edges from
            # ``data_ch.hist_bins()``.
            if not hasattr(bins[0], '__iter__'):
                bins[0] = data_ch.hist_bins(channels=0,
                                            nbins=bins[0],
                                            scale=xscale)
            # If bins for the Y axis is not an iterable, get bin edges from
            # ``data_ch.hist_bins()``.
            if not hasattr(bins[1], '__iter__'):
                bins[1] = data_ch.hist_bins(channels=1,
                                            nbins=bins[1],
                                            scale=yscale)
        else:
            # `bins` contains information for one axis, which will be used
            # twice.
            # If bins is not an iterable, get bin edges from
            # ``data_ch.hist_bins()``.
            if not hasattr(bins, '__iter__'):
                bins = [data_ch.hist_bins(channels=0,
                                          nbins=bins,
                                          scale=xscale),
                        data_ch.hist_bins(channels=1,
                                          nbins=bins,
                                          scale=yscale)]

    # Make 2D histogram
    H,xe,ye = np.histogram2d(data_ch[:,0], data_ch[:,1], bins=bins)

    # Map each event to its histogram bin by sorting events into a 2D array of
    # lists which mimics the histogram.
    #
    # Use np.digitize to calculate the histogram bin index for each event
    # given the histogram bin edges. Note that the index returned by
    # np.digitize is such that bins[i-1] <= x < bins[i], whereas indexing the
    # histogram will result in the following: hist[i,j] = bin corresponding to
    # xedges[i] <= x < xedges[i+1] and yedges[i] <= y < yedges[i+1].
    # Therefore, we need to subtract 1 from the np.digitize result to be able
    # to index into the appropriate bin in the histogram.
    event_indices = np.arange(data_ch.shape[0])
    x_bin_indices = np.digitize(data_ch[:,0], bins=xe) - 1
    y_bin_indices = np.digitize(data_ch[:,1], bins=ye) - 1

    # In the current version of numpy, there exists a disparity in how
    # np.histogram and np.digitize treat the rightmost bin edge (np.digitize
    # is not the strict inverse of np.histogram). Specifically, np.histogram
    # treats the rightmost bin interval as fully closed (rightmost bin edge is
    # included in rightmost bin), whereas np.digitize treats all bins as
    # half-open (you can specify which side is closed and which side is open;
    # `right` parameter). The expected behavior for this gating function is to
    # mimic np.histogram behavior, so we must reconcile this disparity.
    x_bin_indices[data_ch[:,0] == xe[-1]] = len(xe)-2
    y_bin_indices[data_ch[:,1] == ye[-1]] = len(ye)-2

    # Ignore (gate out) events which exist outside specified bins.
    # `np.digitize()-1` will assign events less than `bins` to bin "-1" and
    # events greater than `bins` to len(bins)-1.
    outlier_mask = (
        (x_bin_indices == -1) |
        (x_bin_indices == len(xe)-1) |
        (y_bin_indices == -1) |
        (y_bin_indices == len(ye)-1))

    event_indices = event_indices[~outlier_mask]
    x_bin_indices = x_bin_indices[~outlier_mask]
    y_bin_indices = y_bin_indices[~outlier_mask]

    # Create a 2D array of lists mimicking the histogram to accumulate events
    # associated with each bin.
    filler = np.frompyfunc(lambda x: list(), 1, 1)
    H_events = np.empty_like(H, dtype=np.object)
    filler(H_events, H_events)

    for event_idx, x_bin_idx, y_bin_idx in \
            zip(event_indices, x_bin_indices, y_bin_indices):
        H_events[x_bin_idx, y_bin_idx].append(event_idx)

    # Determine number of events to keep. Only consider events which have not
    # been thrown out as outliers.
    n = int(np.ceil(gate_fraction*float(len(event_indices))))

    # n = 0 edge case (e.g. if gate_fraction = 0.0); incorrectly handled below
    if n == 0:
        mask = np.zeros(shape=data_ch.shape[0], dtype=bool)
        gated_data = data[mask]
        if full_output:
            return Density2dGateOutput(
                gated_data=gated_data, mask=mask, contour=[])
        else:
            return gated_data

    # Smooth 2D histogram
    sH = scipy.ndimage.filters.gaussian_filter(
        H,
        sigma=sigma,
        order=0,
        mode='constant',
        cval=0.0,
        truncate=6.0)

    # Normalize smoothed histogram to make it a valid probability mass function
    D = sH / np.sum(sH)

    # Sort bins by density
    vD = D.ravel()
    vH = H.ravel()
    sidx = np.argsort(vD)[::-1]
    svH = vH[sidx]  # linearized counts array sorted by density

    # Find minimum number of accepted bins needed to reach specified number
    # of events
    csvH = np.cumsum(svH)
    Nidx = np.nonzero(csvH >= n)[0][0]    # we want to include this index

    # Get indices of events to keep
    vH_events = H_events.ravel()
    accepted_indices = vH_events[sidx[:(Nidx+1)]]
    accepted_indices = np.array([item       # flatten list of lists
                                 for sublist in accepted_indices
                                 for item in sublist])
    accepted_indices = np.sort(accepted_indices)

    # Convert list of accepted indices to boolean mask array
    mask = np.zeros(shape=data.shape[0], dtype=bool)
    mask[accepted_indices] = True

    gated_data = data[mask]

    if full_output:
        # Use scikit-image to find the contour of the gated region
        #
        # To find the contour of the gated region, values in the 2D probability
        # mass function ``D`` are used to trace contours at the level of the
        # probability associated with the last accepted bin, ``vD[sidx[Nidx]]``.

        # find_contours() specifies contours as collections of row and column
        # indices into the density matrix. The row or column index may be
        # interpolated (i.e. non-integer) for greater precision.
        contours_ij = skimage.measure.find_contours(D, vD[sidx[Nidx]])

        # Map contours from indices into density matrix to histogram x and y
        # coordinate spaces (assume values in the density matrix are associated
        # with histogram bin centers).
        xc = (xe[:-1] + xe[1:]) / 2.0   # x-axis bin centers
        yc = (ye[:-1] + ye[1:]) / 2.0   # y-axis bin centers

        contours = [np.array([np.interp(contour_ij[:,0],
                                        np.arange(len(xc)),
                                        xc),
                              np.interp(contour_ij[:,1],
                                        np.arange(len(yc)),
                                        yc)]).T
                    for contour_ij in contours_ij]

        return Density2dGateOutput(
            gated_data=gated_data, mask=mask, contour=contours)
    else:
        return gated_data

Response: Generates a sequence of states that preserves events in the region with highest density for the two specified channels.


Instruction:
How would you implement a function in Python 3 that
applies some transformation function to flow cytometry data. This function is a template transformation function, intended to be used by other specific transformation functions. It performs basic checks on `channels` and `data`. It then applies `transform_fxn` to the specified channels. Finally, it rescales ``data.range`` and if necessary. Parameters ---------- data : FCSData or numpy array NxD flow cytometry data where N is the number of events and D is the number of parameters (aka channels). channels : int, str, list of int, list of str, optional Channels on which to perform the transformation. If `channels` is None, use def_channels. transform_fxn : function Function that performs the actual transformation. def_channels : int, str, list of int, list of str, optional Default set of channels in which to perform the transformation. If `def_channels` is None, use all channels. Returns ------- data_t : FCSData or numpy array NxD transformed flow cytometry data.

Response:
def transform(data, channels, transform_fxn, def_channels = None):
    """
    Apply some transformation function to flow cytometry data.

    This function is a template transformation function, intended to be
    used by other specific transformation functions. It performs basic
    checks on `channels` and `data`. It then applies `transform_fxn` to the
    specified channels. Finally, it rescales  ``data.range`` and if
    necessary.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : int, str, list of int, list of str, optional
        Channels on which to perform the transformation. If `channels` is
        None, use def_channels.
    transform_fxn : function
        Function that performs the actual transformation.
    def_channels : int, str, list of int, list of str, optional
        Default set of channels in which to perform the transformation.
        If `def_channels` is None, use all channels.

    Returns
    -------
    data_t : FCSData or numpy array
        NxD transformed flow cytometry data.

    """
    # Copy data array
    data_t = data.copy().astype(np.float64)

    # Default
    if channels is None:
        if def_channels is None:
            channels = range(data_t.shape[1])
        else:
            channels = def_channels

    # Convert channels to iterable
    if not (hasattr(channels, '__iter__') \
            and not isinstance(channels, six.string_types)):
        channels = [channels]

    # Apply transformation
    data_t[:,channels] = transform_fxn(data_t[:,channels])

    # Apply transformation to ``data.range``
    if hasattr(data_t, '_range'):
        for channel in channels:
            # Transform channel name to index if necessary
            channel_idx = data_t._name_to_index(channel)
            if data_t._range[channel_idx] is not None:
                data_t._range[channel_idx] = \
                    transform_fxn(data_t._range[channel_idx])

    return data_t


Instruction:
Can you write a function in Python 3 where it
transforms the flow cytometry data to Relative Fluorescence Units RFI.

Response:
def to_rfi(data,
           channels=None,
           amplification_type=None,
           amplifier_gain=None,
           resolution=None):
    """
    Transform flow cytometry data to Relative Fluorescence Units (RFI).

    If ``amplification_type[0]`` is different from zero, data has been
    taken using a log amplifier. Therefore, to transform to RFI, the
    following operation is applied::

        y = a[1]*10^(a[0] * (x/r))

    Where ``x`` and ``y`` are the original and transformed data,
    respectively; ``a`` is `amplification_type` argument, and ``r`` is
    `resolution`. This will transform flow cytometry data taken with a log
    amplifier and an ADC of range ``r`` to linear RFIs, such
    that it covers ``a[0]`` decades of signal with a minimum value of
    ``a[1]``.

    If ``amplification_type[0]==0``, however, a linear amplifier has been
    used and the following operation is applied instead::

        y = x/g

    Where ``g`` is `amplifier_gain`. This will transform flow cytometry
    data taken with a linear amplifier of gain ``g`` back to RFIs.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : int, str, list of int, list of str, optional
        Channels on which to perform the transformation. If `channels` is
        None, perform transformation in all channels.
    amplification_type : tuple or list of tuple
        The amplification type of the specified channel(s). This should be
        reported as a tuple, in which the first element indicates how many
        decades the logarithmic amplifier covers, and the second indicates
        the linear value that corresponds to a channel value of zero. If
        the first element is zero, the amplification type is linear. This
        is similar to the $PnE keyword from the FCS standard. If None, take
        `amplification_type` from ``data.amplification_type(channel)``.
    amplifier_gain : float or list of floats, optional
        The linear amplifier gain of the specified channel(s). Only used if
        ``amplification_type[0]==0`` (linear amplifier). If None,
        take `amplifier_gain` from ``data.amplifier_gain(channel)``. If
        `data` does not contain ``amplifier_gain()``, use 1.0.
    resolution : int, float, or list of int or float, optional
        Maximum range, for each specified channel. Only needed if
        ``amplification_type[0]!=0`` (log amplifier). If None, take
        `resolution` from ``len(data.domain(channel))``.

    Returns
    -------
    FCSData or numpy array
        NxD transformed flow cytometry data.

    """
    # Default: all channels
    if channels is None:
        channels = range(data.shape[1])

    if not (hasattr(channels, '__iter__') \
            and not isinstance(channels, six.string_types)):
        # If channels is not an iterable, convert it, along with resolution,
        # amplification_type, and amplifier_gain.
        channels = [channels]
        amplification_type = [amplification_type]
        amplifier_gain = [amplifier_gain]
        resolution = [resolution]
    else:
        # If channels is an iterable, check that the other attributes are either
        # None, or iterables of the same length.

        if amplification_type is None:
            # If None, propagate None for all channels
            amplification_type = [None]*len(channels)
        elif hasattr(amplification_type, '__iter__'):
            # If it's a list, it should be the same length as channels
            if len(amplification_type) != len(channels):
                raise ValueError("channels and amplification_type should have "
                    "the same length")
        else:
            # If it's not a list or None, raise error
            raise ValueError("channels and amplification_type should have the "
                    "same length")

        if amplifier_gain is None:
            # If None, propagate None for all channels
            amplifier_gain = [None]*len(channels)
        elif hasattr(amplifier_gain, '__iter__'):
            # If it's a list, it should be the same length as channels
            if len(amplifier_gain) != len(channels):
                raise ValueError("channels and amplifier_gain should have "
                    "the same length")
        else:
            # If it's not a list or None, raise error
            raise ValueError("channels and amplifier_gain should have the "
                    "same length")

        if resolution is None:
            # If None, propagate None for all channels
            resolution = [None]*len(channels)
        elif hasattr(resolution, '__iter__'):
            # If it's a list, it should be the same length as channels
            if len(resolution) != len(channels):
                raise ValueError("channels and resolution should have "
                    "the same length")
        else:
            # If it's not a list or None, raise error
            raise ValueError("channels and resolution should have the "
                    "same length")

    # Convert channels to integers
    if hasattr(data, '_name_to_index'):
        channels = data._name_to_index(channels)
    else:
        channels = channels

    # Copy data array
    data_t = data.copy().astype(np.float64)

    # Iterate over channels
    for channel, r, at, ag in \
            zip(channels, resolution, amplification_type, amplifier_gain):
        # If amplification type is None, try to obtain from data
        if at is None:
            if hasattr(data, 'amplification_type'):
                at = data.amplification_type(channel)
            else:
                raise ValueError('amplification_type should be specified')
        # Define transformation, depending on at[0]
        if at[0]==0:
            # Linear amplifier
            # If no amplifier gain has been specified, try to obtain from data,
            # otherwise assume one
            if ag is None:
                if hasattr(data, 'amplifier_gain') and \
                        hasattr(data.amplifier_gain, '__call__'):
                    ag = data.amplifier_gain(channel)
                    # If the linear gain has not been specified, it should be
                    # assumed to be one.
                    if ag is None:
                        ag = 1.
                else:
                    ag = 1.
            tf = lambda x: x/ag
        else:
            # Log amplifier
            # If no range has been specified, try to obtain from data.
            if r is None:
                if hasattr(data, 'resolution'):
                    r = data.resolution(channel)
                else:
                    raise ValueError('range should be specified')
            tf = lambda x: at[1] * 10**(at[0]/float(r) * x)
        # Apply transformation to event list
        data_t[:,channel] = tf(data_t[:,channel])
        # Apply transformation to range
        if hasattr(data_t, '_range') and data_t._range[channel] is not None:
            data_t._range[channel] = [tf(data_t._range[channel][0]),
                                      tf(data_t._range[channel][1])]

    return data_t


Instruction:
Write a Python 3 script to
transform flow cytometry data using a standard curve function.

Response:
def to_mef(data, channels, sc_list, sc_channels = None):
    """
    Transform flow cytometry data using a standard curve function.

    This function accepts a list of standard curves (`sc_list`) and a list
    of channels to which those standard curves should be applied
    (`sc_channels`). `to_mef` automatically checks whether a standard curve
    is available for each channel specified in `channels`, and throws an
    error otherwise.

    This function is intended to be reduced to the following signature::

        to_mef_reduced(data, channels)

    by using ``functools.partial`` once a list of standard curves and their
    respective channels is available.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : int, str, list of int, list of str
        Channels on which to perform the transformation. If `channels` is
        None, perform transformation in all channels specified on
        `sc_channels`.
    sc_list : list of functions
        Functions implementing the standard curves for each channel in
        `sc_channels`.
    sc_channels : list of int or list of str, optional
        List of channels corresponding to each function in `sc_list`. If
        None, use all channels in `data`.

    Returns
    -------
    FCSData or numpy array
        NxD transformed flow cytometry data.

    Raises
    ------
    ValueError
        If any channel specified in `channels` is not in `sc_channels`.

    """
    # Default sc_channels
    if sc_channels is None:
        if data.ndim == 1:
            sc_channels = range(data.shape[0])
        else:
            sc_channels = range(data.shape[1])
    # Check that sc_channels and sc_list have the same length
    if len(sc_channels) != len(sc_list):
        raise ValueError("sc_channels and sc_list should have the same length")
    # Convert sc_channels to indices
    if hasattr(data, '_name_to_index'):
        sc_channels = data._name_to_index(sc_channels)

    # Default channels
    if channels is None:
        channels = sc_channels
    # Convert channels to iterable
    if not (hasattr(channels, '__iter__') \
            and not isinstance(channels, six.string_types)):
        channels = [channels]
    # Convert channels to index
    if hasattr(data, '_name_to_index'):
        channels_ind = data._name_to_index(channels)
    else:
        channels_ind = channels
    # Check if every channel is in sc_channels
    for chi, chs in zip(channels_ind, channels):
        if chi not in sc_channels:
            raise ValueError("no standard curve for channel {}".format(chs))

    # Copy data array
    data_t = data.copy().astype(np.float64)

    # Iterate over channels
    for chi, sc in zip(sc_channels, sc_list):
        if chi not in channels_ind:
            continue
        # Apply transformation
        data_t[:,chi] = sc(data_t[:,chi])
        # Apply transformation to range
        if hasattr(data_t, '_range') and data_t._range[chi] is not None:
            data_t._range[chi] = [sc(data_t._range[chi][0]),
                                  sc(data_t._range[chi][1])]

    return data_t


Instruction:
Explain what the following Python 3 code does
def hist1d(data_list,
           channel=0,
           xscale='logicle',
           bins=256,
           histtype='stepfilled',
           normed_area=False,
           normed_height=False,
           xlabel=None,
           ylabel=None,
           xlim=None,
           ylim=None,
           title=None,
           legend=False,
           legend_loc='best',
           legend_fontsize='medium',
           legend_labels=None,
           facecolor=None,
           edgecolor=None,
           savefig=None,
           **kwargs):
    """
    Plot one 1D histogram from one or more flow cytometry data sets.

    Parameters
    ----------
    data_list : FCSData or numpy array or list of FCSData or numpy array
        Flow cytometry data to plot.
    channel : int or str, optional
        Channel from where to take the events to plot. If ndim == 1,
        channel is ignored. String channel specifications are only
        supported for data types which support string-based indexing
        (e.g. FCSData).
    xscale : str, optional
        Scale of the x axis, either ``linear``, ``log``, or ``logicle``.
    bins : int or array_like, optional
        If `bins` is an integer, it specifies the number of bins to use.
        If `bins` is an array, it specifies the bin edges to use. If `bins`
        is None or an integer, `hist1d` will attempt to use
        ``data.hist_bins`` to generate the bins automatically.
    histtype : {'bar', 'barstacked', 'step', 'stepfilled'}, str, optional
        Histogram type. Directly passed to ``plt.hist``.
    normed_area : bool, optional
        Flag indicating whether to normalize the histogram such that the
        area under the curve is equal to one. The resulting plot is
        equivalent to a probability density function.
    normed_height : bool, optional
        Flag indicating whether to normalize the histogram such that the
        sum of all bins' heights is equal to one. The resulting plot is
        equivalent to a probability mass function. `normed_height` is
        ignored if `normed_area` is True.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    xlabel : str, optional
        Label to use on the x axis. If None, attempts to extract channel
        name from last data object.
    ylabel : str, optional
        Label to use on the y axis. If None and ``normed_area==True``, use
        'Probability'. If None, ``normed_area==False``, and
        ``normed_height==True``, use 'Counts (normalized)'. If None,
        ``normed_area==False``, and ``normed_height==False``, use 'Counts'.
    xlim : tuple, optional
        Limits for the x axis. If not specified and `bins` exists, use
        the lowest and highest values of `bins`.
    ylim : tuple, optional
        Limits for the y axis.
    title : str, optional
        Plot title.
    legend : bool, optional
        Flag specifying whether to include a legend. If `legend` is True,
        the legend labels will be taken from `legend_labels` if present,
        else they will be taken from ``str(data_list[i])``.
    legend_loc : str, optional
        Location of the legend.
    legend_fontsize : int or str, optional
        Font size for the legend.
    legend_labels : list, optional
        Labels to use for the legend.
    facecolor : matplotlib color or list of matplotlib colors, optional
        The histogram's facecolor. It can be a list with the same length as
        `data_list`. If `edgecolor` and `facecolor` are not specified, and
        ``histtype == 'stepfilled'``, the facecolor will be taken from the
        module-level variable `cmap_default`.
    edgecolor : matplotlib color or list of matplotlib colors, optional
        The histogram's edgecolor. It can be a list with the same length as
        `data_list`. If `edgecolor` and `facecolor` are not specified, and
        ``histtype == 'step'``, the edgecolor will be taken from the
        module-level variable `cmap_default`.
    kwargs : dict, optional
        Additional parameters passed directly to matploblib's ``hist``.

    Notes
    -----
    `hist1d` calls matplotlib's ``hist`` function for each object in
    `data_list`. `hist_type`, the type of histogram to draw, is directly
    passed to ``plt.hist``. Additional keyword arguments provided to
    `hist1d` are passed directly to ``plt.hist``.

    If `normed_area` is set to True, `hist1d` calls ``plt.hist`` with
    ``density`` (or ``normed``, if matplotlib's version is older than
    2.2.0) set to True. There is a bug in matplotlib 2.1.0 that
    produces an incorrect plot in these conditions. We do not recommend
    using matplotlib 2.1.0 if `normed_area` is expected to be used.

    """
    # Using `normed_area` with matplotlib 2.1.0 causes an incorrect plot to be
    # produced. Raise warning in these conditions.
    if normed_area and packaging.version.parse(matplotlib.__version__) \
            == packaging.version.parse('2.1.0'):
        warnings.warn("bug in matplotlib 2.1.0 will result in an incorrect plot"
            " when normed_area is set to True")

    # Convert to list if necessary
    if not isinstance(data_list, list):
        data_list = [data_list]

    # Default colors
    if histtype == 'stepfilled':
        if facecolor is None:
            facecolor = [cmap_default(i)
                         for i in np.linspace(0, 1, len(data_list))]
        if edgecolor is None:
            edgecolor = ['black']*len(data_list)
    elif histtype == 'step':
        if edgecolor is None:
            edgecolor = [cmap_default(i)
                         for i in np.linspace(0, 1, len(data_list))]

    # Convert colors to lists if necessary
    if not isinstance(edgecolor, list):
        edgecolor = [edgecolor]*len(data_list)
    if not isinstance(facecolor, list):
        facecolor = [facecolor]*len(data_list)

    # Collect scale parameters that depend on all elements in data_list
    xscale_kwargs = {}
    if xscale=='logicle':
        t = _LogicleTransform(data=data_list, channel=channel)
        xscale_kwargs['T'] = t.T
        xscale_kwargs['M'] = t.M
        xscale_kwargs['W'] = t.W

    # Iterate through data_list
    for i, data in enumerate(data_list):
        # Extract channel
        if data.ndim > 1:
            y = data[:, channel]
        else:
            y = data

        # If ``data_plot.hist_bins()`` exists, obtain bin edges from it if
        # necessary. If it does not exist, do not modify ``bins``.
        if hasattr(y, 'hist_bins') and hasattr(y.hist_bins, '__call__'):
            # If bins is None or an integer, get bin edges from
            # ``data_plot.hist_bins()``.
            if bins is None or isinstance(bins, int):
                bins = y.hist_bins(channels=0,
                                   nbins=bins,
                                   scale=xscale,
                                   **xscale_kwargs)

        # Decide whether to normalize
        if normed_height and not normed_area:
            weights = np.ones_like(y)/float(len(y))
        else:
            weights = None

        # Actually plot
        if packaging.version.parse(matplotlib.__version__) \
                >= packaging.version.parse('2.2'):
            if bins is not None:
                n, edges, patches = plt.hist(y,
                                             bins,
                                             weights=weights,
                                             density=normed_area,
                                             histtype=histtype,
                                             edgecolor=edgecolor[i],
                                             facecolor=facecolor[i],
                                             **kwargs)
            else:
                n, edges, patches = plt.hist(y,
                                             weights=weights,
                                             density=normed_area,
                                             histtype=histtype,
                                             edgecolor=edgecolor[i],
                                             facecolor=facecolor[i],
                                             **kwargs)
        else:
            if bins is not None:
                n, edges, patches = plt.hist(y,
                                             bins,
                                             weights=weights,
                                             normed=normed_area,
                                             histtype=histtype,
                                             edgecolor=edgecolor[i],
                                             facecolor=facecolor[i],
                                             **kwargs)
            else:
                n, edges, patches = plt.hist(y,
                                             weights=weights,
                                             normed=normed_area,
                                             histtype=histtype,
                                             edgecolor=edgecolor[i],
                                             facecolor=facecolor[i],
                                             **kwargs)

    # Set scale of x axis
    if xscale=='logicle':
        plt.gca().set_xscale(xscale, data=data_list, channel=channel)
    else:
        plt.gca().set_xscale(xscale)

    ###
    # Final configuration
    ###

    # x and y labels
    if xlabel is not None:
        # Highest priority is user-provided label
        plt.xlabel(xlabel)
    elif hasattr(y, 'channels'):
        # Attempt to use channel name
        plt.xlabel(y.channels[0])

    if ylabel is not None:
        # Highest priority is user-provided label
        plt.ylabel(ylabel)
    elif normed_area:
        plt.ylabel('Probability')
    elif normed_height:
        plt.ylabel('Counts (normalized)')
    else:
        # Default is "Counts"
        plt.ylabel('Counts')

    # x and y limits
    if xlim is not None:
        # Highest priority is user-provided limits
        plt.xlim(xlim)
    elif bins is not None:
        # Use bins if specified
        plt.xlim((edges[0], edges[-1]))

    if ylim is not None:
        plt.ylim(ylim)

    # Title
    if title is not None:
        plt.title(title)

    # Legend
    if legend:
        if legend_labels is None:
            legend_labels = [str(data) for data in data_list]
        plt.legend(legend_labels,
                   loc=legend_loc,
                   prop={'size': legend_fontsize})

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()

Response: Plots one 1D histogram from one or more flow cytometry data sets.


Instruction:
Can you tell what is the following Python 3 function doing
def density2d(data,
              channels=[0,1],
              bins=1024,
              mode='mesh',
              normed=False,
              smooth=True,
              sigma=10.0,
              colorbar=False,
              xscale='logicle',
              yscale='logicle',
              xlabel=None,
              ylabel=None,
              xlim=None,
              ylim=None,
              title=None,
              savefig=None,
              **kwargs):
    """
    Plot a 2D density plot from two channels of a flow cytometry data set.

    `density2d` has two plotting modes which are selected using the `mode`
    argument. With ``mode=='mesh'``, this function plots the data as a true
    2D histogram, in which a plane is divided into bins and the color of
    each bin is directly related to the number of elements therein. With
    ``mode=='scatter'``, this function also calculates a 2D histogram,
    but it plots a 2D scatter plot in which each dot corresponds to a bin,
    colored according to the number elements therein. The most important
    difference is that the ``scatter`` mode does not color regions
    corresponding to empty bins. This allows for easy identification of
    regions with low number of events. For both modes, the calculated
    histogram can be smoothed using a Gaussian kernel by specifying
    ``smooth=True``. The width of the kernel is, in this case, given by
    `sigma`.

    Parameters
    ----------
    data : FCSData or numpy array
        Flow cytometry data to plot.
    channels : list of int, list of str, optional
        Two channels to use for the plot.
    bins : int or array_like or [int, int] or [array, array], optional
        Bins used for plotting:

          - If None, use ``data.hist_bins`` to obtain bin edges for both
            axes. None is not allowed if ``data.hist_bins`` is not
            available.
          - If int, `bins` specifies the number of bins to use for both
            axes. If ``data.hist_bins`` exists, it will be used to generate
            a number `bins` of bins.
          - If array_like, `bins` directly specifies the bin edges to use
            for both axes.
          - If [int, int], each element of `bins` specifies the number of
            bins for each axis. If ``data.hist_bins`` exists, use it to
            generate ``bins[0]`` and ``bins[1]`` bin edges, respectively.
          - If [array, array], each element of `bins` directly specifies
            the bin edges to use for each axis.
          - Any combination of the above, such as [int, array], [None,
            int], or [array, int]. In this case, None indicates to generate
            bin edges using ``data.hist_bins`` as above, int indicates the
            number of bins to generate, and an array directly indicates the
            bin edges. Note that None is not allowed if ``data.hist_bins``
            does not exist.
    mode : {'mesh', 'scatter'}, str, optional
        Plotting mode. 'mesh' produces a 2D-histogram whereas 'scatter'
        produces a scatterplot colored by histogram bin value.
    normed : bool, optional
        Flag indicating whether to plot a normed histogram (probability
        mass function instead of a counts-based histogram).
    smooth : bool, optional
        Flag indicating whether to apply Gaussian smoothing to the
        histogram.
    colorbar : bool, optional
        Flag indicating whether to add a colorbar to the plot.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    sigma : float, optional
        The sigma parameter for the Gaussian kernel to use when smoothing.
    xscale : str, optional
        Scale of the x axis, either ``linear``, ``log``, or ``logicle``.
    yscale : str, optional
        Scale of the y axis, either ``linear``, ``log``, or ``logicle``
    xlabel : str, optional
        Label to use on the x axis. If None, attempts to extract channel
        name from `data`.
    ylabel : str, optional
        Label to use on the y axis. If None, attempts to extract channel
        name from `data`.
    xlim : tuple, optional
        Limits for the x axis. If not specified and `bins` exists, use
        the lowest and highest values of `bins`.
    ylim : tuple, optional
        Limits for the y axis. If not specified and `bins` exists, use
        the lowest and highest values of `bins`.
    title : str, optional
        Plot title.
    kwargs : dict, optional
        Additional parameters passed directly to the underlying matplotlib
        functions: ``plt.scatter`` if ``mode==scatter``, and
        ``plt.pcolormesh`` if ``mode==mesh``.

    """
    # Extract channels to plot
    if len(channels) != 2:
        raise ValueError('two channels need to be specified')
    data_plot = data[:, channels]

    # If ``data_plot.hist_bins()`` exists, obtain bin edges from it if
    # necessary.
    if hasattr(data_plot, 'hist_bins') and \
            hasattr(data_plot.hist_bins, '__call__'):
        # Check whether `bins` contains information for one or two axes
        if hasattr(bins, '__iter__') and len(bins)==2:
            # `bins` contains separate information for both axes
            # If bins for the X axis is not an iterable, get bin edges from
            # ``data_plot.hist_bins()``.
            if not hasattr(bins[0], '__iter__'):
                bins[0] = data_plot.hist_bins(channels=0,
                                              nbins=bins[0],
                                              scale=xscale)
            # If bins for the Y axis is not an iterable, get bin edges from
            # ``data_plot.hist_bins()``.
            if not hasattr(bins[1], '__iter__'):
                bins[1] = data_plot.hist_bins(channels=1,
                                              nbins=bins[1],
                                              scale=yscale)
        else:
            # `bins` contains information for one axis, which will be used
            # twice.
            # If bins is not an iterable, get bin edges from
            # ``data_plot.hist_bins()``.
            if not hasattr(bins, '__iter__'):
                bins = [data_plot.hist_bins(channels=0,
                                            nbins=bins,
                                            scale=xscale),
                        data_plot.hist_bins(channels=1,
                                            nbins=bins,
                                            scale=yscale)]

    else:
        # Check if ``bins`` is None and raise error
        if bins is None:
            raise ValueError("bins should be specified")

    # If colormap is not specified, use the default of this module
    if 'cmap' not in kwargs:
        kwargs['cmap'] = cmap_default

    # Calculate histogram
    H,xe,ye = np.histogram2d(data_plot[:,0], data_plot[:,1], bins=bins)

    # Smooth
    if smooth:
        sH = scipy.ndimage.filters.gaussian_filter(
            H,
            sigma=sigma,
            order=0,
            mode='constant',
            cval=0.0)
    else:
        sH = None

    # Normalize
    if normed:
        H = H / np.sum(H)
        sH = sH / np.sum(sH) if sH is not None else None

    ###
    # Plot
    ###

    # numpy histograms are organized such that the 1st dimension (eg. FSC) =
    # rows (1st index) and the 2nd dimension (eg. SSC) = columns (2nd index).
    # Visualized as is, this results in x-axis = SSC and y-axis = FSC, which
    # is not what we're used to. Transpose the histogram array to fix the
    # axes.
    H = H.T
    sH = sH.T if sH is not None else None

    if mode == 'scatter':
        Hind = np.ravel(H)
        xc = (xe[:-1] + xe[1:]) / 2.0   # x-axis bin centers
        yc = (ye[:-1] + ye[1:]) / 2.0   # y-axis bin centers
        xv, yv = np.meshgrid(xc, yc)
        x = np.ravel(xv)[Hind != 0]
        y = np.ravel(yv)[Hind != 0]
        z = np.ravel(H if sH is None else sH)[Hind != 0]
        plt.scatter(x, y, s=1.5, edgecolor='none', c=z, **kwargs)
    elif mode == 'mesh':
        plt.pcolormesh(xe, ye, H if sH is None else sH, **kwargs)
    else:
        raise ValueError("mode {} not recognized".format(mode))

    if colorbar:
        cbar = plt.colorbar()
        if normed:
            cbar.ax.set_ylabel('Probability')
        else:
            cbar.ax.set_ylabel('Counts')

    # Set scale of axes
    if xscale=='logicle':
        plt.gca().set_xscale(xscale, data=data_plot, channel=0)
    else:
        plt.gca().set_xscale(xscale)
    if yscale=='logicle':
        plt.gca().set_yscale(yscale, data=data_plot, channel=1)
    else:
        plt.gca().set_yscale(yscale)

    # x and y limits
    if xlim is not None:
        # Highest priority is user-provided limits
        plt.xlim(xlim)
    else:
        # Use histogram edges
        plt.xlim((xe[0], xe[-1]))

    if ylim is not None:
        # Highest priority is user-provided limits
        plt.ylim(ylim)
    else:
        # Use histogram edges
        plt.ylim((ye[0], ye[-1]))

    # x and y labels
    if xlabel is not None:
        # Highest priority is user-provided label
        plt.xlabel(xlabel)
    elif hasattr(data_plot, 'channels'):
        # Attempt to use channel name
        plt.xlabel(data_plot.channels[0])

    if ylabel is not None:
        # Highest priority is user-provided label
        plt.ylabel(ylabel)
    elif hasattr(data_plot, 'channels'):
        # Attempt to use channel name
        plt.ylabel(data_plot.channels[1])

    # title
    if title is not None:
        plt.title(title)

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()

Response: This function plots a 2D density plot from two channels of flow cytometry data.


Instruction:
Create a Python 3 function for
generating a 2D scatter plot from one or more FCSData objects or numpy arrays.

Response:
def scatter2d(data_list,
              channels=[0,1],
              xscale='logicle',
              yscale='logicle',
              xlabel=None,
              ylabel=None,
              xlim=None,
              ylim=None,
              title=None,
              color=None,
              savefig=None,
              **kwargs):
    """
    Plot 2D scatter plot from one or more FCSData objects or numpy arrays.

    Parameters
    ----------
    data_list : array or FCSData or list of array or list of FCSData
        Flow cytometry data to plot.
    channels : list of int, list of str
        Two channels to use for the plot.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    xscale : str, optional
        Scale of the x axis, either ``linear``, ``log``, or ``logicle``.
    yscale : str, optional
        Scale of the y axis, either ``linear``, ``log``, or ``logicle``.
    xlabel : str, optional
        Label to use on the x axis. If None, attempts to extract channel
        name from last data object.
    ylabel : str, optional
        Label to use on the y axis. If None, attempts to extract channel
        name from last data object.
    xlim : tuple, optional
        Limits for the x axis. If None, attempts to extract limits from the
        range of the last data object.
    ylim : tuple, optional
        Limits for the y axis. If None, attempts to extract limits from the
        range of the last data object.
    title : str, optional
        Plot title.
    color : matplotlib color or list of matplotlib colors, optional
        Color for the scatter plot. It can be a list with the same length
        as `data_list`. If `color` is not specified, elements from
        `data_list` are plotted with colors taken from the module-level
        variable `cmap_default`.
    kwargs : dict, optional
        Additional parameters passed directly to matploblib's ``scatter``.

    Notes
    -----
    `scatter2d` calls matplotlib's ``scatter`` function for each object in
    data_list. Additional keyword arguments provided to `scatter2d` are
    passed directly to ``plt.scatter``.

    """
    # Check appropriate number of channels
    if len(channels) != 2:
        raise ValueError('two channels need to be specified')

    # Convert to list if necessary
    if not isinstance(data_list, list):
        data_list = [data_list]

    # Default colors
    if color is None:
        color = [cmap_default(i) for i in np.linspace(0, 1, len(data_list))]

    # Convert color to list, if necessary
    if not isinstance(color, list):
       color = [color]*len(data_list)

    # Iterate through data_list
    for i, data in enumerate(data_list):
        # Get channels to plot
        data_plot = data[:, channels]
        # Make scatter plot
        plt.scatter(data_plot[:,0],
                    data_plot[:,1],
                    s=5,
                    alpha=0.25,
                    color=color[i],
                    **kwargs)

    # Set labels if specified, else try to extract channel names
    if xlabel is not None:
        plt.xlabel(xlabel)
    elif hasattr(data_plot, 'channels'):
        plt.xlabel(data_plot.channels[0])
    if ylabel is not None:
        plt.ylabel(ylabel)
    elif hasattr(data_plot, 'channels'):
        plt.ylabel(data_plot.channels[1])

    # Set scale of axes
    if xscale=='logicle':
        plt.gca().set_xscale(xscale, data=data_list, channel=channels[0])
    else:
        plt.gca().set_xscale(xscale)
    if yscale=='logicle':
        plt.gca().set_yscale(yscale, data=data_list, channel=channels[1])
    else:
        plt.gca().set_yscale(yscale)

    # Set plot limits if specified, else extract range from data_list.
    # ``.hist_bins`` with one bin works better for visualization that
    # ``.range``, because it deals with two issues. First, it automatically
    # deals with range values that are outside the domain of the current scaling
    # (e.g. when the lower range value is zero and the scaling is logarithmic).
    # Second, it takes into account events that are outside the limits specified
    # by .range (e.g. negative events will be shown with logicle scaling, even
    # when the lower range is zero).
    if xlim is None:
        xlim = [np.inf, -np.inf]
        for data in data_list:
            if hasattr(data, 'hist_bins') and \
                    hasattr(data.hist_bins, '__call__'):
                xlim_data = data.hist_bins(channels=channels[0],
                                           nbins=1,
                                           scale=xscale)
                xlim[0] = xlim_data[0] if xlim_data[0] < xlim[0] else xlim[0]
                xlim[1] = xlim_data[1] if xlim_data[1] > xlim[1] else xlim[1]
    plt.xlim(xlim)
    if ylim is None:
        ylim = [np.inf, -np.inf]
        for data in data_list:
            if hasattr(data, 'hist_bins') and \
                    hasattr(data.hist_bins, '__call__'):
                ylim_data = data.hist_bins(channels=channels[1],
                                           nbins=1,
                                           scale=yscale)
                ylim[0] = ylim_data[0] if ylim_data[0] < ylim[0] else ylim[0]
                ylim[1] = ylim_data[1] if ylim_data[1] > ylim[1] else ylim[1]
    plt.ylim(ylim)

    # Title
    if title is not None:
        plt.title(title)

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()


Instruction:
Create a Python 3 function for
functioning to plot a 3D scatter plot from one or more Flow cytometry data objects or numpy arrays.

Response:
def scatter3d(data_list,
              channels=[0,1,2],
              xscale='logicle',
              yscale='logicle',
              zscale='logicle',
              xlabel=None,
              ylabel=None,
              zlabel=None,
              xlim=None,
              ylim=None,
              zlim=None,
              title=None,
              color=None,
              savefig=None,
              **kwargs):
    """
    Plot 3D scatter plot from one or more FCSData objects or numpy arrays.

    Parameters
    ----------
    data_list : array or FCSData or list of array or list of FCSData
        Flow cytometry data to plot.
    channels : list of int, list of str
        Three channels to use for the plot.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    xscale : str, optional
        Scale of the x axis, either ``linear``, ``log``, or ``logicle``.
    yscale : str, optional
        Scale of the y axis, either ``linear``, ``log``, or ``logicle``.
    zscale : str, optional
        Scale of the z axis, either ``linear``, ``log``, or ``logicle``.
    xlabel : str, optional
        Label to use on the x axis. If None, attempts to extract channel
        name from last data object.
    ylabel : str, optional
        Label to use on the y axis. If None, attempts to extract channel
        name from last data object.
    zlabel : str, optional
        Label to use on the z axis. If None, attempts to extract channel
        name from last data object.
    xlim : tuple, optional
        Limits for the x axis. If None, attempts to extract limits from the
        range of the last data object.
    ylim : tuple, optional
        Limits for the y axis. If None, attempts to extract limits from the
        range of the last data object.
    zlim : tuple, optional
        Limits for the z axis. If None, attempts to extract limits from the
        range of the last data object.
    title : str, optional
        Plot title.
    color : matplotlib color or list of matplotlib colors, optional
        Color for the scatter plot. It can be a list with the same length
        as `data_list`. If `color` is not specified, elements from
        `data_list` are plotted with colors taken from the module-level
        variable `cmap_default`.
    kwargs : dict, optional
        Additional parameters passed directly to matploblib's ``scatter``.

    Notes
    -----
    `scatter3d` uses matplotlib's ``scatter`` with a 3D projection.
    Additional keyword arguments provided to `scatter3d` are passed
    directly to ``scatter``.

    """
    # Check appropriate number of channels
    if len(channels) != 3:
        raise ValueError('three channels need to be specified')

    # Convert to list if necessary
    if not isinstance(data_list, list):
        data_list = [data_list]

    # Default colors
    if color is None:
        color = [cmap_default(i) for i in np.linspace(0, 1, len(data_list))]

    # Convert color to list, if necessary
    if not isinstance(color, list):
       color = [color]*len(data_list)

    # Get transformation functions for each axis
    # Explicit rescaling is required for non-linear scales because mplot3d does
    # not natively support anything but linear scale.
    if xscale == 'linear':
        xscale_transform = lambda x: x
    elif xscale == 'log':
        xscale_transform = np.log10
    elif xscale == 'logicle':
        t = _LogicleTransform(data=data_list, channel=channels[0])
        it = _InterpolatedInverseTransform(t, 0, t.M)
        xscale_transform = it.transform_non_affine
    else:
        raise ValueError('scale {} not supported'.format(xscale))

    if yscale == 'linear':
        yscale_transform = lambda x: x
    elif yscale == 'log':
        yscale_transform = np.log10
    elif yscale == 'logicle':
        t = _LogicleTransform(data=data_list, channel=channels[1])
        it = _InterpolatedInverseTransform(t, 0, t.M)
        yscale_transform = it.transform_non_affine
    else:
        raise ValueError('scale {} not supported'.format(yscale))

    if zscale == 'linear':
        zscale_transform = lambda x: x
    elif zscale == 'log':
        zscale_transform = np.log10
    elif zscale == 'logicle':
        t = _LogicleTransform(data=data_list, channel=channels[2])
        it = _InterpolatedInverseTransform(t, 0, t.M)
        zscale_transform = it.transform_non_affine
    else:
        raise ValueError('scale {} not supported'.format(zscale))

    # Make 3d axis if necessary
    ax_3d = plt.gca(projection='3d')

    # Iterate through data_list
    for i, data in enumerate(data_list):
        # Get channels to plot
        data_plot = data[:, channels]
        # Make scatter plot
        ax_3d.scatter(xscale_transform(data_plot[:, 0]),
                      yscale_transform(data_plot[:, 1]),
                      zscale_transform(data_plot[:, 2]),
                      marker='o',
                      alpha=0.1,
                      color=color[i],
                      **kwargs)

    # Remove tick labels
    ax_3d.xaxis.set_ticklabels([])
    ax_3d.yaxis.set_ticklabels([])
    ax_3d.zaxis.set_ticklabels([])

    # Set labels if specified, else try to extract channel names
    if xlabel is not None:
        ax_3d.set_xlabel(xlabel)
    elif hasattr(data_plot, 'channels'):
        ax_3d.set_xlabel(data_plot.channels[0])
    if ylabel is not None:
        ax_3d.set_ylabel(ylabel)
    elif hasattr(data_plot, 'channels'):
        ax_3d.set_ylabel(data_plot.channels[1])
    if zlabel is not None:
        ax_3d.set_zlabel(zlabel)
    elif hasattr(data_plot, 'channels'):
        ax_3d.set_zlabel(data_plot.channels[2])

    # Set plot limits if specified, else extract range from data_plot
    # ``.hist_bins`` with one bin works better for visualization that
    # ``.range``, because it deals with two issues. First, it automatically
    # deals with range values that are outside the domain of the current scaling
    # (e.g. when the lower range value is zero and the scaling is logarithmic).
    # Second, it takes into account events that are outside the limits specified
    # by .range (e.g. negative events will be shown with logicle scaling, even
    # when the lower range is zero).
    if xlim is None:
        xlim = np.array([np.inf, -np.inf])
        for data in data_list:
            if hasattr(data, 'hist_bins') and \
                    hasattr(data.hist_bins, '__call__'):
                xlim_data = data.hist_bins(channels=channels[0],
                                           nbins=1,
                                           scale=xscale)
                xlim[0] = xlim_data[0] if xlim_data[0] < xlim[0] else xlim[0]
                xlim[1] = xlim_data[1] if xlim_data[1] > xlim[1] else xlim[1]
        xlim = xscale_transform(xlim)
    ax_3d.set_xlim(xlim)

    if ylim is None:
        ylim = np.array([np.inf, -np.inf])
        for data in data_list:
            if hasattr(data, 'hist_bins') and \
                    hasattr(data.hist_bins, '__call__'):
                ylim_data = data.hist_bins(channels=channels[1],
                                           nbins=1,
                                           scale=yscale)
                ylim[0] = ylim_data[0] if ylim_data[0] < ylim[0] else ylim[0]
                ylim[1] = ylim_data[1] if ylim_data[1] > ylim[1] else ylim[1]
        ylim = yscale_transform(ylim)
    ax_3d.set_ylim(ylim)

    if zlim is None:
        zlim = np.array([np.inf, -np.inf])
        for data in data_list:
            if hasattr(data, 'hist_bins') and \
                    hasattr(data.hist_bins, '__call__'):
                zlim_data = data.hist_bins(channels=channels[2],
                                           nbins=1,
                                           scale=zscale)
                zlim[0] = zlim_data[0] if zlim_data[0] < zlim[0] else zlim[0]
                zlim[1] = zlim_data[1] if zlim_data[1] > zlim[1] else zlim[1]
        zlim = zscale_transform(zlim)
    ax_3d.set_zlim(zlim)

    # Title
    if title is not None:
        plt.title(title)

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()


Instruction:
Implement a Python 3 function for
making a combined density/histogram plot of a FCSData object. This function calls `hist1d` and `density2d` to plot a density diagram and a number of histograms in different subplots of the same plot using one single function call. Setting `density_channels` to None will not produce a density diagram, and setting `hist_channels` to None will not produce any histograms. Setting both to None will raise an error. Additional parameters can be provided to `density2d` and `hist1d` by using `density_params` and `hist_params`. If `gated_data` is provided, this function will plot the histograms corresponding to `gated_data` on top of `data`'s histograms, with some transparency on `data`. In addition, a legend will be added with the labels 'Ungated' and 'Gated'. If `gate_contour` is provided and it contains a valid list of 2D curves, these will be plotted on top of the density plot. Parameters ---------- data : FCSData object Flow cytometry data object to plot. gated_data : FCSData object, optional Flow cytometry data object. If `gated_data` is specified, the histograms of `data` are plotted with an alpha value of 0.5, and the histograms of `gated_data` are plotted on top of those with an alpha value of 1.0. gate_contour : list, optional List of Nx2 curves, representing a gate contour to be plotted in the density diagram. density_channels : list Two channels to use for the density plot. If `density_channels` is None, do not plot a density plot. density_params : dict, optional Parameters to pass to `density2d`. hist_channels : list Channels to use for each histogram. If `hist_channels` is None, do not plot histograms. hist_params : list, optional List of dictionaries with the parameters to pass to each call of `hist1d`. savefig : str, optional The name of the file to save the figure to. If None, do not save. Other parameters ---------------- figsize : tuple, optional Figure size. If None, calculate a default based on the number of subplots. Raises ------ ValueError If both `density_channels` and `hist_channels` are None.

Response:
def density_and_hist(data,
                     gated_data=None,
                     gate_contour=None,
                     density_channels=None,
                     density_params={},
                     hist_channels=None,
                     hist_params={},
                     figsize=None,
                     savefig=None):
    """
    Make a combined density/histogram plot of a FCSData object.

    This function calls `hist1d` and `density2d` to plot a density diagram
    and a number of histograms in different subplots of the same plot using
    one single function call. Setting `density_channels` to None will not
    produce a density diagram, and setting `hist_channels` to None will not
    produce any histograms. Setting both to None will raise an error.
    Additional parameters can be provided to `density2d` and `hist1d` by
    using `density_params` and `hist_params`.

    If `gated_data` is provided, this function will plot the histograms
    corresponding to `gated_data` on top of `data`'s histograms, with some
    transparency on `data`. In addition, a legend will be added with the
    labels 'Ungated' and 'Gated'. If `gate_contour` is provided and it
    contains a valid list of 2D curves, these will be plotted on top of the
    density plot.

    Parameters
    ----------
    data : FCSData object
        Flow cytometry data object to plot.
    gated_data : FCSData object, optional
        Flow cytometry data object. If `gated_data` is specified, the
        histograms of `data` are plotted with an alpha value of 0.5, and
        the histograms of `gated_data` are plotted on top of those with
        an alpha value of 1.0.
    gate_contour : list, optional
        List of Nx2 curves, representing a gate contour to be plotted in
        the density diagram.
    density_channels : list
        Two channels to use for the density plot. If `density_channels` is
        None, do not plot a density plot.
    density_params : dict, optional
        Parameters to pass to `density2d`.
    hist_channels : list
        Channels to use for each histogram. If `hist_channels` is None,
        do not plot histograms.
    hist_params : list, optional
        List of dictionaries with the parameters to pass to each call of
        `hist1d`.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    figsize : tuple, optional
        Figure size. If None, calculate a default based on the number of
        subplots.

    Raises
    ------
    ValueError
        If both `density_channels` and `hist_channels` are None.

    """
    # Check number of plots
    if density_channels is None and hist_channels is None:
        raise ValueError("density_channels and hist_channels cannot be both "
            "None")

    # Change hist_channels to iterable if necessary
    if not hasattr(hist_channels, "__iter__"):
        hist_channels = [hist_channels]
    if isinstance(hist_params, dict):
        hist_params = [hist_params]*len(hist_channels)

    plot_density = not(density_channels is None)
    n_plots = plot_density + len(hist_channels)

    # Calculate plot size if necessary
    if figsize is None:
        height = 0.315 + 2.935*n_plots
        figsize = (6, height)

    # Create plot
    plt.figure(figsize=figsize)

    # Density plot
    if plot_density:
        plt.subplot(n_plots, 1, 1)
        # Plot density diagram
        density2d(data, channels=density_channels, **density_params)
        # Plot gate contour
        if gate_contour is not None:
            for g in gate_contour:
                plt.plot(g[:,0], g[:,1], color='k', linewidth=1.25)
        # Add title
        if 'title' not in density_params:
            if gated_data is not None:
                ret = gated_data.shape[0] * 100. / data.shape[0]
                title = "{} ({:.1f}% retained)".format(str(data), ret)
            else:
                title = str(data)
            plt.title(title)

    # Colors
    n_colors = n_plots - 1
    colors = [cmap_default(i) for i in np.linspace(0, 1, n_colors)]
    # Histogram
    for i, hist_channel in enumerate(hist_channels):
        # Define subplot
        plt.subplot(n_plots, 1, plot_density + i + 1)
        # Default colors
        hist_params_i = hist_params[i].copy()
        if 'facecolor' not in hist_params_i:
            hist_params_i['facecolor'] = colors[i]
        # Plots
        if gated_data is not None:
            hist1d(data,
                   channel=hist_channel,
                   alpha=0.5,
                   **hist_params_i)
            hist1d(gated_data,
                   channel=hist_channel,
                   alpha=1.0,
                   **hist_params_i)
            plt.legend(['Ungated', 'Gated'], loc='best', fontsize='medium')
        else:
            hist1d(data, channel=hist_channel, **hist_params_i)

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()


Instruction:
Explain what the following Python 3 code does
def scatter3d_and_projections(data_list,
                              channels=[0,1,2],
                              xscale='logicle',
                              yscale='logicle',
                              zscale='logicle',
                              xlabel=None,
                              ylabel=None,
                              zlabel=None,
                              xlim=None,
                              ylim=None,
                              zlim=None,
                              color=None,
                              figsize=None,
                              savefig=None,
                              **kwargs):
    """
    Plot a 3D scatter plot and 2D projections from FCSData objects.

    `scatter3d_and_projections` creates a 3D scatter plot and three 2D
    projected scatter plots in four different axes for each FCSData object
    in `data_list`, in the same figure.

    Parameters
    ----------
    data_list : FCSData object, or list of FCSData objects
        Flow cytometry data to plot.
    channels : list of int, list of str
        Three channels to use for the plot.
    savefig : str, optional
        The name of the file to save the figure to. If None, do not save.

    Other parameters
    ----------------
    xscale : str, optional
        Scale of the x axis, either ``linear``, ``log``, or ``logicle``.
    yscale : str, optional
        Scale of the y axis, either ``linear``, ``log``, or ``logicle``.
    zscale : str, optional
        Scale of the z axis, either ``linear``, ``log``, or ``logicle``.
    xlabel : str, optional
        Label to use on the x axis. If None, attempts to extract channel
        name from last data object.
    ylabel : str, optional
        Label to use on the y axis. If None, attempts to extract channel
        name from last data object.
    zlabel : str, optional
        Label to use on the z axis. If None, attempts to extract channel
        name from last data object.
    xlim : tuple, optional
        Limits for the x axis. If None, attempts to extract limits from the
        range of the last data object.
    ylim : tuple, optional
        Limits for the y axis. If None, attempts to extract limits from the
        range of the last data object.
    zlim : tuple, optional
        Limits for the z axis. If None, attempts to extract limits from the
        range of the last data object.
    color : matplotlib color or list of matplotlib colors, optional
        Color for the scatter plot. It can be a list with the same length
        as `data_list`. If `color` is not specified, elements from
        `data_list` are plotted with colors taken from the module-level
        variable `cmap_default`.
    figsize : tuple, optional
        Figure size. If None, use matplotlib's default.
    kwargs : dict, optional
        Additional parameters passed directly to matploblib's ``scatter``.

    Notes
    -----
    `scatter3d_and_projections` uses matplotlib's ``scatter``, with the 3D
    scatter plot using a 3D projection. Additional keyword arguments
    provided to `scatter3d_and_projections` are passed directly to
    ``scatter``.

    """
    # Check appropriate number of channels
    if len(channels) != 3:
        raise ValueError('three channels need to be specified')

    # Create figure
    plt.figure(figsize=figsize)

    # Axis 1: channel 0 vs channel 2
    plt.subplot(221)
    scatter2d(data_list,
              channels=[channels[0], channels[2]],
              xscale=xscale,
              yscale=zscale,
              xlabel=xlabel,
              ylabel=zlabel,
              xlim=xlim,
              ylim=zlim,
              color=color,
              **kwargs)

    # Axis 2: 3d plot
    ax_3d = plt.gcf().add_subplot(222, projection='3d')
    scatter3d(data_list,
              channels=channels,
              xscale=xscale,
              yscale=yscale,
              zscale=zscale,
              xlabel=xlabel,
              ylabel=ylabel,
              zlabel=zlabel,
              xlim=xlim,
              ylim=ylim,
              zlim=zlim,
              color=color,
              **kwargs)

    # Axis 3: channel 0 vs channel 1
    plt.subplot(223)
    scatter2d(data_list,
              channels=[channels[0], channels[1]],
              xscale=xscale,
              yscale=yscale,
              xlabel=xlabel,
              ylabel=ylabel,
              xlim=xlim,
              ylim=ylim,
              color=color,
              **kwargs)

    # Axis 4: channel 2 vs channel 1
    plt.subplot(224)
    scatter2d(data_list,
              channels=[channels[2], channels[1]],
              xscale=zscale,
              yscale=yscale,
              xlabel=zlabel,
              ylabel=ylabel,
              xlim=zlim,
              ylim=ylim,
              color=color,
              **kwargs)

    # Save if necessary
    if savefig is not None:
        plt.tight_layout()
        plt.savefig(savefig, dpi=savefig_dpi)
        plt.close()

Response: This function creates a 3D scatter plot and 2D projections from FCSData objects.


Instruction:
Explain what the following Python 3 code does
def transform_non_affine(self, x, mask_out_of_range=True):
        # Mask out-of-range values
        if mask_out_of_range:
            x_masked = np.ma.masked_where((x < self._xmin) | (x > self._xmax),
                                          x)
        else:
            x_masked = x
        # Calculate s and return
        return np.interp(x_masked, self._x_range, self._s_range)

Response: Transform a Nx1 numpy array.


Instruction:
Implement a function in Python 3 to
apply transformation to a Nx1 numpy array.

Response:
def transform_non_affine(self, s):
        """
        Apply transformation to a Nx1 numpy array.

        Parameters
        ----------
        s : array
            Data to be transformed in display scale units.

        Return
        ------
        array or masked array
            Transformed data, in data value units.

        """
        T = self._T
        M = self._M
        W = self._W
        p = self._p
        # Calculate x
        return T * 10**(-(M-W)) * (10**(s-W) - (p**2)*10**(-(s-W)/p) + p**2 - 1)


Instruction:
Implement a Python 3 function for
setting parameters within this locator.

Response:
def set_params(self, subs=None, numticks=None):
        """
        Set parameters within this locator.

        Parameters
        ----------
        subs : array, optional
            Subtick values, as multiples of the main ticks.
        numticks : array, optional
            Number of ticks.

        """
        if numticks is not None:
            self.numticks = numticks
        if subs is not None:
            self._subs = subs


Instruction:
Write a Python 3 script to
return a set of tick values for a given logicle level.

Response:
def tick_values(self, vmin, vmax):
        """
        Get a set of tick values properly spaced for logicle axis.

        """
        # Extract base from transform object
        b = self._transform.base
        # The logicle domain is divided into two regions: A "linear" region,
        # which may include negative numbers, and a "logarithmic" region, which
        # only includes positive numbers. These two regions are separated by a
        # value t, given by the logicle equations. An illustration is given
        # below.
        #
        # -t ==0== t ========>
        #     lin       log
        #
        # vmin and vmax can be anywhere in this domain, meaning that both should
        # be greater than -t.
        #
        # The logarithmic region will only have major ticks at integral log
        # positions. The linear region will have a major tick at zero, and one
        # major tick at the largest absolute  integral log value in screen
        # inside this region. Subticks will be added at multiples of the
        # integral log positions.

        # If the linear range is too small, create new transformation object
        # with slightly wider linear range. Otherwise, the number of decades
        # below will be infinite
        if self._transform.W == 0 or \
                self._transform.M / self._transform.W > self.numticks:
            self._transform = _LogicleTransform(
                T=self._transform.T,
                M=self._transform.M,
                W=self._transform.M / self.numticks)
        # Calculate t
        t = - self._transform.transform_non_affine(0)

        # Swap vmin and vmax if necessary
        if vmax < vmin:
            vmin, vmax = vmax, vmin
        # Calculate minimum and maximum limits in scale units
        vmins = self._transform.inverted().transform_non_affine(vmin)
        vmaxs = self._transform.inverted().transform_non_affine(vmax)

        # Check whether linear or log regions are present
        has_linear = has_log = False
        if vmin <= t:
            has_linear = True
            if vmax > t:
                has_log = True
        else:
            has_log = True

        # Calculate number of ticks in linear and log regions
        # The number of ticks is distributed by the fraction that each region
        # occupies in scale units
        if has_linear:
            fraction_linear = (min(vmaxs, 2*self._transform.W) - vmins) / \
                (vmaxs - vmins)
            numticks_linear = np.round(self.numticks*fraction_linear)
        else:
            numticks_linear = 0
        if has_log:
            fraction_log = (vmaxs - max(vmins, 2*self._transform.W)) / \
                (vmaxs - vmins)
            numticks_log = np.round(self.numticks*fraction_log)
        else:
            numticks_log = 0

        # Calculate extended ranges and step size for tick location
        # Extended ranges take into account discretization.
        if has_log:
            # The logarithmic region's range will include from the decade
            # immediately below the lower end of the region to the decade
            # immediately above the upper end.
            # Note that this may extend the logarithmic region to the left.
            log_ext_range = [np.floor(np.log(max(vmin, t)) / np.log(b)),
                             np.ceil(np.log(vmax) / np.log(b))]
            # Since a major tick will be located at the lower end of the
            # extended range, make sure that it is not too close to zero.
            if vmin <= 0:
                zero_s = self._transform.inverted().\
                    transform_non_affine(0)
                min_tick_space = 1./self.numticks
                while True:
                    min_tick_s = self._transform.inverted().\
                        transform_non_affine(b**log_ext_range[0])
                    if (min_tick_s - zero_s)/(vmaxs - vmins) < min_tick_space \
                            and ((log_ext_range[0] + 1) < log_ext_range[1]):
                        log_ext_range[0] += 1
                    else:
                        break
            # Number of decades in the extended region
            log_decades = log_ext_range[1] - log_ext_range[0]
            # The step is at least one decade.
            if numticks_log > 1:
                log_step = max(np.floor(float(log_decades)/(numticks_log-1)), 1)
            else:
                log_step = 1
        else:
            # Linear region only
            linear_range = [vmin, vmax]
            # Initial step size will be one decade below the maximum whole
            # decade in the range
            linear_step = matplotlib.ticker.decade_down(
                linear_range[1] - linear_range[0], b) / b
            # Reduce the step size according to specified number of ticks
            while (linear_range[1] - linear_range[0])/linear_step > \
                    numticks_linear:
                linear_step *= b
            # Get extended range by discretizing the region limits
            vmin_ext = np.floor(linear_range[0]/linear_step)*linear_step
            vmax_ext = np.ceil(linear_range[1]/linear_step)*linear_step
            linear_range_ext = [vmin_ext, vmax_ext]

        # Calculate major tick positions
        major_ticklocs = []
        if has_log:
            # Logarithmic region present
            # If a linear region is present, add the negative of the lower limit
            # of the extended log region and zero. Then, add ticks for each
            # logarithmic step as calculated above.
            if has_linear:
                major_ticklocs.append(- b**log_ext_range[0])
                major_ticklocs.append(0)
            # Use nextafter to pick the next floating point number, and try to
            # include the upper limit in the generated range.
            major_ticklocs.extend(b ** (np.arange(
                log_ext_range[0],
                np.nextafter(log_ext_range[1], np.inf),
                log_step)))
        else:
            # Only linear region present
            # Draw ticks according to linear step calculated above.
            # Use nextafter to pick the next floating point number, and try to
            # include the upper limit in the generated range.
            major_ticklocs.extend(np.arange(
                linear_range_ext[0],
                np.nextafter(linear_range_ext[1], np.inf),
                linear_step))
        major_ticklocs = np.array(major_ticklocs)

        # Add subticks if requested
        subs = self._subs
        if (subs is not None) and (len(subs) > 1 or subs[0] != 1.0):
            ticklocs = []
            if has_log:
                # Subticks for each major tickloc present
                for major_tickloc in major_ticklocs:
                    ticklocs.extend(subs * major_tickloc)
                # Subticks from one decade below the lowest
                major_ticklocs_pos = major_ticklocs[major_ticklocs > 0]
                if len(major_ticklocs_pos):
                    tickloc_next_low = np.min(major_ticklocs_pos)/b
                    ticklocs.append(tickloc_next_low)
                    ticklocs.extend(subs * tickloc_next_low)
                # Subticks for the negative linear range
                if vmin < 0:
                    ticklocs.extend([(-ti) for ti in ticklocs if ti < -vmin ])
            else:
                ticklocs = list(major_ticklocs)
                # If zero is present, add ticks from a decade below the lowest
                if (vmin < 0) and (vmax > 0):
                    major_ticklocs_nonzero = major_ticklocs[
                        np.nonzero(major_ticklocs)]
                    tickloc_next_low = np.min(np.abs(major_ticklocs_nonzero))/b
                    ticklocs.append(tickloc_next_low)
                    ticklocs.extend(subs * tickloc_next_low)
                    ticklocs.append(-tickloc_next_low)
                    ticklocs.extend(subs * - tickloc_next_low)

        else:
            # Subticks not requested
            ticklocs = major_ticklocs

        return self.raise_if_exceeds(np.array(ticklocs))


Instruction:
Write a Python 3 function that can
try to choose the view limits intelligently.

Response:
def view_limits(self, vmin, vmax):
        """
        Try to choose the view limits intelligently.

        """
        b = self._transform.base
        if vmax < vmin:
            vmin, vmax = vmax, vmin

        if not matplotlib.ticker.is_decade(abs(vmin), b):
            if vmin < 0:
                vmin = -matplotlib.ticker.decade_up(-vmin, b)
            else:
                vmin = matplotlib.ticker.decade_down(vmin, b)
        if not matplotlib.ticker.is_decade(abs(vmax), b):
            if vmax < 0:
                vmax = -matplotlib.ticker.decade_down(-vmax, b)
            else:
                vmax = matplotlib.ticker.decade_up(vmax, b)

        if vmin == vmax:
            if vmin < 0:
                vmin = -matplotlib.ticker.decade_up(-vmin, b)
                vmax = -matplotlib.ticker.decade_down(-vmax, b)
            else:
                vmin = matplotlib.ticker.decade_down(vmin, b)
                vmax = matplotlib.ticker.decade_up(vmax, b)
        result = matplotlib.transforms.nonsingular(vmin, vmax)
        return result


Instruction:
Given the following Python 3 function, write the documentation
def get_transform(self):
        return _InterpolatedInverseTransform(transform=self._transform,
                                             smin=0,
                                             smax=self._transform._M)

Response: Get a new object to perform the scaling transformation.


Instruction:
Write a Python 3 script for
setting up the locators and formatters for the scale.

Response:
def set_default_locators_and_formatters(self, axis):
        """
        Set up the locators and formatters for the scale.

        Parameters
        ----------
        axis: matplotlib.axis
            Axis for which to set locators and formatters.

        """
        axis.set_major_locator(_LogicleLocator(self._transform))
        axis.set_minor_locator(_LogicleLocator(self._transform,
                                               subs=np.arange(2.0, 10.)))
        axis.set_major_formatter(matplotlib.ticker.LogFormatterSciNotation(
            labelOnlyBase=True))


Instruction:
Write a Python 3 function that can
return minimum and maximum bounds for the logicle axis.

Response:
def limit_range_for_scale(self, vmin, vmax, minpos):
        """
        Return minimum and maximum bounds for the logicle axis.

        Parameters
        ----------
        vmin : float
            Minimum data value.
        vmax : float
            Maximum data value.
        minpos : float
            Minimum positive value in the data. Ignored by this function.

        Return
        ------
        float
            Minimum axis bound.
        float
            Maximum axis bound.

        """
        vmin_bound = self._transform.transform_non_affine(0)
        vmax_bound = self._transform.transform_non_affine(self._transform.M)
        vmin = max(vmin, vmin_bound)
        vmax = min(vmax, vmax_bound)
        return vmin, vmax


Instruction:
How would you code a function in Python 3 to
calculate the mean of the events in a NxD flow cytometry data.

Response:
def mean(data, channels=None):
    """
    Calculate the mean of the events in an FCSData object.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : int or str or list of int or list of str, optional
        Channels on which to calculate the statistic. If None, use all
        channels.

    Returns
    -------
    float or numpy array
        The mean of the events in the specified channels of `data`.

    """
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.mean(data_stats, axis=0)


Instruction:
Can you generate the documentation for the following Python 3 function
def gmean(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return scipy.stats.gmean(data_stats, axis=0)

Response: Calculates the geometric mean of the events in a flow cytometry data object.


Instruction:
Make a summary of the following Python 3 code
def median(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.median(data_stats, axis=0)

Response: Calculate the median of the events in a flow cytometry data.


Instruction:
Make a summary of the following Python 3 code
def mode(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    # scipy.stats.mode returns two outputs, the first of which is an array
    # containing the modal values. This array has the same number of
    # dimensions as the input, and with only one element in the first
    # dimension. We extract this fist element to make it match the other
    # functions in this module.
    return scipy.stats.mode(data_stats, axis=0)[0][0]

Response: Calculate the mode of the events in a NxD flow cytometry data object.


Instruction:
Can you tell what is the following Python 3 function doing
def std(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.std(data_stats, axis=0)

Response: Calculate the standard deviation of the events in a NxD flow cytometry data.


Instruction:
Can you implement a function in Python 3 that
calculates the Coeff. of Variation of the events in a flow cytometry dataset.

Response:
def cv(data, channels=None):
    """
    Calculate the Coeff. of Variation of the events in an FCSData object.

    Parameters
    ----------
    data : FCSData or numpy array
        NxD flow cytometry data where N is the number of events and D is
        the number of parameters (aka channels).
    channels : int or str or list of int or list of str, optional
        Channels on which to calculate the statistic. If None, use all
        channels.

    Returns
    -------
    float or numpy array
        The Coefficient of Variation of the events in the specified
        channels of `data`.

    Notes
    -----
    The Coefficient of Variation (CV) of a dataset is defined as the
    standard deviation divided by the mean of such dataset.

    """
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.std(data_stats, axis=0) / np.mean(data_stats, axis=0)


Instruction:
Given the following Python 3 function, write the documentation
def gstd(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.exp(np.std(np.log(data_stats), axis=0))

Response: Calculates the geometric std. dev of the events in a flow cytometry data object.


Instruction:
Can you generate the documentation for the following Python 3 function
def gcv(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    return np.sqrt(np.exp(np.std(np.log(data_stats), axis=0)**2) - 1)

Response: Calculate the geometric CV of the events in a NxD flow cytometry data object.


Instruction:
Can you generate the documentation for the following Python 3 function
def iqr(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    q75, q25 = np.percentile(data_stats, [75 ,25], axis=0)
    return q75 - q25

Response: Calculate the Interquartile Range of the events in a flow cytometry dataset.


Instruction:
How would you explain what the following Python 3 function does
def rcv(data, channels=None):
    # Slice data to take statistics from
    if channels is None:
        data_stats = data
    else:
        data_stats = data[:, channels]

    # Calculate and return statistic
    q75, q25 = np.percentile(data_stats, [75 ,25], axis=0)
    return (q75 - q25)/np.median(data_stats, axis=0)

Response: Calculates the RCV of the events in a flow cytometry data object.


Instruction:
Explain what the following Python 3 code does
def dados_qrcode(cfe):
    infCFe = cfe.getroot().find('./infCFe')
    cnpjcpf_consumidor = infCFe.findtext('dest/CNPJ') or \
            infCFe.findtext('dest/CPF') or ''
    return '|'.join([
            infCFe.attrib['Id'][3:], # remove prefixo "CFe"
            '{}{}'.format(
                    infCFe.findtext('ide/dEmi'),
                    infCFe.findtext('ide/hEmi')),
            infCFe.findtext('total/vCFe'),
            cnpjcpf_consumidor,
            infCFe.findtext('ide/assinaturaQRCODE'),])

Response: Compila os dados que compila o QRCode do CF - e - SAT.


Instruction:
Given the following Python 3 function, write the documentation
def partes(self, num_partes=11):
        assert 44 % num_partes == 0, 'O numero de partes nao produz um '\
                'resultado inteiro (partes por 44 digitos): '\
                'num_partes=%s' % num_partes

        salto = 44 // num_partes
        return [self._campos[n:(n + salto)] for n in range(0, 44, salto)]

Response: Return a lista de strings contendo a chave do CF - e - SAT.


Instruction:
Can you tell what is the following Python 3 function doing
def validar_casas_decimais(valor, minimo=1, maximo=2):
    atributos = valor.as_tuple()
    if not (minimo <= abs(atributos.exponent) <= maximo):
        raise ValueError('Numero de casas decimais fora dos limites esperados '
                '(valor={!r}, minimo={!r}, maximo={!r}): {!r}'.format(
                        valor, minimo, maximo, atributos))

Response: Valida o número de casas decimais.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def uf_pelo_codigo(codigo_ibge):
    idx = [i for s, i, n, r in UNIDADES_FEDERACAO].index(codigo_ibge)
    return UNIDADES_FEDERACAO[idx][_UF_SIGLA]

Response: Retorna a UF para o código do IBGE informado.


Instruction:
Explain what the following Python 3 code does
def codigo_ibge_uf(sigla):
    idx = [s for s, i, n, r in UNIDADES_FEDERACAO].index(sigla)
    return UNIDADES_FEDERACAO[idx][_UF_CODIGO_IBGE]

Response: Retorna o código do IBGE para a UF informada.


Instruction:
How would you explain what the following Python 3 function does
def cnpj(numero):
    _digitos = [int(c) for c in numero if c.isdigit()]

    if len(_digitos) != 14 or len(numero) != 14:
        raise NumeroCNPJError('Nao possui 14 digitos: {!r}'.format(numero))

    if numero == numero[0] * 14:
        raise NumeroCNPJError('Todos os digitos iguais: {!r}'.format(numero))

    multiplicadores = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]

    soma1 = sum([_digitos[i] * multiplicadores[i+1] for i in range(12)])
    soma2 = sum([_digitos[i] * multiplicadores[i] for i in range(13)])
    digito1 = 11 - (soma1 % 11)
    digito2 = 11 - (soma2 % 11)

    if digito1 >= 10:
        digito1 = 0

    if digito2 >= 10:
        digito2 = 0

    if _digitos[12] != digito1 or _digitos[13] != digito2:
        raise NumeroCNPJError('Digitos verificadores invalidos: {!r}'.format(numero))

Response: Valida um número de CNPJ.


Instruction:
Make a summary of the following Python 3 code
def cpf(numero):
    _digitos = [int(c) for c in numero if c.isdigit()]

    if len(_digitos) != 11 or len(numero) != 11:
        raise NumeroCPFError('Nao possui 11 digitos: {!r}'.format(numero))

    if numero == numero[0] * 11:
        raise NumeroCPFError('Todos os digitos iguais: {!r}'.format(numero))

    multiplicadores = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2]

    soma1 = sum([_digitos[i] * multiplicadores[i+1] for i in range(9)])
    soma2 = sum([_digitos[i] * multiplicadores[i] for i in range(10)])
    digito1 = 11 - (soma1 % 11)
    digito2 = 11 - (soma2 % 11)

    if digito1 >= 10:
        digito1 = 0

    if digito2 >= 10:
        digito2 = 0

    if _digitos[9] != digito1 or _digitos[10] != digito2:
        raise NumeroCPFError('Digitos verificadores invalidos: {!r}'.format(numero))

Response: Valida um número de CPF.


Instruction:
Can you tell what is the following Python 3 function doing
def is_cpf(numero, estrito=False):
    try:
        cpf(digitos(numero) if not estrito else numero)
        return True
    except NumeroCPFError:
        pass
    return False

Response: A funziona se puede um numero CPF.


Instruction:
Can you tell what is the following Python 3 function doing
def as_cpf(numero):
    _num = digitos(numero)
    if is_cpf(_num):
        return '{}.{}.{}-{}'.format(_num[:3], _num[3:6], _num[6:9], _num[9:])
    return numero

Response: Formata um número de CPF retorna o argumento sem qualquer modificação.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def is_cnpjcpf(numero, estrito=False):
    _numero = digitos(numero) if not estrito else numero
    try:
        cnpj(_numero)
        return True
    except NumeroCNPJError:
        try:
            cpf(_numero)
            return True
        except NumeroCPFError:
            pass
    return False

Response: A funziona o numero de verifica se puede um CNPJ CPF.


Instruction:
Explain what the following Python 3 code does
def as_cnpjcpf(numero):
    if is_cnpj(numero):
        return as_cnpj(numero)
    elif is_cpf(numero):
        return as_cpf(numero)
    return numero

Response: Formata um número de CNPJ ou CPF.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def cep(numero):
    _digitos = digitos(numero)

    if len(_digitos) != 8 or len(numero) != 8:
        raise NumeroCEPError('CEP "%s" nao possui 8 digitos' % numero)

    elif _digitos[0] * 8 == _digitos:
        raise NumeroCEPError('CEP "%s" considerado invalido' % numero)

Response: Valida um número de CEP.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def is_cep(numero, estrito=False):
    try:
        cep(digitos(numero) if not estrito else numero)
        return True
    except NumeroCEPError:
        pass
    return False

Response: A funziona se puede um numero de verifica. Se verdadeiro para usar em testes condicionais.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def as_cep(numero):
    _numero = digitos(numero)
    if is_cep(_numero):
        return '{}-{}'.format(_numero[:5], _numero[5:])
    return numero

Response: Formata um número de CEP para um numero.