Skip to content

Commit bfc6c2c

Browse files
committed
Extended quantitative data analysis by using name-value pairs for computation of multiple values.
1 parent 99b6f8f commit bfc6c2c

10 files changed

+99
-77
lines changed

AnalysisTest/Test.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ void single_user_analysis() {
262262

263263
void synchrony_analysis(){
264264
std::vector<std::string> files;
265-
std::string directory = "C:\\Users\\Anton-Lammert\\Downloads\\PilotNew";
265+
std::string directory = "C:\\Users\\Anton-Lammert\\Downloads\\Test";
266266
if(!std::filesystem::exists(directory))
267267
return;
268268

@@ -286,11 +286,19 @@ void synchrony_analysis(){
286286
int participant_a_hand_right = meta_information.get_old_uuid("/Lobby-HMDUser/Camera Offset/RightHand Controller");
287287
int avatar_hand_right = meta_information.get_old_uuid("/__STUDY__/VisualStimulus/HandWaving/StudyHMDAvatar/Camera Offset/RightHand Controller");
288288

289-
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_synchrony_request_1 = std::make_shared<QuantitativeSynchronyAnalysisRequest>(participant_a_hand_left, avatar_hand_right, 0.3f);
290-
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_synchrony_request_2 = std::make_shared<QuantitativeSynchronyAnalysisRequest>(participant_a_hand_right, avatar_hand_right, 0.3f);
289+
float sampling_rate = 0.25f;
290+
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_synchrony_request_1 = std::make_shared<QuantitativeSynchronyAnalysisRequest>(participant_a_hand_left, avatar_hand_right, sampling_rate);
291+
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_synchrony_request_2 = std::make_shared<QuantitativeSynchronyAnalysisRequest>(participant_a_hand_right, avatar_hand_right, sampling_rate);
292+
293+
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_velocity_request_1 = std::make_shared<QuantitativeVelocityAnalysisRequest>(participant_a_hand_left, sampling_rate);
294+
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_velocity_request_2 = std::make_shared<QuantitativeVelocityAnalysisRequest>(participant_a_hand_right, sampling_rate);
295+
std::shared_ptr<QuantitativeTransformAnalysisRequest> quantitative_velocity_request_3 = std::make_shared<QuantitativeVelocityAnalysisRequest>(avatar_hand_right, sampling_rate);
291296

292297
manager.add_quantitative_analysis_request(quantitative_synchrony_request_1);
293298
manager.add_quantitative_analysis_request(quantitative_synchrony_request_2);
299+
manager.add_quantitative_analysis_request(quantitative_velocity_request_1);
300+
manager.add_quantitative_analysis_request(quantitative_velocity_request_2);
301+
manager.add_quantitative_analysis_request(quantitative_velocity_request_3);
294302

295303
manager.process_quantitative_analysis_requests_for_all_files();
296304
}

Src/Analysis/AnalysisManager.cpp

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,7 @@ void AnalysisManager::add_quantitative_analysis_request(std::shared_ptr<Quantita
378378
quantitative_analysis_queries.push_back(request);
379379
}
380380

381-
int AnalysisManager::process_quantitative_analysis_request(std::shared_ptr<QuantitativeAnalysisRequest> analysis_request,
382-
float *values, const std::string &file,
383-
const std::vector<TimeInterval> &intervals_to_investigate) const {
381+
std::vector<TimeBasedValue> AnalysisManager::process_quantitative_analysis_request(std::shared_ptr<QuantitativeAnalysisRequest> analysis_request, const std::string &file) const {
384382
std::ifstream transform_file(file + ".txt", std::ios::in | std::ios::binary);
385383
std::ifstream sound_file(file + "_sound.txt", std::ios::in | std::ios::binary);
386384
MetaInformation meta_info{file + ".recordmeta"};
@@ -431,25 +429,7 @@ int AnalysisManager::process_quantitative_analysis_request(std::shared_ptr<Quant
431429
Debug::Log("Reading sounds for analysis finished\n");
432430
}
433431

434-
result_values = analysis_request->get_result();
435-
int i = 0;
436-
for (auto &time_based_value: result_values) {
437-
if (!intervals_to_investigate.empty()) {
438-
for (auto const &interval_of_interest: intervals_to_investigate) {
439-
if (interval_of_interest.contains(time_based_value.time)) {
440-
values[i] = time_based_value.time;
441-
// TODO: handle return of more return values
442-
values[i + 1] = time_based_value.values[0];
443-
i += 2;
444-
}
445-
}
446-
} else {
447-
values[i] = time_based_value.time;
448-
values[i + 1] = time_based_value.values[0];
449-
i += 2;
450-
}
451-
}
452-
return result_values.size();
432+
return analysis_request->get_result();
453433
}
454434

455435
int AnalysisManager::process_quantitative_analysis_requests_for_all_files() {
@@ -499,21 +479,23 @@ void AnalysisManager::process_quantitative_analysis_requests_for_file(std::strin
499479
}
500480

501481
for (auto request: adapted_queries) {
502-
float values[5000];
503-
int value_count = process_quantitative_analysis_request(request, values, file, intervals_of_interest);
504-
std::cout << "Value count: " << value_count << "\n";
482+
std::vector<TimeBasedValue> results = process_quantitative_analysis_request(request, file);
483+
std::cout << "Value count: " << results.size() << "\n";
505484

506485
out << "AnalysisQuery,";
507486
out << request->get_description(current_meta_information) << ",";
508487

509488
out << "\n\n";
510489
out << "Time,";
511-
out << "Value\n";
512-
513-
for (int i = 0; i < value_count; ++i) {
514-
float time = values[i * 2];
515-
float value = values[i * 2 + 1];
516-
out << time << "," << value << "\n";
490+
for(auto & value : results[0].values)
491+
out << value.first << ",";
492+
out << "\n";
493+
494+
for (int i = 0; i < results.size(); ++i) {
495+
out << results[i].time << ",";
496+
for(auto & value : results[i].values)
497+
out << value.second << ",";
498+
out << "\n";
517499
}
518500

519501
out << "\n\n";

Src/Analysis/AnalysisManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class AnalysisManager {
8989

9090
void add_quantitative_analysis_request(std::shared_ptr<QuantitativeAnalysisRequest> request);
9191

92-
int process_quantitative_analysis_request(std::shared_ptr<QuantitativeAnalysisRequest> analysis_request, float* values, std::string const& file, std::vector<TimeInterval> const& intervals_to_investigate) const;
92+
std::vector<TimeBasedValue> process_quantitative_analysis_request(std::shared_ptr<QuantitativeAnalysisRequest> analysis_request, std::string const& file) const;
9393

9494
int process_quantitative_analysis_requests_for_all_files();
9595

Src/Analysis/AnalysisStructs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@
4040

4141
#include <algorithm>
4242
#include <vector>
43+
#include <string>
4344

4445
enum TransformAnalysisType{
4546
ContainmentAnalysis, DistanceAnalysis, GazeAnalysis, RotationAnalysis, VelocityAnalysis, PositionAdjustmentAnalysis, SynchronyAnalysis
4647
};
4748

4849
struct TimeBasedValue{
4950
float time;
50-
std::vector<float> values;
51+
std::vector<std::pair<std::string,float>> values;
5152
};
5253

5354
struct TimeInterval{

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeDistanceAnalysisRequest.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ void QuantitativeDistanceAnalysisRequest::process_request(std::shared_ptr<Transf
8484
if((t_data->id == id_a || t_data->id == id_b) && present_a && present_b && current_a.time >= current_b.time){
8585
glm::vec3 dir = current_b.global_position - current_a.global_position;
8686
if(current_t - last_value_time > 1.0f/temporal_sampling_rate){
87-
values.push_back(TimeBasedValue{current_t, {glm::length(dir)}});
87+
std::pair<std::string, float> dist = {"Distance",glm::length(dir)};
88+
values.push_back(TimeBasedValue{current_t, {dist}});
8889
last_value_time = current_t;
8990
}
9091
}

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeGazeAnalysisRequest.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ void QuantitativeGazeAnalysisRequest::process_request(std::shared_ptr<TransformD
7272
glm::mat4 TRS = translate * rotate * scale;
7373
glm::vec4 local_pos = glm::inverse(TRS) * glm::vec4{current_b.global_position,1.0f};
7474
if(current_t - last_value_time > 1.0f/temporal_sampling_rate){
75-
values.push_back(TimeBasedValue{current_t, {local_pos.x/local_pos.w,local_pos.y/local_pos.w,local_pos.z,local_pos.w}});
75+
std::pair<std::string, float> x = {"Pos b.x local in a",local_pos.x/local_pos.w};
76+
std::pair<std::string, float> y = {"Pos b.y local in a",local_pos.y/local_pos.w};
77+
std::pair<std::string, float> z = {"Pos b.z local in a",local_pos.z/local_pos.w};
78+
values.push_back(TimeBasedValue{current_t, {x,y,z}});
7679
last_value_time = current_t;
7780
}
7881
}

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeRotationAnalysisRequest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ void QuantitativeRotationAnalysisRequest::process_request(std::shared_ptr<Transf
7171
max_angle_diff = angle_diff_degrees;
7272
}
7373
}
74-
75-
values.push_back(TimeBasedValue{t_data->time, {max_angle_diff}});
74+
std::pair<std::string, float> angle_diff = {"Max angle diff", max_angle_diff};
75+
values.push_back(TimeBasedValue{t_data->time, {angle_diff}});
7676
last_value_time = t_data->time;
7777
}
7878
}

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeSynchronyAnalysisRequest.cpp

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -30,41 +30,61 @@ void QuantitativeSynchronyAnalysisRequest::process_request(std::shared_ptr<Trans
3030

3131
if (t_data->time > current_t) {
3232
current_t = t_data->time;
33-
while (recent_data_a.size() > 0 &&recent_data_a.front().time < current_t - temporal_sampling_rate) {
33+
while (recent_data_a.size() > 0 &&recent_data_a.front().time < current_t - (1.0f/temporal_sampling_rate)) {
3434
recent_data_a.pop_front();
3535
}
36-
while (recent_data_b.size() > 0 && recent_data_b.front().time < current_t - temporal_sampling_rate) {
36+
while (recent_data_b.size() > 0 && recent_data_b.front().time < current_t - (1.0f/temporal_sampling_rate)) {
3737
recent_data_b.pop_front();
3838
}
39-
std::vector<float> a_velocities;
40-
if (recent_data_a.size() > 1) {
41-
for (int i = 1; i < recent_data_a.size(); i++) {
42-
TransformData last = recent_data_a[i - 1];
43-
TransformData current = recent_data_a[i];
44-
float pos_diff = glm::length(current.global_position - last.global_position);
45-
float time_diff = current.time - last.time;
46-
a_velocities.push_back(std::abs(pos_diff / time_diff));
39+
40+
if(recent_data_a.size() > 0 && std::abs(recent_data_a.front().time - current_t) > (1.0f/temporal_sampling_rate) - 0.01f) {
41+
std::vector<float> a_velocities;
42+
if (recent_data_a.size() > 1) {
43+
for (int i = 1; i < recent_data_a.size(); i++) {
44+
TransformData last = recent_data_a[i - 1];
45+
TransformData current = recent_data_a[i];
46+
float pos_diff = glm::length(current.global_position - last.global_position);
47+
float time_diff = current.time - last.time;
48+
float velocity = std::abs(pos_diff / time_diff);
49+
if(velocity < 0.1f)
50+
velocity = 0.0f;
51+
a_velocities.push_back(velocity);
52+
}
4753
}
48-
}
4954

50-
std::vector<float> b_velocities;
51-
if (recent_data_b.size() > 1) {
52-
for (int i = 1; i < recent_data_b.size(); i++) {
53-
TransformData last = recent_data_b[i - 1];
54-
TransformData current = recent_data_b[i];
55-
float pos_diff = glm::length(current.global_position - last.global_position);
56-
float time_diff = current.time - last.time;
57-
b_velocities.push_back(std::abs(pos_diff / time_diff));
55+
std::vector<float> b_velocities;
56+
if (recent_data_b.size() > 1) {
57+
for (int i = 1; i < recent_data_b.size(); i++) {
58+
TransformData last = recent_data_b[i - 1];
59+
TransformData current = recent_data_b[i];
60+
float pos_diff = glm::length(current.global_position - last.global_position);
61+
float time_diff = current.time - last.time;
62+
float velocity = std::abs(pos_diff / time_diff);
63+
if(velocity < 0.1f)
64+
velocity = 0.0f;
65+
b_velocities.push_back(velocity);
66+
}
5867
}
59-
}
6068

61-
std::vector<float> a_ranks = rank_data(a_velocities);
62-
std::vector<float> b_ranks = rank_data(b_velocities);
69+
std::vector<float> a_ranks = rank_data(a_velocities);
70+
std::vector<float> b_ranks = rank_data(b_velocities);
71+
72+
if(a_velocities.size() == b_velocities.size()) {
73+
float pearson_corr = pearson_correlation(a_velocities, b_velocities);
74+
float spearman_corr = pearson_correlation(a_ranks, b_ranks);
6375

64-
float spearman_corr = correlation(a_ranks, b_ranks);
65-
if(current_t > last_value_time + (1.0f /temporal_sampling_rate)) {
66-
values.push_back(TimeBasedValue{current_t, {spearman_corr}});
67-
last_value_time = current_t;
76+
if(std::isnan(pearson_corr))
77+
pearson_corr = 0.0f;
78+
if(std::isnan(spearman_corr))
79+
spearman_corr = 0.0f;
80+
81+
if (current_t > last_value_time + (1.0f / temporal_sampling_rate)) {
82+
std::pair<std::string, float> s_corr = {"Spearman Correlation", spearman_corr};
83+
std::pair<std::string, float> p_corr = {"Pearson Correlation", pearson_corr};
84+
values.push_back(TimeBasedValue{current_t, {s_corr, p_corr}});
85+
last_value_time = current_t;
86+
}
87+
}
6888
}
6989
}
7090
}
@@ -115,23 +135,29 @@ std::vector<float> QuantitativeSynchronyAnalysisRequest::rank_data(std::vector<f
115135
return ranks;
116136
}
117137

118-
float QuantitativeSynchronyAnalysisRequest::correlation(const std::vector<float> &a, const std::vector<float> &b) {
138+
float QuantitativeSynchronyAnalysisRequest::pearson_correlation(const std::vector<float> &a, const std::vector<float> &b) {
119139
if(a.size() != b.size() || a.empty()) {
120140
//Debug::Log("Error: Cannot calculate correlation between vectors of different sizes");
121141
return 0;
122142
}
123143
float sum_a = 0, sum_b = 0, sum_ab = 0, square_sum_a = 0, square_sum_b = 0;
124144

125145
for (int i = 0; i < a.size(); i++) {
126-
sum_a = sum_a + a[i];
127-
sum_b = sum_b + b[i];
128-
sum_ab = sum_ab + a[i] * b[i];
129-
square_sum_a = square_sum_a + a[i] * a[i];
130-
square_sum_b = square_sum_b + b[i] * b[i];
146+
sum_a += a[i];
147+
sum_b += b[i];
131148
}
132149

133-
float corr = (float) (a.size() * sum_ab - sum_a * sum_b) /
134-
sqrt((a.size() * square_sum_a - sum_a * sum_a) * (a.size() * square_sum_b - sum_b * sum_b));
150+
float mean_a = sum_a / a.size();
151+
float mean_b = sum_b / b.size();
135152

136-
return corr;
153+
float top = 0.0f;
154+
float bottom_l = 0.0f;
155+
float bottom_r = 0.0f;
156+
157+
for(int i = 0; i < a.size(); ++i){
158+
top += (a[i] - mean_a) * (b[i] - mean_b);
159+
bottom_l += (a[i] - mean_a) * (a[i] - mean_a);
160+
bottom_r += (b[i] - mean_b) * (b[i] - mean_b);
161+
}
162+
return top / (std::sqrt(bottom_l) * std::sqrt(bottom_r));
137163
}

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeSynchronyAnalysisRequest.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class QuantitativeSynchronyAnalysisRequest : public QuantitativeTransformAnalysi
4040
private:
4141
std::vector<float> rank_data(std::vector<float> const& data);
4242

43-
float correlation(std::vector<float> const& a, std::vector<float> const& b);
43+
float pearson_correlation(std::vector<float> const& a, std::vector<float> const& b);
4444
};
4545

4646

Src/Analysis/QuantitativeAnalysis/TransformAnalysis/QuantitativeVelocityAnalysisRequest.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ void QuantitativeVelocityAnalysisRequest::process_request(std::shared_ptr<Transf
9090
float time_diff = last.time - previous.time;
9191
float current_velocity = std::abs(pos_diff / time_diff);
9292
if(last.time > last_value_time + (1.0f /temporal_sampling_rate)) {
93-
values.push_back(TimeBasedValue{last.time, {current_velocity}});
93+
std::pair<std::string, float> vel = {"Velocity",current_velocity};
94+
values.push_back(TimeBasedValue{last.time, {vel}});
9495
last_value_time = last.time;
9596
}
9697
}

0 commit comments

Comments
 (0)