diff --git a/data/tools/2d_event_writer.py b/data/tools/2d_event_writer.py
new file mode 100644
index 0000000000000000000000000000000000000000..d36e85beaa0ab513ca90d46d73fc2f89347fa490
--- /dev/null
+++ b/data/tools/2d_event_writer.py
@@ -0,0 +1,112 @@
+import ConfigParser as cp
+import os
+import numpy as np
+import csv
+import h5py
+
+from support.maximum import maximum
+from support.norm import norm
+from support.find_quakes import find_quakes
+from support.slip_beginnings import slip_beginnings
+from support.slip_endings import slip_endings
+from support.max_distance import max_distance
+
+
+NBODIES = 2
+FINAL_TIME = 1000  # s
+FINAL_VELOCITY = 1e-5  # m/s
+THRESHOLD_VELOCITY = 0.5*FINAL_VELOCITY  # 1000e-6 + FINAL_VELOCITY
+
+TANGENTIAL_COORDS = 1
+
+# read config ini
+config = cp.ConfigParser()
+config_path = os.path.join('config.ini')
+config.read(config_path)
+sim_path = config.get('directories', 'simulation')
+exp_path = config.get('directories', 'experiment')
+out_path = config.get('directories', 'output')
+
+# create output directory
+out_dir = os.path.join(out_path)
+if not os.path.exists(out_dir):
+    os.mkdir(out_dir)
+
+h5path = os.path.join(sim_path)
+h5file = h5py.File(os.path.join(h5path, 'output.h5'), 'r')
+
+# read time
+relative_time = np.array(h5file['relativeTime'])
+real_time = relative_time * FINAL_TIME
+
+for body_ID in range(NBODIES):
+    body = 'body' + str(body_ID)
+
+    if body not in h5file:
+        continue
+
+    # read data
+    coordinates = np.array(h5file[body + '/coordinates'])
+    displacement = np.array(h5file[body + '/displacement'])
+    velocity = np.array(h5file[body + '/velocity'])
+
+    num_vertices = displacement.shape[1]
+    velocity_norm = norm(velocity[:, :, TANGENTIAL_COORDS:])
+    maximum_velocity = maximum(velocity_norm)
+
+    [quake_starts, quake_ends] = find_quakes(THRESHOLD_VELOCITY,
+                                             maximum_velocity)
+
+    quakes = {}
+    for quake_ID in range(len(quake_starts)):
+        quake_start = int(quake_starts[quake_ID])
+        quake_end = int(quake_ends[quake_ID])
+
+        quake = {}
+        quake['start'] = real_time[quake_start]
+        quake['end'] = real_time[quake_end]
+
+        local_slipping_times = velocity_norm[quake_start:quake_end, :] \
+            > THRESHOLD_VELOCITY
+        quake_displacement = displacement[quake_start:quake_end, :, :]
+        slip = np.zeros(num_vertices)
+
+        for i in range(num_vertices):
+            if any(local_slipping_times[:, i]):
+                starts = slip_beginnings(local_slipping_times[:, i])
+                ends = slip_endings(local_slipping_times[:, i])
+                slip[i] = np.linalg.norm(quake_displacement[ends, i, :]
+                                         - quake_displacement[starts, i, :])
+
+        quake['peakSlip'] = max(slip)
+        quake['peakSlipRate'] = max(maximum_velocity[quake_start:quake_end])
+
+        max_rupture_width = 0
+        for time_step in range(local_slipping_times.shape[0]):
+            slipping_time = local_slipping_times[time_step, :]
+            if not any(slipping_time):
+                continue
+
+            slipping_coords = coordinates[slipping_time] \
+                + displacement[quake_start + time_step, slipping_time]
+            if len(slipping_coords) > 1:
+                pair = np.array(max_distance(slipping_coords))
+                max_rupture_width = max(max_rupture_width,
+                                        np.linalg.norm(pair[0] - pair[1]))
+
+        quake['ruptureWidth'] = max_rupture_width
+        quakes[quake_ID] = quake
+
+    # output quake data to csv file
+    csv_columns = quakes[0].keys()
+    csv_file_path = os.path.join(out_path, 'events' + str(body_ID) + '.csv')
+    try:
+        with open(csv_file_path, 'w') as csv_file:
+            writer = csv.DictWriter(csv_file, fieldnames=csv_columns)
+            writer.writeheader()
+            for quake_ID in quakes:
+                writer.writerow(quakes[quake_ID])
+    except IOError:
+        print('I/O error')
+
+h5file.close()
diff --git a/data/tools/2d_event_writer.py~ b/data/tools/2d_event_writer.py~
new file mode 100644
index 0000000000000000000000000000000000000000..d36e85beaa0ab513ca90d46d73fc2f89347fa490
--- /dev/null
+++ b/data/tools/2d_event_writer.py~
@@ -0,0 +1,112 @@
+import ConfigParser as cp
+import os
+import numpy as np
+import csv
+import h5py
+
+from support.maximum import maximum
+from support.norm import norm
+from support.find_quakes import find_quakes
+from support.slip_beginnings import slip_beginnings
+from support.slip_endings import slip_endings
+from support.max_distance import max_distance
+
+
+NBODIES = 2
+FINAL_TIME = 1000  # s
+FINAL_VELOCITY = 1e-5  # m/s
+THRESHOLD_VELOCITY = 0.5*FINAL_VELOCITY  # 1000e-6 + FINAL_VELOCITY
+
+TANGENTIAL_COORDS = 1
+
+# read config ini
+config = cp.ConfigParser()
+config_path = os.path.join('config.ini')
+config.read(config_path)
+sim_path = config.get('directories', 'simulation')
+exp_path = config.get('directories', 'experiment')
+out_path = config.get('directories', 'output')
+
+# create output directory
+out_dir = os.path.join(out_path)
+if not os.path.exists(out_dir):
+    os.mkdir(out_dir)
+
+h5path = os.path.join(sim_path)
+h5file = h5py.File(os.path.join(h5path, 'output.h5'), 'r')
+
+# read time
+relative_time = np.array(h5file['relativeTime'])
+real_time = relative_time * FINAL_TIME
+
+for body_ID in range(NBODIES):
+    body = 'body' + str(body_ID)
+
+    if body not in h5file:
+        continue
+
+    # read data
+    coordinates = np.array(h5file[body + '/coordinates'])
+    displacement = np.array(h5file[body + '/displacement'])
+    velocity = np.array(h5file[body + '/velocity'])
+
+    num_vertices = displacement.shape[1]
+    velocity_norm = norm(velocity[:, :, TANGENTIAL_COORDS:])
+    maximum_velocity = maximum(velocity_norm)
+
+    [quake_starts, quake_ends] = find_quakes(THRESHOLD_VELOCITY,
+                                             maximum_velocity)
+
+    quakes = {}
+    for quake_ID in range(len(quake_starts)):
+        quake_start = int(quake_starts[quake_ID])
+        quake_end = int(quake_ends[quake_ID])
+
+        quake = {}
+        quake['start'] = real_time[quake_start]
+        quake['end'] = real_time[quake_end]
+
+        local_slipping_times = velocity_norm[quake_start:quake_end, :] \
+            > THRESHOLD_VELOCITY
+        quake_displacement = displacement[quake_start:quake_end, :, :]
+        slip = np.zeros(num_vertices)
+
+        for i in range(num_vertices):
+            if any(local_slipping_times[:, i]):
+                starts = slip_beginnings(local_slipping_times[:, i])
+                ends = slip_endings(local_slipping_times[:, i])
+                slip[i] = np.linalg.norm(quake_displacement[ends, i, :]
+                                         - quake_displacement[starts, i, :])
+
+        quake['peakSlip'] = max(slip)
+        quake['peakSlipRate'] = max(maximum_velocity[quake_start:quake_end])
+
+        max_rupture_width = 0
+        for time_step in range(local_slipping_times.shape[0]):
+            slipping_time = local_slipping_times[time_step, :]
+            if not any(slipping_time):
+                continue
+
+            slipping_coords = coordinates[slipping_time] \
+                + displacement[quake_start + time_step, slipping_time]
+            if len(slipping_coords) > 1:
+                pair = np.array(max_distance(slipping_coords))
+                max_rupture_width = max(max_rupture_width,
+                                        np.linalg.norm(pair[0] - pair[1]))
+
+        quake['ruptureWidth'] = max_rupture_width
+        quakes[quake_ID] = quake
+
+    # output quake data to csv file
+    csv_columns = quakes[0].keys()
+    csv_file_path = os.path.join(out_path, 'events' + str(body_ID) + '.csv')
+    try:
+        with open(csv_file_path, 'w') as csv_file:
+            writer = csv.DictWriter(csv_file, fieldnames=csv_columns)
+            writer.writeheader()
+            for quake_ID in quakes:
+                writer.writerow(quakes[quake_ID])
+    except IOError:
+        print('I/O error')
+
+h5file.close()
diff --git a/data/config.ini b/data/tools/config.ini
similarity index 56%
rename from data/config.ini
rename to data/tools/config.ini
index a3a37a49ee4e8a594affaebd9e10bb6f7aa7213c..d8a6165b28fd6ef91665bfedf4653f55827fc05f 100644
--- a/data/config.ini
+++ b/data/tools/config.ini
@@ -1,4 +1,4 @@
 [directories]
