<commit_before>"""
Functions for gating flow cytometry data.

All gate functions are of the following form:

    gated_data = gate(data, channels, parameters)
    (gated_data, mask, contour, ...) = gate(data, channels, parameters,
                                            full_output=True)

where `data` is a NxD FCSData object or numpy array describing N cytometry
events observing D data dimensions, `channels` specifies the channels in
which to perform gating, and `parameters` are gate-specific parameters.
`gated_data` is the gated result, as an FCSData object or numpy array,
`mask` is a bool array specifying the gate mask, and `contour` is an
optional list of 2D numpy arrays containing the x-y coordinates of the
contour surrounding the gated region (useful for plotting).

"""

import numpy as np
import scipy.ndimage.filters
import matplotlib._cntr         # matplotlib contour, implemented in C
import collections

###
# namedtuple Gate Function Output Classes
###

StartEndGateOutput = collections.namedtuple(
    'StartEndGateOutput',
    ['gated_data', 'mask'])
HighLowGateOutput = collections.namedtuple(
    'HighLowGateOutput',
    ['gated_data', 'mask'])
EllipseGateOutput = collections.namedtuple(
    'EllipseGateOutput',
    ['gated_data', 'mask', 'contour'])
Density2dGateOutput = collections.namedtuple(
    'Density2dGateOutput',
    ['gated_data', 'mask', 'contour'])

###
# Gate Functions
###

def start_end(data, num_start = 250, num_end = 100, full_output=False):
    """
    Gate out first and last events.

    Gate out first and last events from `data`. This is a naive
    implementation which simply removes a set number of events from the
    beginning and end of `data` (as opposed to taking into account any
    optionally specified time information).

    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).
    num_start, num_end : int
        Number of events to gate out from beginning and end of `data`.
    full_output : bool
        Flag specifying to return ``namedtuple`` with additional outputs.

    Returns
    -------
    gated_data : FCSData or numpy array, if ``full_output==False``
        Gated flow cytometry data of the same format as `data`.
    namedtuple, if ``full_output==True``
        ``namedtuple`` containing the following fields in this order:
        gated_data : FCSData or numpy array
            Gated flow cytometry data of the same format as `data`.
        mask : numpy array of bool
            Boolean gate mask used to gate data such that
            `gated_data = data[mask]`.

    Raises
    ------
    ValueError
        If the number of events to discard is greater than the total
        number of events in `data`.

    """
    if data.shape[0] < (num_start + num_end):
        raise ValueError('Number of events to discard greater than total' + 
            ' number of events.')
    
    mask = np.ones(shape=data.shape[0],dtype=bool)
    mask[:num_start] = False
    mask[-num_end:] = False
    gated_data = data[mask]

    if full_output:
        return StartEndGateOutput(gated_data=gated_data, mask=mask)
    else:
        return gated_data

def high_low(data, channels=None, high=None, low=None, full_output=False):
    """
    Gate out high and low values across all specified channels.

    Gate out events in `data` with values in the specified channels which
    are larger than or equal to `high` or less than or equal to `low`.

    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 gating (the default is to include
        all channels).
    high, low : int, float
        High and low threshold values (the defaults are np.Inf and
        -np.Inf, respectively, which allows all finite data through the
        gate).
    full_output : bool
        Flag specifying to return ``namedtuple`` with additional outputs.

    Returns
    -------
    gated_data : FCSData or numpy array, if ``full_output==False``
        Gated flow cytometry data of the same format as `data`.
    namedtuple, if ``full_output==True``
        ``namedtuple`` containing the following fields in this order:
        gated_data : FCSData or numpy array
            Gated flow cytometry data of the same format as `data`.
        mask : numpy array of bool
            Boolean gate mask used to gate data such that
            `gated_data = data[mask]`.

    """
    # Extract channels in which to gate
    if channels is None:
        data_ch = data
    else:
        data_ch = data[:,channels]
        if data_ch.ndim == 1:<commit_msg>Small changes in gate.high_low() docstring.<commit_after>"""
Functions for gating flow cytometry data.

All gate functions are of the following form:

    gated_data = gate(data, channels, parameters)
    (gated_data, mask, contour, ...) = gate(data, channels, parameters,
                                            full_output=True)

where `data` is a NxD FCSData object or numpy array describing N cytometry
events observing D data dimensions, `channels` specifies the channels in
which to perform gating, and `parameters` are gate-specific parameters.
`gated_data` is the gated result, as an FCSData object or numpy array,
`mask` is a bool array specifying the gate mask, and `contour` is an
optional list of 2D numpy arrays containing the x-y coordinates of the
contour surrounding the gated region (useful for plotting).

"""

