def _detsat_one(filename, ext, sigma=2.0, low_thresh=0.1, h_thresh=0.5,
                small_edge=60, line_len=200, line_gap=75,
                percentile=(4.5, 93.0), buf=200, plot=False, verbose=False):
    """Called by :func:`detsat`."""
    if verbose:
        t_beg = time.time()

    fname = '{0}[{1}]'.format(filename, ext)

    # check extension
    if ext not in (1, 4, 'SCI', ('SCI', 1), ('SCI', 2)):
        warnings.warn('{0} is not a valid science extension for '
                      'ACS/WFC'.format(ext), AstropyUserWarning)

    # get the data
    image = fits.getdata(filename, ext)
    # image = im.astype('float64')

    # rescale the image
    p1, p2 = np.percentile(image, percentile)

    # there should always be some counts in the image, anything lower should
    # be set to one. Makes things nicer for finding edges.
    if p1 < 0:
        p1 = 0.0

    if verbose:
        print('Rescale intensity percentiles: {0}, {1}'.format(p1, p2))

    image = exposure.rescale_intensity(image, in_range=(p1, p2))

    # get the edges
    immax = np.max(image)
    edge = canny(image, sigma=sigma,
                 low_threshold=immax * low_thresh,
                 high_threshold=immax * h_thresh)

    # clean up the small objects, will make less noise
    morph.remove_small_objects(edge, min_size=small_edge, connectivity=8,
                               in_place=True)

    # create an array of angles from 0 to 180, exactly 0 will get bad columns
    # but it is unlikely that a satellite will be exactly at 0 degrees, so
    # don't bother checking.
    # then, convert to radians.
    angle = np.radians(np.arange(2, 178, 0.5, dtype=float))

    # perform Hough Transform to detect straight lines.
    # only do if plotting to visualize the image in hough space.
    # otherwise just preform a Probabilistic Hough Transform.
    if plot and plt is not None:
        h, theta, d = transform.hough_line(edge, theta=angle)
        plt.ion()

    # perform Probabilistic Hough Transformation to get line segments.
    # NOTE: Results are slightly different from run to run!
    result = transform.probabilistic_hough_line(
        edge, threshold=210, line_length=line_len,
        line_gap=line_gap, theta=angle)
    result = np.asarray(result)
    n_result = len(result)

    # initially assume there is no satellite
    satellite = False

    # only continue if there was more than one point (at least a line)
    # returned from the PHT
    if n_result > 1:
        if verbose:
            print('Length of PHT result: {0}'.format(n_result))

        # create lists for X and Y positions of lines and build points
        x0 = result[:, 0, 0]
        y0 = result[:, 0, 1]
        x1 = result[:, 1, 0]
        y1 = result[:, 1, 1]

        # set some boundries
        ymax, xmax = image.shape
        topx = xmax - buf
        topy = ymax - buf

        if verbose:
            print('min(x0)={0:4d}, min(x1)={1:4d}, min(y0)={2:4d}, '
                  'min(y1)={3:4d}'.format(min(x0), min(x1), min(y0), min(y1)))
            print('max(x0)={0:4d}, max(x1)={1:4d}, max(y0)={2:4d}, '
                  'max(y1)={3:4d}'.format(max(x0), max(x1), max(y0), max(y1)))
            print('buf={0}'.format(buf))
            print('topx={0}, topy={1}'.format(topx, topy))

        # set up trail angle "tracking" arrays.
        # find the angle of each segment and filter things out.
        # TODO: this may be wrong. Try using arctan2.
        trail_angle = np.degrees(np.arctan((y1 - y0) / (x1 - x0)))
        # round to the nearest 5 degrees, trail should not be that curved
        round_angle = (5 * np.round(trail_angle * 0.2)).astype(int)

        # take out 90 degree things
        mask = round_angle % 90 != 0

        if not np.any(mask):
            if verbose:
                print('No round_angle found')
            return np.empty(0)

        round_angle = round_angle[mask]
        trail_angle = trail_angle[mask]
        result = result[mask]

        ang, num = stats.mode(round_angle)

        # do the filtering
        truth = round_angle == ang[0]

        if verbose:
            print('trail_angle: {0}'.format(trail_angle))
            print('round_angle: {0}'.format(round_angle))
            print('mode(round_angle): {0}'.format(ang[0]))

        # filter out the outliers
        trail_angle = trail_angle[truth]
        result = result[truth]
        n_result = len(result)

        if verbose:
            print('Filtered trail_angle: {0}'.format(trail_angle))

        if n_result < 1:
            return np.empty(0)

        # if there is an unreasonable amount of points, it picked up garbage
        elif n_result > 300:
            warnings.warn(
                'Way too many segments results to be correct ({0}). '
                'Rejecting detection on {1}.'.format(n_result, fname),
                AstropyUserWarning)
            return np.empty(0)

        # remake the point lists with things taken out
        x0 = result[:, 0, 0]
        y0 = result[:, 0, 1]
        x1 = result[:, 1, 0]
        y1 = result[:, 1, 1]

        min_x0 = min(x0)
        min_y0 = min(y0)
        min_x1 = min(x1)
        min_y1 = min(y1)

        max_x0 = max(x0)
        max_y0 = max(y0)
        max_x1 = max(x1)
        max_y1 = max(y1)

        mean_angle = np.mean(trail_angle)

        # make decisions on where the trail went and determine if a trail
        # traversed the image
        # top to bottom
        if (((min_y0 < buf) or (min_y1 < buf)) and
                ((max_y0 > topy) or (max_y1 > topy))):
            satellite = True
            if verbose:
                print('Trail Direction: Top to Bottom')

        # right to left
        elif (((min_x0 < buf) or (min_x1 < buf)) and
              ((max_x0 > topx) or (max_x1 > topx))):
            satellite = True
            if verbose:
                print('Trail Direction: Right to Left')

        # bottom to left
        elif (((min_x0 < buf) or (min_x1 < buf)) and
              ((min_y0 < buf) or (min_y1 < buf)) and
              (-1 > mean_angle > -89)):
            satellite = True
            if verbose:
                print('Trail Direction: Bottom to Left')

        # top to left
        elif (((min_x0 < buf) or (min_x1 < buf)) and
              ((max_y0 > topy) or (max_y1 > topy)) and
              (89 > mean_angle > 1)):
            satellite = True
            if verbose:
                print('Trail Direction: Top to Left')

        # top to right
        elif (((max_x0 > topx) or (max_x1 > topx)) and
              ((max_y0 > topy) or (max_y1 > topy)) and
              (-1 > mean_angle > -89)):
            satellite = True
            if verbose:
                print('Trail Direction: Top to Right')

        # bottom to right
        elif (((max_x0 > topx) or (max_x1 > topx)) and
              ((min_y0 < buf) or (min_y1 < buf)) and
              (89 > mean_angle > 1)):
            satellite = True
            if verbose:
                print('Trail Direction: Bottom to Right')

    if satellite:
        if verbose:
            print('{0} trail segment(s) detected'.format(n_result))
            print('Trail angle list (not returned): ')
            print(trail_angle)
            print('End point list:')
            for i, ((px0, py0), (px1, py1)) in enumerate(result, 1):
                print('{0:5d}. ({1:4d}, {2:4d}), ({3:4d}, {4:4d})'.format(
                    i, px0, py0, px1, py1))

        if plot and plt is not None:
            mean = np.median(image)
            stddev = image.std()
            lower = mean - stddev
            upper = mean + stddev

            fig1, ax1 = plt.subplots()
            ax1.imshow(edge, cmap=plt.cm.gray)
            ax1.set_title('Edge image for {0}'.format(fname))

            for (px0, py0), (px1, py1) in result:  # Draw trails
                ax1.plot((px0, px1), (py0, py1), scalex=False, scaley=False)

            fig2, ax2 = plt.subplots()
            ax2.imshow(
                np.log(1 + h),
                extent=(np.rad2deg(theta[-1]), np.rad2deg(theta[0]),
                        d[-1], d[0]), aspect=0.02)
            ax2.set_title('Hough Transform')
            ax2.set_xlabel('Angles (degrees)')
            ax2.set_ylabel('Distance from Origin (pixels)')

            fig3, ax3 = plt.subplots()
            ax3.imshow(image, vmin=lower, vmax=upper, cmap=plt.cm.gray)
            ax3.set_title(fname)

            for (px0, py0), (px1, py1) in result:  # Draw trails
                ax3.plot((px0, px1), (py0, py1), scalex=False, scaley=False)

            plt.draw()

    else:  # length of result was too small
        result = np.empty(0)

        if verbose:
            print('No trail detected; found {0} segments'.format(n_result))

        if plot and plt is not None:
            fig1, ax1 = plt.subplots()
            ax1.imshow(edge, cmap=plt.cm.gray)
            ax1.set_title(fname)

            # Draw trails
            for (px0, py0), (px1, py1) in result:
                ax1.plot((px0, px1), (py0, py1), scalex=False, scaley=False)

    if verbose:
        t_end = time.time()
        print('Run time: {0} s'.format(t_end - t_beg))

    return result