You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.8 KiB
86 lines
2.8 KiB
# Anything vaguely portable from the ipython notebook is here in plaintext
|
|
import pandas
|
|
import stumpy
|
|
import numpy
|
|
import matplotlib.pyplot as plot
|
|
import matplotlib.dates as dates
|
|
from matplotlib.patches import Rectangle
|
|
import datetime as dt
|
|
|
|
## Process wrapper, time reporting
|
|
from functools import wraps
|
|
import time
|
|
def timeit(fn):
|
|
def timed(*args, **kw):
|
|
print (f'>>> {fn.__name__} >>>')
|
|
|
|
ts = time.time()
|
|
result = fn(*args, **kw)
|
|
te = time.time()
|
|
|
|
print (f'<<< {fn.__name__} <<< {(te-ts):.3f}s')
|
|
return result
|
|
return timed
|
|
|
|
@timeit
|
|
@wraps(stumpy.stump)
|
|
def timed_stump(dataset, w):
|
|
l = len(dataset)
|
|
ws = l - w + 1
|
|
print(f'Processing a matrix profile over {ws} windows...')
|
|
result = stumpy.stump(dataset, w)
|
|
return result
|
|
|
|
# Basic feature extraction
|
|
def threshold_extraction(op, cmp, profile, motif_order, window_width, threshold):
|
|
assert(0 < threshold < 1.0)
|
|
closest = profile[motif_order[0], 0]
|
|
cutoff = op(closest, (closest * threshold))
|
|
rv = []
|
|
|
|
for obs in motif_order:
|
|
if cmp(profile[obs,0], cutoff):
|
|
if not (any(map(lambda i: abs(i - obs) < window_width, rv))):
|
|
rv.append(obs)
|
|
else:
|
|
# If two motifs overlap it's possible the window is too small?
|
|
# Further criteria needed for that...
|
|
pass
|
|
else:
|
|
break
|
|
return rv
|
|
|
|
def get_motifs(profile, motif_order, window_width, threshold):
|
|
return threshold_extraction(lambda a, b: a + b
|
|
,lambda a, b: a < b
|
|
,profile
|
|
,motif_order
|
|
,window_width
|
|
,threshold)
|
|
|
|
def get_discords(profile, motif_order, window_width, threshold):
|
|
return threshold_extraction(lambda a, b: a - b
|
|
,lambda a, b: a > b
|
|
,profile
|
|
,numpy.flip(motif_order)
|
|
,window_width
|
|
,threshold)
|
|
|
|
def mark_discovered(motif_list, data_fig, profile_fig, window_width, fig_height):
|
|
for motif in motif_list:
|
|
rect = Rectangle((motif, 0), window_width, fig_height, facecolor='lightgrey')
|
|
data_fig.add_patch(rect)
|
|
profile_fig.axvline(x=motif, linestyle='dashed')
|
|
|
|
# Basic helper functions
|
|
def plot_matrix_profile(plot_, profile):
|
|
plot_.set_xlabel('Time', fontsize='15')
|
|
plot_.set_ylabel('Distance', fontsize='15')
|
|
plot_.plot(profile[:, 0])
|
|
|
|
from string import capwords
|
|
plot.style.use("data/stumpy.mplstyle")
|
|
def plot_pandas_import (plot_, data, axis_name):
|
|
plot_.set_ylabel(capwords(axis_name), fontsize='15')
|
|
plot_.plot(data[axis_name].values)
|