import numpy as np
import scipy.ndimage.filters
import matplotlib._cntr         # matplotlib contour, implemented in C
import collections

###
# namedtuple Gate Function Output Classes
###

StartEndGateOutput = collections.namedtuple(
    'StartEndGateOutput',
    ['gated_data', 'mask'])
HighLowGateOutput = collections.namedtuple(
    'HighLowGateOutput',
    ['gated_data', 'mask'])
EllipseGateOutput = collections.namedtuple(
    'EllipseGateOutput',
    ['gated_data', 'mask', 'contour'])
Density2dGateOutput = collections.namedtuple(
    'Density2dGateOutput',
    ['gated_data', 'mask', 'contour'])

###
# Gate Functions
###

def start_end(data, num_start = 250, num_end = 100, full_output=False):
    """
    Gate out first and last events.

    Gate out first and last events from `data`. This is a naive
    implementation which simply removes a set number of events from the
    beginning and end of `data` (as opposed to taking into account any
    optionally specified time information).

    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).
    num_start, num_end : int
        Number of events to gate out from beginning and end of `data`.
    full_output : bool
        Flag specifying to return ``namedtuple`` with additional outputs.

    Returns
    -------
    gated_data : FCSData or numpy array, if ``full_output==False``
        Gated flow cytometry data of the same format as `data`.
    namedtuple, if ``full_output==True``
        ``namedtuple`` containing the following fields in this order:
        gated_data : FCSData or numpy array
            Gated flow cytometry data of the same format as `data`.
        mask : numpy array of bool
            Boolean gate mask used to gate data such that
            `gated_data = data[mask]`.

    Raises
    ------
    ValueError
        If the number of events to discard is greater than the total
        number of events in `data`.

    """
    if data.shape[0] < (num_start + num_end):
        raise ValueError('Number of events to discard greater than total' + 
            ' number of events.')
    
    mask = np.ones(shape=data.shape[0],dtype=bool)
    mask[:num_start] = False
    mask[-num_end:] = False
    gated_data = data[mask]

    if full_output:
        return StartEndGateOutput(gated_data=gated_data, mask=mask)
    else:
        return gated_data

def high_low(data, channels=None, high=None, low=None, full_output=False):
    """
    Gate out high and low values across all specified channels.

    Gate out events in `data` with values in the specified channels which
    are larger than or equal to `high` or less than or equal to `low`.

    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 gating. If None, use all channels.
    high, low : int, float
        High and low threshold values. If None, `high` and `low` will be
        taken from ``data.channel_info`` if available, otherwise
        ``np.Inf`` and ``-np.Inf`` will be used.
    full_output : bool
        Flag specifying to return ``namedtuple`` with additional outputs.

    Returns
    -------
    gated_data : FCSData or numpy array, if ``full_output==False``
        Gated flow cytometry data of the same format as `data`.
    namedtuple, if ``full_output==True``
        ``namedtuple`` containing the following fields in this order:
        gated_data : FCSData or numpy array
            Gated flow cytometry data of the same format as `data`.
        mask : numpy array of bool
            Boolean gate mask used to gate data such that
            `gated_data = data[mask]`.

    """
    # Extract channels in which to gate
    if channels is None:
        data_ch = data
    else:
        data_ch = data[:,channels]
        if data_ch.ndim == 1:
{'fraction_non_alphanumeric': 0.08320524643918434, 'fraction_numerical': 0.002459268367660621, 'mean_word_length': 2.748079877112135, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1392548', 'n_tokens_mistral': 2704, 'n_tokens_neox': 2571, 'n_words': 1131}