<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Test application
Autor
Step1:  Test data from the application loaded into a simple data container. One row contains the data of a click. If not changed the first file from files is loaded.
| circle_x | circle_y | click_x | click_y | timestamp                 | radius |
|----------|----------|---------|---------|---------------------------|--------|
| 391      | 207      | 426     | 232     | 2020-01-23 15
Step3:  ID is the index of difficulty.
$ID = \log_2 \left(\dfrac{2D}{W}\right)$
D is the distance from the starting point to the center of the target.
W is the width of the target measured along the axis of motion. W can also be thought of as the allowed error tolerance in the final position, since the final point of the motion must fall within $\pm \frac{W}{2}$ of the target's center.
MT is the average time to complete the movement.
a and b are constants that depend on the choice of input device and are usually determined empirically by regression analysis. a defines the intersection on the y-axis and is often as interpreted as a delay. The b-parameter is a slope and describes an acceleration. Both paramters show the linear dependency in Fitts' Law.
$MT = a + b \cdot ID = a + b \cdot \log_2 \left(\dfrac{2D}{W}\right) $
Step4:  Calculate all models that can be drawn on the graph later on.
Step5:  All data is put into a pandas dataframe for easier selection and matplot drawing
<ASSISTANT_TASK:>
Python Code:
files = ['clicks_2020-01-24 09:48:51_touchpad_14"_monitor.csv',
         'clicks_2020-01-24 09:44:46_mouse_24"_monitor.csv',
         'clicks_2020-01-23 16:00:32_mouse_24"_monitor.csv']
Explanation: Test application
Autor: Nils Verheyen\
Matriculation number: 3043171
Mouse and touchpad input were tested on full hd screens with 24" and 14".
End of explanation
import csv
import numpy as np
import pandas as pd
from dataclasses import dataclass
from datetime import datetime, timedelta
@dataclass
class CircleClick():
    circle_x: int
    circle_y: int
    click_x: int
    click_y: int
    radius: int
    timestamp: datetime
clicks = []
with open(files[0]) as src:
    reader = csv.reader(src)
    for row in reader:
        circle_click = CircleClick(circle_x=int(row[0]), circle_y=int(row[1]), 
                                   click_x=int(row[2]), click_y=int(row[3]),
                                   timestamp=datetime.strptime(row[4], '%Y-%m-%d %H:%M:%S.%f'),
                                   radius=int(row[5]))
        clicks.append(circle_click)
clicks[0]
Explanation: Test data from the application loaded into a simple data container. One row contains the data of a click. If not changed the first file from files is loaded.
| circle_x | circle_y | click_x | click_y | timestamp                 | radius |
|----------|----------|---------|---------|---------------------------|--------|
| 391      | 207      | 426     | 232     | 2020-01-23 15:59:09.367584| 30     |
End of explanation
def distance(x1: int, x2: int, y1: int, y2: int):
    a = np.power(x1 - x2, 2)
    b = np.power(y1 - y2, 2)
    distance = np.sqrt(a + b)
    return distance
distance(0, 1, 0, 1)
@dataclass 
class FittsModel:
    
    D: float = 0
    W: float = 0
    ID: float = 0
    MT: timedelta = timedelta(0)
        
    def calculate(self, start: CircleClick, end: CircleClick):
        The model calculates its values D, W, ID and MT
        based on two clicks
        self.D = distance(start.click_x, 
                          end.circle_x + end.radius,
                          start.click_y,
                          end.circle_y + end.radius)
        self.W = end.radius * 2
        self.ID = np.log2(2 * self.D / self.W)
        self.MT = end.timestamp - start.timestamp
    
    @property
    def MT_in_millis(self):
        millis, micros = divmod(self.MT.microseconds, 1000)
        return self.MT.total_seconds() * 1000 + millis + micros / 1000
Explanation: ID is the index of difficulty.
$ID = \log_2 \left(\dfrac{2D}{W}\right)$
D is the distance from the starting point to the center of the target.
W is the width of the target measured along the axis of motion. W can also be thought of as the allowed error tolerance in the final position, since the final point of the motion must fall within $\pm \frac{W}{2}$ of the target's center.
MT is the average time to complete the movement.
a and b are constants that depend on the choice of input device and are usually determined empirically by regression analysis. a defines the intersection on the y-axis and is often as interpreted as a delay. The b-parameter is a slope and describes an acceleration. Both paramters show the linear dependency in Fitts' Law.
$MT = a + b \cdot ID = a + b \cdot \log_2 \left(\dfrac{2D}{W}\right) $
End of explanation
models = []
for i in range(1, len(clicks)):
    model = FittsModel()
    model.calculate(clicks[i - 1], clicks[i])
    models.append(model)
    
models[0]
Explanation: Calculate all models that can be drawn on the graph later on.
End of explanation
data = {'D': [], 'W': [], 'ID': [], 'MT': []}
for m in models:
    data['D'].append(m.D)
    data['W'].append(m.W)
    data['ID'].append(m.ID)
    data['MT'].append(m.MT_in_millis)
df = pd.DataFrame(data=data)
df
widths = set([m.W for m in models])
widths
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['figure.figsize']
matplotlib.rcParams['figure.figsize'] = [12, 8]
df['ID'].mean()
df.groupby(['W']).mean()
df.groupby(['W']).median()
from sklearn.linear_model import LinearRegression
# uncomment the next line to select a specific circle width
# widths = [100]
for width in widths:
    
    _df = df[df['W'] == width]
    
    model = LinearRegression()
    model.fit(_df[['ID']], _df[['MT']])
    
    min_x = min(df['ID'])
    max_x = max(df['ID'])
    predicted = model.predict([[min_x], [max_x]])
    
    plt.scatter(x=_df['ID'], y=_df['MT'])
    plt.plot([min_x, max_x], predicted)
    
plt.legend(widths)
plt.show()
Explanation: All data is put into a pandas dataframe for easier selection and matplot drawing
End of explanation
<END_TASK>