def autorange(t, sig, gwin=<NUM_LIT:7>, swin=None, win=<NUM_LIT:30>,<EOL>on_mult=(<NUM_LIT>, <NUM_LIT:1.>), off_mult=(<NUM_LIT:1.>, <NUM_LIT>),<EOL>nbin=<NUM_LIT:10>, transform='<STR_LIT>', thresh=None):
failed = []<EOL>if swin is not None:<EOL><INDENT>sigs = fastsmooth(sig, swin)<EOL><DEDENT>else:<EOL><INDENT>sigs = sig<EOL><DEDENT>if transform == '<STR_LIT>':<EOL><INDENT>tsigs = np.log10(sigs)<EOL><DEDENT>else:<EOL><INDENT>tsigs = sigs<EOL><DEDENT>if thresh is None:<EOL><INDENT>bins = <NUM_LIT:50><EOL>kde_x = np.linspace(tsigs.min(), tsigs.max(), bins)<EOL>kde = gaussian_kde(tsigs)<EOL>yd = kde.pdf(kde_x)<EOL>mins = findmins(kde_x, yd)  <EOL>if len(mins) > <NUM_LIT:0>:<EOL><INDENT>bkg = tsigs < (mins[<NUM_LIT:0>])  <EOL><DEDENT>else:<EOL><INDENT>bkg = np.ones(tsigs.size, dtype=bool)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>bkg = tsigs < thresh<EOL><DEDENT>fbkg = bkg<EOL>fsig = ~bkg<EOL>zeros = bool_2_indices(fsig)<EOL>g = abs(fastgrad(sigs, gwin))  <EOL>if zeros is not None:<EOL><INDENT>zeros = zeros.flatten()<EOL>for z in zeros:  <EOL><INDENT>if z - win < <NUM_LIT:0>:<EOL><INDENT>lo = gwin // <NUM_LIT:2><EOL>hi = int(z + win)<EOL><DEDENT>elif z + win > (len(sig) - gwin // <NUM_LIT:2>):<EOL><INDENT>lo = int(z - win)<EOL>hi = len(sig) - gwin // <NUM_LIT:2><EOL><DEDENT>else:<EOL><INDENT>lo = int(z - win)<EOL>hi = int(z + win)<EOL><DEDENT>xs = t[lo:hi]<EOL>ys = g[lo:hi]<EOL>mid = (hi + lo) // <NUM_LIT:2><EOL>tp = sigs[mid + <NUM_LIT:3>] > sigs[mid - <NUM_LIT:3>]  <EOL>c = t[z]  <EOL>width = (t[<NUM_LIT:1>] - t[<NUM_LIT:0>]) * <NUM_LIT:2><EOL>try:<EOL><INDENT>pg, _ = curve_fit(gauss, xs, ys,<EOL>p0=(np.nanmax(ys),<EOL>c,<EOL>width),<EOL>sigma=(xs - c)**<NUM_LIT:2> + <NUM_LIT>)<EOL>fwhm = abs(<NUM_LIT:2> * pg[-<NUM_LIT:1>] * np.sqrt(<NUM_LIT:2> * np.log(<NUM_LIT:2>)))<EOL>if tp:<EOL><INDENT>lim = np.array([-fwhm, fwhm]) * on_mult + pg[<NUM_LIT:1>]<EOL><DEDENT>else:<EOL><INDENT>lim = np.array([-fwhm, fwhm]) * off_mult + pg[<NUM_LIT:1>]<EOL><DEDENT>fbkg[(t > lim[<NUM_LIT:0>]) & (t < lim[<NUM_LIT:1>])] = False<EOL>fsig[(t > lim[<NUM_LIT:0>]) & (t < lim[<NUM_LIT:1>])] = False<EOL><DEDENT>except RuntimeError:<EOL><INDENT>failed.append([c, tp])<EOL>pass<EOL><DEDENT><DEDENT><DEDENT>ftrn = ~fbkg & ~fsig<EOL>if len(failed) > <NUM_LIT:0>:<EOL><INDENT>trns = t[bool_2_indices(ftrn)]<EOL>tr_mean = (trns[:, <NUM_LIT:1>] - trns[:, <NUM_LIT:0>]).mean() / <NUM_LIT:2><EOL>for f, tp in failed:<EOL><INDENT>if tp:<EOL><INDENT>ind = (t >= f - tr_mean *<EOL>on_mult[<NUM_LIT:0>]) & (t <= f + tr_mean * on_mult[<NUM_LIT:0>])<EOL><DEDENT>else:<EOL><INDENT>ind = (t >= f - tr_mean *<EOL>off_mult[<NUM_LIT:0>]) & (t <= f + tr_mean * off_mult[<NUM_LIT:0>])<EOL><DEDENT>fsig[ind] = False<EOL>fbkg[ind] = False<EOL>ftrn[ind] = False<EOL><DEDENT><DEDENT>return fbkg, fsig, ftrn, [f[<NUM_LIT:0>] for f in failed]<EOL>
Automatically separates signal and background in an on/off data stream.

**Step 1: Thresholding.**
The background signal is determined using a gaussian kernel density
estimator (kde) of all the data. Under normal circumstances, this
kde should find two distinct data distributions, corresponding to
'signal' and 'background'. The minima between these two distributions
is taken as a rough threshold to identify signal and background
regions. Any point where the trace crosses this thrshold is identified
as a 'transition'.

**Step 2: Transition Removal.**
The width of the transition regions between signal and background are
then determined, and the transitions are excluded from analysis. The
width of the transitions is determined by fitting a gaussian to the
smoothed first derivative of the analyte trace, and determining its
width at a point where the gaussian intensity is at at `conf` time the
gaussian maximum. These gaussians are fit to subsets of the data
centered around the transitions regions determined in Step 1, +/- `win`
data points. The peak is further isolated by finding the minima and
maxima of a second derivative within this window, and the gaussian is
fit to the isolated peak.

Parameters
----------
t : array-like
    Independent variable (usually time).
sig : array-like
    Dependent signal, with distinctive 'on' and 'off' regions.
gwin : int
    The window used for calculating first derivative.
    Defaults to 7.
swin : int
    The window used for signal smoothing. If None, ``gwin // 2``.
win : int
    The width (c +/- win) of the transition data subsets.
    Defaults to 20.
on_mult and off_mult : tuple, len=2
    Control the width of the excluded transition regions, which is defined
    relative to the peak full-width-half-maximum (FWHM) of the transition
    gradient. The region n * FHWM below the transition, and m * FWHM above
    the tranision will be excluded, where (n, m) are specified in `on_mult`
    and `off_mult`.
    `on_mult` and `off_mult` apply to the off-on and on-off transitions,
    respectively.
    Defaults to (1.5, 1) and (1, 1.5).
transform : str
    How to transform the data. Default is 'log'.

Returns
-------
fbkg, fsig, ftrn, failed : tuple
    where fbkg, fsig and ftrn are boolean arrays the same length as sig,
    that are True where sig is background, signal and transition, respecively.
    failed contains a list of transition positions where gaussian fitting
    has failed.