Skip to content

Commit 113c4af

Browse files
committed
march commit
1 parent 55e6df5 commit 113c4af

12 files changed

+1268
-303
lines changed

ChairAnalyser.py

Lines changed: 155 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import matplotlib.pyplot as plt
55
from GeneralAnalyser import GeneralAnalyser
66

7+
# TODO: add the name because the same analyser can be used for many plots
78

89
class ChairAnalyser(GeneralAnalyser):
910

@@ -12,80 +13,181 @@ def __init__(self,
1213
pic_prefix,
1314
sensor_name,
1415
session_id,
15-
measurement_interval=0.01,
16-
measurements_per_batch=1000,
16+
events_intervals_list=None,
17+
interval=2,
18+
# measurement_interval=0.01,
19+
# measurements_per_batch=1000,
1720
name=None,
21+
reaction_multiplier=5,
1822
):
19-
super().__init__(df, pic_prefix, sensor_name, session_id)
23+
super().__init__(df, pic_prefix, sensor_name, session_id, name)
2024

21-
# self.df_chair = df_chair
22-
self.measurement_interval = measurement_interval
23-
self.pic_prefix = pic_prefix
24-
self.measurements_per_batch = measurements_per_batch
25-
self.name = name
25+
self.interval = interval
26+
self.reaction_multiplier = reaction_multiplier
27+
self.events_intervals_list = events_intervals_list
28+
# self.sensor_columns = ['acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z']
29+
self.sensor_columns = ['acc_x', 'gyro_x', 'acc_y', 'gyro_y', 'acc_z', 'gyro_z']
2630

27-
self.means, self.stds, medians = self.create_mean_stds()
31+
def get_floating_features(self, interval=2):
32+
# time_interval = f'{interval}s'
33+
time_interval = f'{int(interval * 1000)}ms'
2834

29-
def create_mean_stds(self, columns=('acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z')):
30-
df_chair = self.df.loc[:, columns]
31-
# df_chair = df_chair.loc[:, columns]
32-
# medians, lower_bounds, upper_bounds = np.percentile(df_chair, [50, percentile2crop, 100 - percentile2crop], axis=0)
35+
df2roll = self.df.loc[:, ['time'] + self.sensor_columns].set_index('time')
36+
df2roll.index = pd.to_timedelta(df2roll.index, unit='s')
37+
df_rolling = df2roll.rolling(time_interval) # Can't be centered by default
38+
stds = df_rolling.std()
39+
# stds.columns = [f'{column}_std_{time_interval}' for column in stds.columns]
40+
stds.columns = [f'{column}_std' for column in stds.columns]
41+
stds.reset_index(drop=True, inplace=True)
3342

34-
means = df_chair.mean(axis=0)
35-
medians = df_chair.median(axis=0)
36-
stds = df_chair.std(axis=0)
43+
return stds
3744

38-
return means, stds, medians
45+
def _append_floating_features(self, interval=2):
46+
floating_std = self.get_floating_features(interval)
3947

40-
def get_nonstationary_values_portion(self, n_sigma=3):
41-
means = self.means
42-
stds = self.stds
48+
self.df = pd.concat([self.df, floating_std], axis=1)
4349

44-
columns = stds.index
45-
df_chair = self.df.loc[:, columns]
4650

47-
lower_bounds = means - n_sigma * stds
48-
upper_bounds = means + n_sigma * stds
51+
def get_reactions_mask(self, floating_std, medians, reaction_multiplier):
52+
reaction_levels = medians * reaction_multiplier
53+
reactions_masks = floating_std > reaction_levels.values
4954

50-
low_values_means = (df_chair.loc[:, columns] < lower_bounds).mean()
51-
high_values_means = (df_chair.loc[:, columns] > upper_bounds).mean()
55+
return reactions_masks
5256

53-
nonstationary_values_portion = low_values_means + high_values_means
54-
nonstationary_values_portion.index = [colname + '__nonstationary_portion' for colname in nonstationary_values_portion.index]
55-
nonstationary_values_portion.name = self.name
57+
def get_events_masks_dict(self, events_intervals_list):
58+
events_masks_dict = {}
5659

57-
return nonstationary_values_portion
60+
for events_intervals in events_intervals_list:
61+
mask_interval = events_intervals.get_mask_intervals_union(self.df['time'])
62+
event_label = events_intervals.label
63+
events_masks_dict[event_label] = mask_interval
5864

