diff options
author | jfalkenhagen <jfalkenhagen@uos.de> | 2020-07-02 13:21:44 +0200 |
---|---|---|
committer | jfalkenhagen <jfalkenhagen@uos.de> | 2020-07-02 13:21:44 +0200 |
commit | 8aedd0a2ec227b3bc0233ac136d46ff55c8e6af7 (patch) | |
tree | ade819bd444fc867f700909cf0d4786ca8f024d2 | |
parent | 1d2cf70216e3faf7b82d3b96df4bc3ad7cbca291 (diff) |
Initial commit ProofofConcept-WIP tool
-rw-r--r-- | bin/Proof_Of_Concept_PELT.py | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/bin/Proof_Of_Concept_PELT.py b/bin/Proof_Of_Concept_PELT.py new file mode 100644 index 0000000..643a368 --- /dev/null +++ b/bin/Proof_Of_Concept_PELT.py @@ -0,0 +1,297 @@ +def plot_data_from_json(filename, trace_num, xaxis, yaxis): + import matplotlib.pyplot as plt + import json + with open(filename, 'r') as f: + tx_data = json.load(f) + print(tx_data[trace_num]['parameter']) + plt.plot(tx_data[trace_num]['offline'][0]['uW']) + plt.xlabel(xaxis) + plt.ylabel(yaxis) + plt.show() + + +def plot_data_vs_mean(signal, xaxis, yaxis): + import matplotlib.pyplot as plt + from statistics import mean + plt.plot(signal) + average = mean(signal) + plt.hlines(average, 0, len(signal)) + plt.xlabel(xaxis) + plt.ylabel(yaxis) + plt.show() + + +def plot_data_vs_data_vs_means(signal1, signal2, xaxis, yaxis): + import matplotlib.pyplot as plt + from statistics import mean + plt.plot(signal1) + lens = max(len(signal1), len(signal2)) + average = mean(signal1) + plt.hlines(average, 0, lens, color='red') + plt.vlines(len(signal1), 0, 100000, color='red', linestyles='dashed') + plt.plot(signal2) + average = mean(signal2) + plt.hlines(average, 0, lens, color='green') + plt.vlines(len(signal2), 0, 100000, color='green', linestyles='dashed') + plt.xlabel(xaxis) + plt.ylabel(yaxis) + plt.show() + + +def get_bkps(algo, pen, q): + res = pen, len(algo.predict(pen=pen)) + q.put(pen) + return res + + +def find_knee_point(data_x, data_y, S=1.0, curve='convex', direction='decreasing', plotting=False): + from kneed import KneeLocator + kneedle = KneeLocator(data_x, data_y, S=S, curve=curve, direction=direction) + if plotting: + kneedle.plot_knee() + kneepoint = (kneedle.knee, kneedle.knee_y) + return kneepoint + + +def calc_PELT(signal, model='l1', jump=5, min_dist=2, range_min=1, range_max=50, num_processes=8, refresh_delay=1, + refresh_thresh=5, S=1.0, pen_override=None, plotting=False): + import ruptures as rpt + import time + import matplotlib.pylab as plt + from multiprocessing import Pool, Manager + + # default params in Function + if model is None: + model = 'l1' + if jump is None: + jump = 5 + if min_dist is None: + min_dist = 2 + if range_min is None: + range_min = 1 + if range_max is None: + range_max = 50 + if num_processes is None: + num_processes = 8 + if refresh_delay is None: + refresh_delay = 1 + if refresh_thresh is None: + refresh_thresh = 5 + if S is None: + S = 1.0 + if plotting is None: + plotting = False + + # change point detection. best fit seemingly with l1. rbf prods. RuntimeErr for pen > 30 + # https://ctruong.perso.math.cnrs.fr/ruptures-docs/build/html/costs/index.html + # model = "l1" #"l1" # "l2", "rbf" + algo = rpt.Pelt(model=model, jump=jump, min_size=min_dist).fit(signal) + + ### CALC BKPS WITH DIFF PENALTYS + if pen_override is None: + # building args array for parallelizing + args = [] + # for displaying progression + m = Manager() + q = m.Queue() + + for i in range(range_min, range_max): + args.append((algo, i, q)) + + print('starting kneepoint calculation') + # init Pool with num_proesses + with Pool(num_processes) as p: + # collect results from pool + result = p.starmap_async(get_bkps, args) + # monitor loop + last_percentage = -1 + percentage = -100 # Force display of 0% + i = 0 + while True: + if result.ready(): + break + else: + size = q.qsize() + last_percentage = percentage + percentage = round(size / (range_max - range_min) * 100, 2) + if percentage >= last_percentage + 2 or i >= refresh_thresh: + print('Current progress: ' + str(percentage) + '%') + i = 0 + else: + i += 1 + time.sleep(refresh_delay) + res = result.get() + + # DECIDE WHICH PENALTY VALUE TO CHOOSE ACCORDING TO ELBOW/KNEE APPROACH + # split x and y coords to pass to kneedle + pen_val = [x[0] for x in res] + fittet_bkps_val = [x[1] for x in res] + # # plot to look at res + + knee = find_knee_point(pen_val, fittet_bkps_val, S=S, plotting=plotting) + plt.xlabel('Penalty') + plt.ylabel('Number of Changepoints') + plt.plot(pen_val, fittet_bkps_val) + plt.vlines(knee[0], 0, max(fittet_bkps_val), linestyles='dashed') + print("knee: " + str(knee[0])) + plt.show() + else: + # use forced pen value for plotting + knee = (pen_override, None) + + + #plt.plot(pen_val, fittet_bkps_val) + if knee[0] is not None: + bkps = algo.predict(pen=knee[0]) + if plotting: + fig, ax = rpt.display(signal, bkps) + plt.show() + return bkps + else: + print('With the current thresh-hold S=' + str(S) + ' it is not possible to select a penalty value.') + + +if __name__ == '__main__': + import numpy as np + import json + import ruptures as rpt + import matplotlib.pylab as plt + import sys + import getopt + import re + from dfatool.dfatool import RawData + opt = dict() + + optspec = ( + "filename= " + "v " + "model= " + "jump= " + "min_dist= " + "range_min= " + "range_max= " + "num_processes= " + "refresh_delay= " + "refresh_thresh= " + "S= " + "pen_override= " + "plotting= " + ) + opt_filename = None + opt_verbose = False + opt_model = None + opt_jump = None + opt_min_dist = None + opt_range_min = None + opt_range_max = None + opt_num_processes = None + opt_refresh_delay = None + opt_refresh_thresh = None + opt_S = None + opt_pen_override = None + opt_plotting = False + try: + raw_opts, args = getopt.getopt(sys.argv[1:], "", optspec.split(" ")) + + for option, parameter in raw_opts: + optname = re.sub(r"^--", "", option) + opt[optname] = parameter + + if 'filename' not in opt: + print("No file specified!", file=sys.stderr) + sys.exit(2) + else: + opt_filename = opt['filename'] + if 'v' in opt: + opt_verbose = True + opt_plotting = True + if 'model' in opt: + opt_model = opt['model'] + if 'jump' in opt: + try: + opt_jump = int(opt['jump']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'min_dist' in opt: + try: + opt_min_dist = int(opt['min_dist']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'range_min' in opt: + try: + opt_range_min = int(opt['range_min']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'range_max' in opt: + try: + opt_range_max = int(opt['range_max']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'num_processes' in opt: + try: + opt_num_processes = int(opt['num_processes']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'refresh_delay' in opt: + try: + opt_refresh_delay = int(opt['refresh_delay']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'refresh_thresh' in opt: + try: + opt_refresh_thresh = int(opt['refresh_thresh']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'S' in opt: + try: + opt_S = float(opt['S']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + if 'pen_override' in opt: + try: + opt_pen_override = int(opt['pen_override']) + except ValueError as verr: + print(verr, file=sys.stderr) + sys.exit(2) + except getopt.GetoptError as err: + print(err, file=sys.stderr) + sys.exit(2) + + if ".json" in opt_filename: + # open file with trace data from json + with open(opt['filename'], 'r') as f: + tx_data = json.load(f) + elif ".tar" in opt_filename: + # open with dfatool + raw_data_args = list() + raw_data_args.append(opt_filename) + raw_data = RawData( + raw_data_args, with_traces=True + ) + print("Preprocessing file. Depending on its size, this could take a while.") + preprocessed_data = raw_data.get_preprocessed_data() + print("File fully preprocessed") + + else: + print("Unknown dataformat", file=sys.stderr) + sys.exit(2) + + print(tx_data[1]['parameter']) + # parse json to array for PELT + signal = np.array(tx_data[1]['offline'][0]['uW']) + + for i in range(0, len(signal)): + signal[i] = signal[i]/1000 + bkps = calc_PELT(signal, model=opt_model, range_max=opt_range_max, num_processes=opt_num_processes, jump=opt_jump, S=opt_S) + fig, ax = rpt.display(signal, bkps) + plt.xlabel('Time [us]') + plt.ylabel('Power [mW]') + plt.show() |