In [ ]:
import numpy as np
import pandas as pd

%matplotlib inline
import matplotlib.pyplot as plt

from crossing_tree import fbm, crossings, crossing_tree
from sklearn.preprocessing import StandardScaler

In [ ]:
random_state = np.random.RandomState(0x0BADC0D)

In [ ]:
gen_ = fbm(2**15+1, H=0.60, time=True)
# gen_ = fbm(2**22+1, H=0.95, time=True)
# gen_ = fbm(2**22+1, H=0.90, time=True)
gen_.initialize(random_state)

In [ ]:
T, X = gen_()

In [ ]:
print(np.std(np.diff(X)))
print(np.mean(np.abs(np.diff(X))))
print(np.median(np.abs(np.diff(X))))
print(np.percentile(np.abs(np.diff(X)), 95))
print(1.0 / np.sqrt(len(T) - 1))

In [ ]:
# scale_ = np.diff(X).std()
# scale_ = np.median(np.abs(np.diff(X)))
scale_ = np.mean(np.abs(np.diff(X))) * 1024 # * 16384

In [ ]:
# %%timeit -n 20
xi, ti = crossings(X, T, scale_, 0)
xi2, ti2 = crossings(X, T, scale_, 0.5)

print(xi.shape)
print(ti.shape)

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111)
ax.plot(T[:(1<<20)], X[:(1<<20)], "y", alpha=0.5)
ax.plot(ti[:11], xi[:11], "-k")
ax.plot(ti2[:11], xi2[:11], "-r")
ax.set_title("Scale %g"%(scale_,))
# scale_ *= 2
plt.show()

In [ ]:
from scipy.stats import ks_2samp

In [ ]:
# scale_ = np.median(np.abs(np.diff(X)))
scale_ = np.diff(X).std()
scale_ = 1.96 / np.sqrt( len(T)-1)
# scale_ = np.median(np.abs(np.diff(X)))
# scale_ = np.mean(np.abs(np.diff(X)))
for k in range(10):
    xi, ti = crossings(X, T, scale_, 0)
    xi2, ti2 = crossings(X, T, scale_, 0.25)
    scale_ *= 2

    dti_s = np.diff(ti)
    dti_s /= np.sqrt(np.mean(dti_s**2))
    
    dti2_s = np.diff(ti2)
    dti2_s /= np.sqrt(np.mean(dti2_s**2))

    fig = plt.figure(figsize=(12, 5))
    ax = fig.add_subplot(121)
    ax.hist(dti_s, bins=100, color="k", lw=0);
    ax = fig.add_subplot(122)
    ax.hist(dti2_s, bins=100, color="r", lw=0);
    plt.show()
    print(ks_2samp(dti_s, dti2_s))

Tree


In [ ]:
# scale_ = np.median(np.abs(np.diff(X)))
scale = np.diff(X).std()/2
# scale = 1.96 / np.sqrt( len(T)-1)
# scale = np.median(np.abs(np.diff(X)))
# scale = np.mean(np.abs(np.diff(X)))
origin = 0.

xi, ti, offspring, excursions, subcrossings, durations = crossing_tree(X, T, scale, origin)
print(len(offspring))

In [ ]:
def structure(offspring):
    iter_ = iter(offspring)
    try:
        value_ = next(iter_)
    except StopIteration:
        raise TypeError('reduce() of empty sequence')
    yield value_
    for index in iter_:
        value_ = value_[index]
        yield value_

list(structure(offspring))


In [ ]:
%load_ext cython

In [ ]:
%%cython
#-a
import numpy as _np
cimport numpy as np
cimport cython

from libc.math cimport isnan, fabs, floor, ceil, NAN

np.import_array()

ctypedef fused real:
    cython.floating

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
@cython.initializedcheck(False)
@cython.nonecheck(False)
def integer_xing(real[:] x, real[:] t, real scale, real origin):
    cdef np.intp_t n_samples = x.shape[0]
    cdef np.intp_t[::1] size = _np.empty(n_samples - 1, dtype=_np.int)
    cdef real[::1] first = _np.empty(n_samples - 1, dtype=_np.float)
    
    cdef np.intp_t i
    cdef real first_, last_, direction, prev_last = NAN
    cdef np.intp_t total = 0, size_
    with nogil:
        # Detect integer-level crossings, ignoring re-crossings of the same level
        for i in range(n_samples - 1):
            direction, size_ = 0.0, 0
            if x[i] < x[i+1]:
                first_, last_ = ceil((x[i] - origin) / scale), floor((x[i+1] - origin) / scale)
                direction = +1.0
            elif x[i] > x[i+1]:
                first_, last_ = floor((x[i] - origin) / scale), ceil((x[i+1] - origin) / scale)
                direction = -1.0
            if direction != 0.0:
                size_ = <int>fabs(last_ + direction - first_)
                if size_ > 0 and prev_last == first_:
                    first_ += direction
                    size_ -= 1
                if size_ > 0:
                    prev_last = last_
            first[i], size[i] = first_, size_
            total += size_

    cdef real[::1] xi = _np.empty(total, dtype=_np.float)
    cdef real[::1] ti = _np.empty(total, dtype=_np.float)

    cdef np.int_t k, j = 0
    cdef long double x_slope_, t_slope_, first_xi_, first_ti_
    with nogil:
        # Interpolate the crossing times and crossing levels
        for i in range(n_samples-1):
            size_ = size[i]
            if size_ > 0:
                x_slope_ = +scale if x[i+1] > x[i] else -scale
                t_slope_ = (t[i+1] - t[i]) / (x[i+1] - x[i])
                first_ = first[i] * scale + origin
                for k in range(size_):
                    xi[j] = first_ + x_slope_ * k
                    ti[j] = t[i] + t_slope_ * (xi[j] - x[i])
                    j += 1
## Marginally slower
#             size_ = size[i]
#             if size_ > 0:
#                 t_slope_ = (t[i+1] - t[i]) / (x[i+1] - x[i])
#                 xi[j] = first[i] * scale
#                 ti[j] = t[i] + t_slope_ * (xi[j] - x[i])
#                 j += 1
#             if size_ > 1:
#                 x_slope_ = +scale if x[i+1] > x[i] else -scale
#                 for k in range(size_ - 1):
#                     xi[j] = xi[j-1] + x_slope_
#                     ti[j] = ti[j-1] + t_slope_ * x_slope_
#                     j += 1
    return xi, ti