59-
# def get_lean_back_portion(acc_z, means_stds=means_stds, n_sigma=5):
60-
def get_lean_back_portion(self, acc_z_threshold=0.97):
61-
df_chair = self.df
62-
lean_back_portion = (df_chair[['acc_z']] < acc_z_threshold).mean()
63-
lean_back_portion.index = ['lean_back_portion']
64-
lean_back_portion.name = self.name
65+
return events_masks_dict
66+
67+
def get_reaction_events_features(self, reactions_mask, events_masks_dict):
68+
reactions_mask_sum = reactions_mask.sum(axis=0)
6569

66-
return lean_back_portion
70+
reaction_events_features_dict = {}
6771

68-
def get_oscillation_intensity(self, percentile2crop=10, columns=('acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z')):
69-
df_chair = self.df.loc[:, columns]
70-
result = {}
72+
for event_label, event_mask in events_masks_dict.items():
73+
event_mask_sum = event_mask.sum()
74+
# print(type(reactions_mask), type(event_mask))
75+
reactions_mask_events = reactions_mask.values & event_mask.reshape(-1, 1)
76+
reactions_mask_events_sum = pd.Series(reactions_mask_events.sum(axis=0), index=reactions_mask_sum.index)
7177

72-
for column in columns:
73-
lower_bounds, upper_bounds = np.percentile(df_chair.loc[:, column], [percentile2crop, 100 - percentile2crop], axis=0)
74-
# intervals = upper_bounds - lower_bounds
75-
low_values_mask = (df_chair.loc[:, column] < lower_bounds)
76-
high_values_mask = (df_chair.loc[:, column] > upper_bounds)
78+
# events_in_reactions = reactions_mask_events_sum / reactions_mask_sum
79+
# events_in_reactions.index = [f'events_in_reactions__{event_label}__{index}' for index in events_in_reactions.index]
80+
# reaction_events_features_dict.update(events_in_reactions.to_dict())
7781

78-
normal_values_mask = (~low_values_mask) & (~high_values_mask)
82+
reactions_in_events = reactions_mask_events_sum / event_mask_sum
83+
# reactions_in_events.index = [f'reactions_in_events__{event_label}__{index}' for index in reactions_in_events.index]
84+
reactions_in_events.index = [f'moving_{event_label}_{index[:-4]}' for index in reactions_in_events.index]
85+
reaction_events_features_dict.update(reactions_in_events.to_dict())
7986

80-
usual_sitting_stds = df_chair.loc[normal_values_mask, column].std()
81-
oscillations = usual_sitting_stds# / intervals
82-
feature_name = f'{column}__oscillations'
83-
result[feature_name] = oscillations
87+
return reaction_events_features_dict
8488

85-
result = pd.Series(result)
86-
result.name = self.name
89+
def get_reaction_features(self, reactions_mask):
90+
reactions_mask_mean = reactions_mask.mean(axis=0)
91+
# reactions_mask_mean.index = [f'reactions_{index}' for index in reactions_mask_mean.index]
92+
reactions_mask_mean.index = [f'moving_{index[:-4]}' for index in reactions_mask_mean.index]
8793

