def tops_from_loglike(a, offset=0, null=None):
    """
    Take a log-like stream of numbers or strings, and return two arrays:
    one of the tops (changes), and one of the values from the stream.

    Args:
        loglike (array-like): The input stream of loglike data.
        offset (int): Offset (down) from top at which to get lithology,
            to be sure of getting 'clean' pixels.

    Returns:
        ndarray: Two arrays, tops and values.
    """
    a = np.copy(a)

    try:
        contains_nans = np.isnan(a).any()
    except:
        contains_nans = False

    if contains_nans:
        # Find a null value that's not in the log, and apply it if possible.
        _null = null or -1
        while _null in a:
            _null -= 1

        try:
            a[np.isnan(a)] = _null
            transformed = True
        except:
            transformed = False

    edges = a[1:] == a[:-1]
    edges = np.append(True, edges)

    tops = np.where(~edges)[0]
    tops = np.append(0, tops)

    values = a[tops + offset]

    if contains_nans and transformed:
        values[values == _null] = np.nan

    return tops, values
Take a log-like stream of numbers or strings, and return two arrays:
    one of the tops (changes), and one of the values from the stream.

    Args:
        loglike (array-like): The input stream of loglike data.
        offset (int): Offset (down) from top at which to get lithology,
            to be sure of getting 'clean' pixels.

    Returns:
        ndarray: Two arrays, tops and values.