<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def otsu3(data, min_threshold=None, max_threshold=None,bins=128):
 """Compute a threshold using a 3-category Otsu-like method data - an array of intensity values between zero and one min_threshold - only consider thresholds above this minimum value max_threshold - only consider thresholds below this maximum value bins - we bin the data into this many equally-spaced bins, then pick the bin index that optimizes the metric We find the maximum weighted variance, breaking the histogram into three pieces. Returns the lower and upper thresholds """

    assert min_threshold is None or max_threshold is None or min_threshold < max_threshold
    
    #
    # Compute the running variance and reverse running variance.
    # 
    data = np.atleast_1d(data)
    data = data[~ np.isnan(data)]
    data.sort()
    if len(data) == 0:
        return 0
    var = running_variance(data)
    rvar = np.flipud(running_variance(np.flipud(data)))
    if bins > len(data):
        bins = len(data)
    bin_len = int(len(data)//bins) 
    thresholds = data[0:len(data):bin_len]
    score_low = (var[0:len(data):bin_len] * 
                 np.arange(0,len(data),bin_len))
    score_high = (rvar[0:len(data):bin_len] *
                  (len(data) - np.arange(0,len(data),bin_len)))
    #
    # Compute the middles
    #
    cs = data.cumsum()
    cs2 = (data**2).cumsum()
    i,j = np.mgrid[0:score_low.shape[0],0:score_high.shape[0]]*bin_len
    diff = (j-i).astype(float)
    w = diff
    mean = (cs[j] - cs[i]) / diff
    mean2 = (cs2[j] - cs2[i]) / diff
    score_middle = w * (mean2 - mean**2)
    score_middle[i >= j] = np.Inf
    score = score_low[i*bins//len(data)] + score_middle + score_high[j*bins//len(data)]
    best_score = np.min(score)
    best_i_j = np.argwhere(score==best_score)
    return (thresholds[best_i_j[0,0]],thresholds[best_i_j[0,1]])