-simulation = ~/group/publications/2016-PippingKornhuberRosenauOncken
+simulation = /storage/mi/podlesny/software/dune/build-debug/dune-tectonic/src/strikeslip
 experiment = ~/group/publications/2016-RosenauCorbiDominguezRudolfRitterPipping
 output     = generated
diff --git a/data/tools/generate-2d.bash b/data/tools/generate-2d.bash
old mode 100755
new mode 100644
diff --git a/data/tools/generate-3d.bash b/data/tools/generate-3d.bash
old mode 100755
new mode 100644
diff --git a/data/tools/generate-others.bash b/data/tools/generate-others.bash
old mode 100755
new mode 100644
diff --git a/data/tools/generated/events1.csv b/data/tools/generated/events1.csv
new file mode 100644
index 0000000000000000000000000000000000000000..575827611a85aaa215ca52d24fb45e0a04576668
--- /dev/null
+++ b/data/tools/generated/events1.csv
@@ -0,0 +1,20 @@
+start,peakSlipRate,end,ruptureWidth,peakSlip
+20.086059570312422,5.7045853762396602e-06,20.086669921874922,0,0.0
+20.090332031249918,5.6219949973608878e-06,20.092163085937418,0,0.0
+20.094604492187415,5.8412336903395239e-06,20.095825195312415,0,0.0
+20.099487304687411,5.3352579051826403e-06,20.100097656249908,0,0.0
+20.143737792968619,5.4285740142335498e-06,20.144958496093619,0,0.0
+20.148620605468615,5.6370561043864526e-06,20.149536132812365,0,0.0
+20.353851318359059,6.0525078256123743e-06,20.354461669921559,0,0.0
+20.358734130859055,5.1806538408711459e-06,20.359344482421555,0,0.0
+20.371856689452795,5.6547173619088325e-06,20.373077392577795,0,0.0
+20.425262451171495,6.4545930360194781e-06,20.428314208983991,0.088385894124722503,1.4298690605481336e-08
+20.479583740233945,5.8310594282664788e-06,20.481414794921445,0,0.0
+20.483245849608942,5.2537138171449348e-06,20.485076904296442,0,6.2000101383992609e-09
+20.531158447265149,5.2316818926703734e-06,20.531768798827649,0,0.0
+20.544586181640138,5.4092184353134343e-06,20.545196533202635,0,0.0
+20.593109130858842,6.190190600109647e-06,20.595550537108842,0,0.0
+20.608673095702581,5.5618674305029011e-06,20.609283447265081,0,0.0
+20.625152587890067,5.4920875934131527e-06,20.625762939452567,0,0.0
+20.630035400390064,5.1740512343599518e-06,20.630645751952564,0,0.0
+20.63369750976506,5.7392806837644885e-06,20.63491821289006,0,0.0
diff --git a/data/tools/support/__init__.py b/data/tools/support/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d1c8b69c3fce7bea45c73efd06983e3c419a92f
--- /dev/null
+++ b/data/tools/support/__init__.py
@@ -0,0 +1 @@
+ 
diff --git a/data/tools/support/__init__.pyc b/data/tools/support/__init__.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..05977bb84ed00be29153c30f2bd03eb66ffde9aa
Binary files /dev/null and b/data/tools/support/__init__.pyc differ
diff --git a/data/tools/support/findQuakes.R b/data/tools/support/findQuakes.R
deleted file mode 100644
index 698b649848329ea192b62ff76502447ad053b4db..0000000000000000000000000000000000000000
--- a/data/tools/support/findQuakes.R
+++ /dev/null
@@ -1,18 +0,0 @@
-Rcpp::sourceCpp('tools/support/maxVelocity.cpp')
-Rcpp::sourceCpp('tools/support/negativeStarts.cpp')
-Rcpp::sourceCpp('tools/support/positiveStarts.cpp')
-
-findQuakes <- function (criticalVelocity, velocity, indices, dimensions) {
-  maximumVelocities<- maxVelocity(velocity[indices,,dimensions])
-  slippingTimes  <- maximumVelocities > criticalVelocity
-
-  ns <- negativeStarts(slippingTimes) + indices[[1]] - 1
-  ps <- positiveStarts(slippingTimes) + indices[[1]] - 1
-
-  ## NOTE: we drop incomplete quakes here
-  mlen <- min(length(ns), length(ps))
-  ns <- ns[1:mlen]
-  ps <- ps[1:mlen]
-
-  return(data.frame(endingIndex = ns, beginningIndex = ps))
-}
diff --git a/data/tools/support/find_quakes.py b/data/tools/support/find_quakes.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa4653fd4384a89db8be9a258c882dc7583c1495
--- /dev/null
+++ b/data/tools/support/find_quakes.py
@@ -0,0 +1,16 @@
+from support.slip_beginnings import slip_beginnings
+from support.slip_endings import slip_endings
+
+
+def find_quakes(threshold_velocity, maximum_velocities):
+    slipping_times = maximum_velocities > threshold_velocity
+
+    quake_starts = slip_beginnings(slipping_times)
+    quake_ends = slip_endings(slipping_times)
+
+    # remove incomplete quakes
+    min_len = min(len(quake_starts), len(quake_ends))
+    quake_ends = quake_ends[0:min_len]
+    quake_starts = quake_starts[0:min_len]
+
+    return [quake_starts, quake_ends]
diff --git a/data/tools/support/find_quakes.pyc b/data/tools/support/find_quakes.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ddaf405b860cdef5b12af1266eea56bede793b2
Binary files /dev/null and b/data/tools/support/find_quakes.pyc differ
diff --git a/data/tools/support/find_quakes.py~ b/data/tools/support/find_quakes.py~
new file mode 100644
index 0000000000000000000000000000000000000000..e5aef04016634e9cbe1d30a54cd78ab758324a1d
--- /dev/null
+++ b/data/tools/support/find_quakes.py~
@@ -0,0 +1,17 @@
+from support.slip_beginnings import slip_beginnings
+from support.slip_endings import slip_endings
+
+
+def find_quakes(threshold_velocity, maximum_velocities):
+    slipping_times = maximum_velocities > threshold_velocity
+    print(slipping_times)
+
+    quake_starts = slip_beginnings(slipping_times)
+    quake_ends = slip_endings(slipping_times)
+
+    # remove incomplete quakes
+    min_len = min(len(quake_starts), len(quake_ends))
+    quake_ends = quake_ends[0:min_len]
+    quake_starts = quake_starts[0:min_len]
+
+    return [quake_starts, quake_ends]
diff --git a/data/tools/support/maxVelocity.cpp b/data/tools/support/maxVelocity.cpp
deleted file mode 100644
index 5294e563d99c149fe580368c9df415f73e7bf0d9..0000000000000000000000000000000000000000
--- a/data/tools/support/maxVelocity.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <Rcpp.h>
-
-// For std::hypot(x,y)
-// [[Rcpp::plugins(cpp11)]]
-
-// Layout of vectors is such that loops over inner indices are traversed first
-// [[Rcpp::export]]
-Rcpp::NumericVector maxVelocity(Rcpp::NumericVector const &x) {
-  Rcpp::IntegerVector size = x.attr("dim");
-  Rcpp::NumericVector ret(size[0]);
-  switch (size[2]) {
-  case 1:
-    for (size_t ts = 0; ts < size[0]; ++ts)
-      for (size_t coord = 0; coord < size[1]; ++coord)
-        ret[ts] = std::max(ret[ts],
-                           std::abs(x[0 * size[1] * size[0] + coord * size[0] + ts]));
-    break;
-  case 2:
-    for (size_t ts = 0; ts < size[0]; ++ts)
-      for (size_t coord = 0; coord < size[1]; ++coord)
-        ret[ts] = std::max(ret[ts],
-                           std::hypot(x[0 * size[1] * size[0] + coord * size[0] + ts],
-                                      x[1 * size[1] * size[0] + coord * size[0] + ts]));
-    break;
-  default:
-    throw std::range_error("Inadmissible value");
-  }
-  return ret;
-}
diff --git a/data/tools/support/max_distance.py b/data/tools/support/max_distance.py
new file mode 100644
index 0000000000000000000000000000000000000000..95467bad19b6ed7116817bcd1cf014923b3a8762
--- /dev/null
+++ b/data/tools/support/max_distance.py
@@ -0,0 +1,17 @@
+from itertools import combinations
+
+
+def square_distance(x, y):
+    return sum([(xi-yi)**2 for xi, yi in zip(x, y)])
+
+
+def max_distance(points):
+    max_square_distance = 0
+    max_pair = (0, 0)
+    for pair in combinations(points, 2):
+        sq_dist = square_distance(*pair)
+
+        if sq_dist > max_square_distance:
+            max_square_distance = sq_dist
+            max_pair = pair
+    return max_pair
diff --git a/data/tools/support/max_distance.pyc b/data/tools/support/max_distance.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7fc47e8672dbe1ee8d9da3ab51be2c4d3346a3fc
Binary files /dev/null and b/data/tools/support/max_distance.pyc differ
diff --git a/data/tools/support/max_distance.py~ b/data/tools/support/max_distance.py~
new file mode 100644
index 0000000000000000000000000000000000000000..2bb875712b0b934f7c9232a0b6901c36cc25bdb3
--- /dev/null
+++ b/data/tools/support/max_distance.py~
@@ -0,0 +1,17 @@
+from itertools import combinations
+
+
+def square_distance(x, y):
+    return sum([(xi-yi)**2 for xi, yi in zip(x, y)])
+
+
+def max_distance(points):
+    max_square_distance = 0
+    max_pair = (0, 0)
+    for pair in combinations(points, 2):
+        sq_dist = square_distance(*pair)
+        print(sq_dist)
+        if sq_dist > max_square_distance:
+            max_square_distance = sq_dist
+            max_pair = pair
+    return max_pair
diff --git a/data/tools/support/max_velocity.py b/data/tools/support/max_velocity.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3ee84ebaf76341c1da11d262cd5b13f8dcdfa7f
--- /dev/null
+++ b/data/tools/support/max_velocity.py
@@ -0,0 +1,4 @@
+import numpy as np
+
+def max_velocity(x) :
+    return maximum(norm(x))
\ No newline at end of file
diff --git a/data/tools/support/max_velocity.pyc b/data/tools/support/max_velocity.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e0953b749ce794147ae298b2c25c36082d51a0b
Binary files /dev/null and b/data/tools/support/max_velocity.pyc differ
diff --git a/data/tools/support/max_velocity.py~ b/data/tools/support/max_velocity.py~
new file mode 100644
index 0000000000000000000000000000000000000000..b0ef5d74a8fc06d89fda692c8f7c96707e8574cb
--- /dev/null
+++ b/data/tools/support/max_velocity.py~
@@ -0,0 +1,11 @@
+import numpy as np
+
+def max_velocity(x) :
+    size = x.shape 
+    res = np.zeros(size[0])
+
+    for time_step in range(size[0]) :
+        for vertex in range(size[1]) :
+            res[time_step] = max(res[time_step], np.linalg.norm(x[time_step, vertex, :]))
+
+    return res
\ No newline at end of file
diff --git a/data/tools/support/maximum.py b/data/tools/support/maximum.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7666fbe39eb69d896f3b1504984a3dfcd4f81fe
--- /dev/null
+++ b/data/tools/support/maximum.py
@@ -0,0 +1,11 @@
+import numpy as np
+
+
+def maximum(x):
+    size = x.shape
+    res = np.zeros(size[0])
+
+    for time_step in range(size[0]):
+        res[time_step] = max(res[time_step], max(x[time_step, :]))
+
+    return res
diff --git a/data/tools/support/maximum.pyc b/data/tools/support/maximum.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..30e653a21ca5c22d270af2091ca051cb8f599f8f
Binary files /dev/null and b/data/tools/support/maximum.pyc differ
diff --git a/data/tools/support/maximum.py~ b/data/tools/support/maximum.py~
new file mode 100644
index 0000000000000000000000000000000000000000..3664f3bd7ce2f320de7a1b362d30b381e8babbd8
--- /dev/null
+++ b/data/tools/support/maximum.py~
@@ -0,0 +1,11 @@
+import numpy as np
+
+def maximum(x) :
+    size = x.shape 
+    res = np.zeros(size[0])
+
+    for time_step in range(size[0]) :
+        for vertex in range(size[1]) :
+            res[time_step] = max(res[time_step], max(x[time_step, vertex]))
+
+    return res
\ No newline at end of file
diff --git a/data/tools/support/negativeStarts.cpp b/data/tools/support/negativeStarts.cpp
deleted file mode 100644
index 940765c2d1a55074308c986d6b232c7458404ca3..0000000000000000000000000000000000000000
--- a/data/tools/support/negativeStarts.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <Rcpp.h>
-
-// [[Rcpp::export]]
-Rcpp::NumericVector negativeStarts(Rcpp::NumericVector const &x) {
-  std::vector<size_t> starts(0);
-  bool prev = false;
-  for (size_t i = 0; i < x.size(); ++i) {
-    if (prev && !x[i])
-      starts.push_back(i+1); // R indices start at 1
-    prev = x[i];
-  }
-  return Rcpp::NumericVector(starts.begin(), starts.end());
-}
diff --git a/data/tools/support/norm.py b/data/tools/support/norm.py
new file mode 100644
index 0000000000000000000000000000000000000000..c0276d801d74c79be9f9deb0c53bc6e635798b75
--- /dev/null
+++ b/data/tools/support/norm.py
@@ -0,0 +1,12 @@
+import numpy as np
+
+
+def norm(x):
+    size = x.shape
+    res = np.zeros((size[0], size[1]))
+
+    for time_step in range(size[0]):
+        for vertex in range(size[1]):
+            res[time_step, vertex] = np.linalg.norm(x[time_step, vertex, :])
+
+    return res
diff --git a/data/tools/support/norm.pyc b/data/tools/support/norm.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ba10f9d1d00a542cac6c76c38fa465f6a1633e7e
Binary files /dev/null and b/data/tools/support/norm.pyc differ
diff --git a/data/tools/support/norm.py~ b/data/tools/support/norm.py~
new file mode 100644
index 0000000000000000000000000000000000000000..3e26f65dff8ab3ba4176062c8870e62e3a02bd98
--- /dev/null
+++ b/data/tools/support/norm.py~
@@ -0,0 +1,11 @@
+import numpy as np
+
+def norm(x) :
+    size = x.shape 
+    res = np.zeros(size[0], size[1])
+
+    for time_step in range(size[0]) :
+        for vertex in range(size[1]) :
+            res[time_step, vertex] = np.linalg.norm(x[time_step, vertex, :])
+
+    return res 
diff --git a/data/tools/support/positiveStarts.cpp b/data/tools/support/positiveStarts.cpp
deleted file mode 100644
index 3e9498c05dc4425918d4351095cd86a807f2c562..0000000000000000000000000000000000000000
--- a/data/tools/support/positiveStarts.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <Rcpp.h>
-
-// [[Rcpp::export]]
-Rcpp::NumericVector positiveStarts(Rcpp::NumericVector const &x) {
-  std::vector<size_t> starts(0);
-  bool prev = false;
-  for (size_t i = 0; i < x.size(); ++i) {
-    if (!prev && x[i])
-      starts.push_back(i+1); // R indices start at 1
-    prev = x[i];
-  }
-  return Rcpp::NumericVector(starts.begin(), starts.end());
-}
-
diff --git a/data/tools/support/slip_beginnings.py b/data/tools/support/slip_beginnings.py
new file mode 100644
index 0000000000000000000000000000000000000000..255adf44d900595def438864124830b7134306c9
--- /dev/null
+++ b/data/tools/support/slip_beginnings.py
@@ -0,0 +1,15 @@
+import array as ar
+
+
+def slip_beginnings(x):
+    # returns indicies i for which x[i-1]=0 and x[i]>0
+    starts = ar.array('i', (0 for i in range(len(x))))
+    prev = False
+
+    length = 0
+    for i in range(len(x)):
+        if (not prev and x[i]):
+            starts[length] = i
+            length += 1
+        prev = x[i]
+    return starts[:length]
diff --git a/data/tools/support/slip_beginnings.pyc b/data/tools/support/slip_beginnings.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6ab6756aec374c95a324af74844469346be2e0cf
Binary files /dev/null and b/data/tools/support/slip_beginnings.pyc differ
diff --git a/data/tools/support/slip_beginnings.py~ b/data/tools/support/slip_beginnings.py~
new file mode 100644
index 0000000000000000000000000000000000000000..6c54c9afc93d37c803fae67d441f1e1da3ff6796
--- /dev/null
+++ b/data/tools/support/slip_beginnings.py~
@@ -0,0 +1,11 @@
+import numpy as np
+
+def slip_beginnings(x) :
+    # returns indicies i for which x[i-1]=0 and x[i]>0  
+    starts = []
+    prev = False
+    for i in range(len(x)) :
+        if (not prev and x[i]) :
+            starts.append(i)
+            prev = x[i]
+    return starts
diff --git a/data/tools/support/slip_endings.py b/data/tools/support/slip_endings.py
new file mode 100644
index 0000000000000000000000000000000000000000..9fdcaf88a6f8f7942a580489a33bf60f6ce1271a
--- /dev/null
+++ b/data/tools/support/slip_endings.py
@@ -0,0 +1,16 @@
+import array as ar
+
+
+def slip_endings(x):
+    # returns indicies i for which x[i-1]>0 and x[i]=0
+    ends = ar.array('i', (0 for i in range(len(x))))
+    prev = False
+
+    length = 0
+    for i in range(len(x)):
+        if (prev and not x[i]):
+            ends[length] = i
+            length += 1
+        prev = x[i]
+
+    return ends[:length]
diff --git a/data/tools/support/slip_endings.pyc b/data/tools/support/slip_endings.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..89caa52ad2f9e896a68667e641bce5836ddceaeb
Binary files /dev/null and b/data/tools/support/slip_endings.pyc differ
diff --git a/data/tools/support/slip_endings.py~ b/data/tools/support/slip_endings.py~
new file mode 100644
index 0000000000000000000000000000000000000000..f05b69c961ab30cf1cfcd40fb42be2adf4f53447
--- /dev/null
+++ b/data/tools/support/slip_endings.py~
@@ -0,0 +1,11 @@
+import numpy as np
+
+def slip_endings(x) :
+    # returns indicies i for which x[i-1]>0 and x[i]=0
+    starts = np.array([])
+    prev = False
+    for i in range(len(x)) :
+        if (prev and not x[i]) :
+            starts.append(i)
+            prev = x[i]
+    return starts
\ No newline at end of file
diff --git a/data/tools/support/trapezoidal.cpp b/data/tools/support/trapezoidal.cpp
deleted file mode 100644
index 3b4833d65cefddead8f84c8d368113edc07a3c4f..0000000000000000000000000000000000000000
--- a/data/tools/support/trapezoidal.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <Rcpp.h>
-
-// [[Rcpp::export]]
-double trapezoidal(Rcpp::NumericVector const &x, Rcpp::NumericVector const &y) {
-  double ret = 0;
-  for (size_t i = 1; i < x.size(); ++i)
-    ret += (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / 2;
-  return ret;
-}
diff --git a/data/tools/support/trapezoidal.py b/data/tools/support/trapezoidal.py
new file mode 100644
index 0000000000000000000000000000000000000000..9574b1259f684cd6c07ff538ceb9f805e7197aee
--- /dev/null
+++ b/data/tools/support/trapezoidal.py
@@ -0,0 +1,8 @@
+# x: vector of domain values
+# y: vector of function values f(x)
+def trapezoidal(x, y) :
+    # returns integral of (x, y = f(x)) calculated with trapezoidal rule 
+	res = 0.0
+	for i in range(1, len(x)) :
+		res += (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / 2.0
+	return res
\ No newline at end of file
diff --git a/data/tools/support/trapezoidal.py~ b/data/tools/support/trapezoidal.py~
new file mode 100644
index 0000000000000000000000000000000000000000..8d462782918156b0fce5a381cf08d2c7fc31e728
--- /dev/null
+++ b/data/tools/support/trapezoidal.py~
@@ -0,0 +1,8 @@
+# x: vector of domain values
+# y: vector of function values f(x)
+def trapezoidal(x, y) :
+	# returns integral of (x, y = f(x)) calculated with trapezoidal rule 
+	res = 0.0
+	for i in range(1, len(x)) :
+		res += (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / 2.0
+	return res
\ No newline at end of file
diff --git a/data/tools/support/writeContours.R b/data/tools/support/write_contours.py
similarity index 100%
rename from data/tools/support/writeContours.R
rename to data/tools/support/write_contours.py
diff --git a/debugging.m b/debugging.m
index 259ae8dbe47c9706bf3ad7e21670e12ad7a0a2c9..0146058d9136e94cad4d9f263b30772871edf529 100644
--- a/debugging.m
+++ b/debugging.m
@@ -1,3 +1,15 @@
+% householder reflection
+
+v0 = [1; 0];
+v0 = v0./norm(v0);
+
+v1 = [1; -1];
+v1 = v1./norm(v1);
+
+v = 1/2.*(v1-v0);
+vnorm = norm(v);
+
+H = eye(2) - 2/(vnorm^2).*(v*v')
 
 A = [...
 ];