88-
return result
94+
return reactions_mask_mean.to_dict()
95+
96+
def get_lean_back_portion(self, acc_z_threshold=0.97):
97+
lean_back_portion = (self.df[['acc_z']] < acc_z_threshold).mean()
98+
# lean_back_portion.index = ['lean_back_portion']
99+
# lean_back_portion.name = self.name
100+
101+
return {
102+
# 'lean_back_portion': lean_back_portion.values[0],
103+
'lean_back': lean_back_portion.values[0],
104+
}
105+
106+
def get_features(self, interval=None, reaction_multiplier=None):
107+
if interval is None:
108+
interval = self.interval
109+
110+
if reaction_multiplier is None:
111+
reaction_multiplier = self.reaction_multiplier
112+
113+
floating_std = self.get_floating_features(interval)
114+
floating_std_median = floating_std.quantile(0.5, axis=0)
115+
# floating_std_median.index = [f'median_{index}' for index in floating_std_median.index]
116+
floating_std_median.index = [f'med_{index}' for index in floating_std_median.index]
117+
118+
reactions_mask = self.get_reactions_mask(floating_std, floating_std_median, reaction_multiplier=reaction_multiplier)
119+
120+
reaction_features = self.get_reaction_features(reactions_mask)
121+
oscillations_features = floating_std_median.to_dict()
122+
lean_back_portion = self.get_lean_back_portion()
123+
124+
features_list = [reaction_features, oscillations_features, lean_back_portion]
125+
126+
if self.events_intervals_list is not None:
127+
events_masks_dict = self.get_events_masks_dict(self.events_intervals_list)
128+
reaction_events_features = self.get_reaction_events_features(reactions_mask, events_masks_dict)
129+
features_list.append(reaction_events_features)
130+
131+
all_features_dict = {}
132+
for features in features_list:
133+
all_features_dict.update(features)
134+
135+
all_features = pd.Series(all_features_dict, name=self.session_id)
136+
137+
return all_features
138+
139+
# # def create_mean_stds(self, columns=('acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z')):
140+
# def create_mean_stds(self):
141+
# df_chair = self.df.loc[:, self.sensor_columns]
142+
# # df_chair = df_chair.loc[:, columns]
143+
# # medians, lower_bounds, upper_bounds = np.percentile(df_chair, [50, percentile2crop, 100 - percentile2crop], axis=0)
144+
#
145+
# means = df_chair.mean(axis=0)
146+
# medians = df_chair.median(axis=0)
147+
# stds = df_chair.std(axis=0)
148+
#
149+
# return means, stds, medians
150+
#
151+
# def get_nonstationary_values_portion(self, n_sigma=3):
152+
# means = self.means
153+
# stds = self.stds
154+
#
155+
# columns = stds.index
156+
# df_chair = self.df.loc[:, columns]
157+
#
158+
# lower_bounds = means - n_sigma * stds
159+
# upper_bounds = means + n_sigma * stds
160+
#
161+
# low_values_means = (df_chair.loc[:, columns] < lower_bounds).mean()
162+
# high_values_means = (df_chair.loc[:, columns] > upper_bounds).mean()
163+
#
164+
# nonstationary_values_portion = low_values_means + high_values_means
165+
# nonstationary_values_portion.index = [colname + '__nonstationary_portion' for colname in nonstationary_values_portion.index]
166+
# nonstationary_values_portion.name = self.name
167+
#
168+
# return nonstationary_values_portion
169+
#
170+
# def get_oscillation_intensity(self, percentile2crop=10, columns=('acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z')):
171+
# df_chair = self.df.loc[:, columns]
172+
# result = {}
173+
#
174+
# for column in columns:
175+
# lower_bounds, upper_bounds = np.percentile(df_chair.loc[:, column], [percentile2crop, 100 - percentile2crop], axis=0)
176+
# # intervals = upper_bounds - lower_bounds
177+
# low_values_mask = (df_chair.loc[:, column] < lower_bounds)
178+
# high_values_mask = (df_chair.loc[:, column] > upper_bounds)
179+
#
180+
# normal_values_mask = (~low_values_mask) & (~high_values_mask)
181+
#
182+
# usual_sitting_stds = df_chair.loc[normal_values_mask, column].std()
183+
# oscillations = usual_sitting_stds# / intervals
184+
# feature_name = f'{column}__oscillations'
185+
# result[feature_name] = oscillations
186+
#
187+
# result = pd.Series(result)
188+
# result.name = self.name
189+
#
190+
# return result
89191

90192

91193

ChairGamedataProcessing.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import os
66
import joblib
77
from utils import normalize_MPU9250_data, split_df
8-
from ChairAnalyzerOld import ChairAnalyser
8+
# from ChairAnalyzerOld import ChairAnalyser
99
from datetime import datetime
1010

1111
plt.interactive(True)
@@ -59,7 +59,7 @@
5959
reaction_stats = pd.DataFrame(std_list).median() # It should be compared with mean std on the chair
6060
event_reactions_dict[name] = reaction_stats
6161

62-
df_event_reactions = pd.DataFrame(event_reactions_dict ) #.round(4).values
62+
df_event_reactions = pd.DataFrame(event_reactions_dict) #.round(4).values
6363

6464
features_dict = {}
6565

@@ -68,6 +68,16 @@
6868
feature_name = f"{sensor_name}__{column}"
6969
features_dict[feature_name] = df_event_reactions.loc[sensor_name, column]
7070

71+
### KDA-like objectives
72+
n_deaths = len(times_is_killed)
73+
n_kills = len(times_kills)
74+
75+
n_deaths = max(n_deaths, 0.001) # bound
76+
77+
kill_death_ratio = min(n_kills / n_deaths, 10)
78+
features_dict['Kill Death Ratio'] = kill_death_ratio
79+
# features_dict['kill_death_ratio'] = kill_death_ratio
80+
7181
game_events_features_dict[session_id] = features_dict
7282

7383

0 commit comments

Comments
 (0)