--- a
+++ b/app/AnybodyResults.py
@@ -0,0 +1,207 @@
+import re
+import numpy as np
+import copy
+import matplotlib.pyplot as plt
+from matplotlib.widgets import CheckButtons
+from matplotlib.lines import Line2D
+from matplotlib.cm import get_cmap
+
+
+LINE_STYLES = ['--', '-.', '--', ':']
+COLORS = [i for i in get_cmap('tab20').colors]
+
+LEAPMOTION = 'Leap Motion'
+INTERPOLATION = 'AnyBody'
+FLEXION = 'Flexion'
+ABDUCTION = 'Abduction'
+DEVIATION = 'Deviation'
+
+
+class AnybodyResults:
+    def __init__(self, output):
+        self.output = output
+        self.fig = None
+        self.ax = None
+
+        data_dict = {INTERPOLATION: None,
+                     LEAPMOTION: None}
+        rotation_dict = {FLEXION: copy.deepcopy(data_dict),
+                         ABDUCTION: copy.deepcopy(data_dict),
+                         DEVIATION: copy.deepcopy(data_dict)}
+        self.joint_mapping = {
+            'CMC1': copy.deepcopy(rotation_dict),
+            'MCP1': copy.deepcopy(rotation_dict),
+            'DIP1': copy.deepcopy(rotation_dict),
+            # 'CMC2': copy.deepcopy(rotation_dict),
+            'MCP2': copy.deepcopy(rotation_dict),
+            'PIP2': copy.deepcopy(rotation_dict),
+            'DIP2': copy.deepcopy(rotation_dict),
+            # 'CMC3': copy.deepcopy(rotation_dict),
+            'MCP3': copy.deepcopy(rotation_dict),
+            'PIP3': copy.deepcopy(rotation_dict),
+            'DIP3': copy.deepcopy(rotation_dict),
+            # 'CMC4': copy.deepcopy(rotation_dict),
+            'MCP4': copy.deepcopy(rotation_dict),
+            'PIP4': copy.deepcopy(rotation_dict),
+            'DIP4': copy.deepcopy(rotation_dict),
+            # 'CMC5': copy.deepcopy(rotation_dict),
+            'MCP5': copy.deepcopy(rotation_dict),
+            'PIP5': copy.deepcopy(rotation_dict),
+            'DIP5': copy.deepcopy(rotation_dict)}
+
+        self.checkbuttons = {'check_finger': {'status': (False, True, False, False, False),
+                                              'labels': ('Thumb', 'Index', 'Middle', 'Ring', 'Pinky'),
+                                              'buttons': None},
+                             'check_joint': {'status': (False, True, False, False),
+                                             'labels': ('CMC', 'MCP', 'PIP', 'DIP'),
+                                             'buttons': None},
+                             'check_rotation': {'status': (True, False, False),
+                                                'labels': (FLEXION, ABDUCTION, DEVIATION),
+                                                'buttons': None},
+                             'check_data': {'status': (True, True),
+                                            'labels': (INTERPOLATION, LEAPMOTION),
+                                            'buttons': None}}
+
+    def plot(self):
+        """Call this method to initialize and open the plot"""
+        self.plot_setup()
+        self.generate_lines_interpolation()
+        self.update_plot()
+        plt.show()
+
+    def plot_setup(self):
+        """create the plot, add checkbuttons, legend, title, labels"""
+        self.fig, self.ax = plt.subplots()
+        plt.subplots_adjust(left=0.2)
+        plt.grid()
+        plt.title('comparison of angles')
+        plt.xlabel('frame')
+        plt.ylabel('angle in degree')
+        custom_legend = [Line2D([0], [0], linestyle='None', color='k', marker='$A$', lw=2, label=INTERPOLATION),
+                         Line2D([0], [0], linestyle='None', color='tab:gray', marker='$L$', lw=2, label=LEAPMOTION),
+                         Line2D([0], [0], linestyle='None', color=COLORS[0], marker='$1$', lw=2, label='Thumb'),
+                         Line2D([0], [0], linestyle='None', color=COLORS[2], marker='$2$', lw=2, label='Index'),
+                         Line2D([0], [0], linestyle='None', color=COLORS[4], marker='$3$', lw=2, label='Middle'),
+                         Line2D([0], [0], linestyle='None', color=COLORS[6], marker='$4$', lw=2, label='Ring'),
+                         Line2D([0], [0], linestyle='None', color=COLORS[8], marker='$5$', lw=2, label='Pinky'),
+                         Line2D([0], [0], linestyle=LINE_STYLES[0], color='k', lw=2, label='CMC'),
+                         Line2D([0], [0], linestyle=LINE_STYLES[1], color='k', lw=2, label='MCP'),
+                         Line2D([0], [0], linestyle=LINE_STYLES[2], color='k', lw=2, label='PIP'),
+                         Line2D([0], [0], linestyle=LINE_STYLES[3], color='k', lw=2, label='DIP'),
+                         Line2D([0], [0], linestyle='None', color='k', marker='$F$', lw=2, label=FLEXION),
+                         Line2D([0], [0], linestyle='None', color='k', marker='$A$', lw=2, label=ABDUCTION),
+                         Line2D([0], [0], linestyle='None', color='k', marker='$D$', lw=2, label=DEVIATION)]
+        leg = self.ax.legend(handles=custom_legend)
+        # change the font colors to match the line colors:
+        for line, text in zip(leg.get_lines(), leg.get_texts()):
+            text.set_color(line.get_color())
+
+        """checkboxes"""
+        rax_data = plt.axes([0.05, 0.7, 0.1, 0.15])
+        self.checkbuttons['check_data']['buttons'] = CheckButtons(
+            rax_data, self.checkbuttons['check_data']['labels'], self.checkbuttons['check_data']['status'])
+
+        rax_finger = plt.axes([0.05, 0.5, 0.1, 0.15])
+        self.checkbuttons['check_finger']['buttons'] = CheckButtons(
+            rax_finger, self.checkbuttons['check_finger']['labels'], self.checkbuttons['check_finger']['status'])
+
+        rax_joint = plt.axes([0.05, 0.3, 0.1, 0.15])
+        self.checkbuttons['check_joint']['buttons'] = CheckButtons(
+            rax_joint, self.checkbuttons['check_joint']['labels'], self.checkbuttons['check_joint']['status'])
+
+        rax_rotation = plt.axes([0.05, 0.1, 0.1, 0.15])
+        self.checkbuttons['check_rotation']['buttons'] = CheckButtons(
+            rax_rotation, self.checkbuttons['check_rotation']['labels'], self.checkbuttons['check_rotation']['status'])
+
+        # activate on_clicked function for all button groups
+        for button_group, button_values in self.checkbuttons.items():
+            button_values['buttons'].on_clicked(self.change_label)
+
+    def save_status(self):
+        """fetch status from all checkbuttons and save"""
+        for b_group, b_values in self.checkbuttons.items():
+            self.checkbuttons[b_group]['status'] = b_values['buttons'].get_status()
+
+    def change_label(self, label):
+        self.save_status()
+        self.update_plot()
+        plt.draw()
+
+    def generate_lines_interpolation(self):
+        rotation_index = {'Flexion': 0,
+                          'Abduction': 1,
+                          'Deviation': 2}
+        markers_rotation = ['$F{}{}$', '$A{}{}$', '$D{}{}$']
+
+        def joint_line_style(joint_name):
+            if 'CMC' in joint_name:
+                return LINE_STYLES[0]
+            if 'MCP' in joint_name:
+                return LINE_STYLES[1]
+            if 'PIP' in joint_name:
+                return LINE_STYLES[2]
+            if 'DIP' in joint_name:
+                return LINE_STYLES[3]
+
+        # save plots into joint_mapping
+        for joint_name, joint_values in self.joint_mapping.items():
+            line_style = joint_line_style(joint_name)
+            _, finger_number = AnybodyResults.split_joint(joint_name)
+            for rotation_channel, data_source in joint_values.items():
+                index = rotation_index[rotation_channel]
+                offset = 0
+                for data_name in data_source:
+                    x, y = self.get_plot_data(joint_name, index, data_name)
+                    self.joint_mapping[joint_name][rotation_channel][data_name] = self.ax.plot(
+                        x, y,
+                        visible=False,
+                        lw=1.5,
+                        marker=markers_rotation[index].format(finger_number, data_name[0]),
+                        markersize=14,
+                        markevery=(0.03 * index + finger_number / 50 + 0.02 * offset, 0.1),
+                        linestyle=line_style,
+                        color=COLORS[2*(finger_number - 1) + offset]
+                    )[0]
+                    offset += 1
+
+    def update_plot(self):
+        for joint_name, joint_values in self.joint_mapping.items():
+            for rotation, data_source in joint_values.items():
+                for data_name, line in data_source.items():
+                    joint_type, finger_index = AnybodyResults.split_joint(joint_name)
+                    plot_status = \
+                        self.checkbuttons['check_finger']['status'][finger_index - 1] and \
+                        self.checkbuttons['check_joint']['status'][
+                            self.checkbuttons['check_joint']['labels'].index(joint_type)] and \
+                        self.checkbuttons['check_rotation']['status'][
+                            self.checkbuttons['check_rotation']['labels'].index(rotation)] and \
+                        self.checkbuttons['check_data']['status'][
+                            self.checkbuttons['check_data']['labels'].index(data_name)]
+                    line.set_visible(plot_status)
+
+    @staticmethod
+    def split_joint(joint_name):
+        joint_split = re.split(r'(\d)', joint_name)
+        return joint_split[0], int(joint_split[1])
+
+    def get_plot_data(self, joint_name, index, data_name):
+        frames_interpolation = self.output['Main.Study.nStep']
+        t_interpolation = np.arange(1, frames_interpolation + 1, 1)
+        if data_name == INTERPOLATION:
+            output_path = 'Main.Study.Output.JointAngleOutputs.{}'
+            return \
+                t_interpolation, \
+                np.rad2deg(self.output[output_path.format(joint_name)][0][:, index])
+
+        if data_name == LEAPMOTION:
+            output_path = 'Main.HumanModel.Mannequin.Posture.Right.Finger{}.{}'
+
+            frames_leap_motion = len(self.output[output_path.format(2, 'MCP2')][0][:, 0])
+            t_leap_motion = np.arange(1, frames_interpolation + 1, frames_interpolation / frames_leap_motion)
+
+            _, finger_number = AnybodyResults.split_joint(joint_name)
+            return \
+                t_leap_motion, \
+                self.output[output_path.format(finger_number, joint_name)][0][:, index]
+
+        raise ValueError('Unknown data source. Available sources: {}'.format([INTERPOLATION, LEAPMOTION]))