compileprofile-spacetests 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/emotions.d.ts +10 -0
- package/dist/cjs/emotions.js +54 -0
- package/dist/cjs/gonogo.d.ts +10 -3
- package/dist/cjs/gonogo.js +64 -23
- package/dist/cjs/index.d.ts +9 -5
- package/dist/cjs/index.js +11 -1
- package/dist/cjs/nback.d.ts +8 -8
- package/dist/cjs/spatial-cognition.d.ts +4 -4
- package/dist/cjs/spatial-cognition.js +3 -7
- package/dist/esm/emotions.d.ts +10 -0
- package/dist/esm/emotions.js +49 -0
- package/dist/esm/gonogo.d.ts +10 -3
- package/dist/esm/gonogo.js +60 -24
- package/dist/esm/index.d.ts +9 -5
- package/dist/esm/index.js +9 -1
- package/dist/esm/nback.d.ts +8 -8
- package/dist/esm/spatial-cognition.d.ts +4 -4
- package/dist/esm/spatial-cognition.js +3 -7
- package/example-data/spatial-cognition.json +1 -1
- package/package.json +2 -2
- package/src/__tests__/integration/emotions.test.ts +65 -0
- package/src/__tests__/integration/gonogo.test.ts +81 -0
- package/src/__tests__/integration/spatial-cognition.test.ts +8 -1
- package/src/emotions.ts +59 -0
- package/src/gonogo.ts +69 -30
- package/src/index.ts +16 -5
- package/src/nback.ts +8 -8
- package/src/spatial-cognition.ts +7 -11
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface EmotionResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
6
|
+
}
|
|
7
|
+
declare const emotion_calculate_results: (obj: any[]) => EmotionResultsStructure;
|
|
8
|
+
declare const emotion_results: (obj: any[]) => EmotionResultsStructure;
|
|
9
|
+
declare const emotion_extract_trials: (obj: any[]) => any[];
|
|
10
|
+
export { EmotionResultsStructure, emotion_calculate_results, emotion_extract_trials, emotion_results };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emotion_results = exports.emotion_extract_trials = exports.emotion_calculate_results = void 0;
|
|
4
|
+
var emotion_calculate_results = function (obj) {
|
|
5
|
+
var trials = emotion_extract_trials(obj);
|
|
6
|
+
// throw if trials is empty
|
|
7
|
+
if (trials.length === 0) {
|
|
8
|
+
throw new Error("No trials found");
|
|
9
|
+
}
|
|
10
|
+
return emotion_results(trials);
|
|
11
|
+
};
|
|
12
|
+
exports.emotion_calculate_results = emotion_calculate_results;
|
|
13
|
+
var emotion_results = function (obj) {
|
|
14
|
+
// throw error if obj is empty
|
|
15
|
+
if (obj.length === 0) {
|
|
16
|
+
throw new Error("No trials found");
|
|
17
|
+
}
|
|
18
|
+
var results = {
|
|
19
|
+
n: obj.length,
|
|
20
|
+
avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
|
|
21
|
+
avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
|
|
22
|
+
performance: NaN
|
|
23
|
+
};
|
|
24
|
+
var best_score = 1000;
|
|
25
|
+
var worst_score = 10000;
|
|
26
|
+
var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
27
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
28
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
29
|
+
return results;
|
|
30
|
+
};
|
|
31
|
+
exports.emotion_results = emotion_results;
|
|
32
|
+
var emotion_extract_trials = function (obj) {
|
|
33
|
+
var emotionMap = ["neutral", "sad", "happy", "surprised", "angry"];
|
|
34
|
+
// filter trials where response and rt are defined and not null
|
|
35
|
+
var trials = obj.filter(function (o) { return 'response' in o && 'rt' in o && 'emotion' in o; });
|
|
36
|
+
trials = trials.filter(function (o) { return o.response !== null && o.rt !== null; });
|
|
37
|
+
trials.forEach(function (o) {
|
|
38
|
+
var match = o.emotion.match(/\/([^/]+)_([0-9]+)\.png/);
|
|
39
|
+
if (match) {
|
|
40
|
+
o.stimulus = match[0];
|
|
41
|
+
o.emotion = match[1];
|
|
42
|
+
o.image_number = match[2];
|
|
43
|
+
//this is <emotion>_<number>.png
|
|
44
|
+
o.image = "".concat(match[1], "_").concat(match[2], ".png");
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
trials.forEach(function (o) {
|
|
48
|
+
o.emotion_response = emotionMap[o.response] || "unknown";
|
|
49
|
+
o.correct = o.emotion === o.emotion_response;
|
|
50
|
+
// in the older ones there were 15 trials per rotation
|
|
51
|
+
});
|
|
52
|
+
return trials;
|
|
53
|
+
};
|
|
54
|
+
exports.emotion_extract_trials = emotion_extract_trials;
|
package/dist/cjs/gonogo.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
interface GonogoResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
6
|
+
}
|
|
7
|
+
declare const gonogo_calculate_results: (data: any[]) => GonogoResultsStructure;
|
|
8
|
+
declare const gonogo_extract_trials: (obj: any[]) => any[];
|
|
9
|
+
declare const gonogo_results: (data: any[]) => GonogoResultsStructure;
|
|
10
|
+
export { GonogoResultsStructure, gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
|
package/dist/cjs/gonogo.js
CHANGED
|
@@ -1,30 +1,71 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// df <- as.data.frame(fromJSON(arr[[1]]))
|
|
5
|
-
// GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
|
|
6
|
-
// df <- filter(df, !is.na(image))
|
|
7
|
-
// df <- select(df, trial_index, time_elapsed, rt,
|
|
8
|
-
// response, block_number, image)
|
|
9
|
-
// df$image <- gsub(GONOGO_IMAGE_PATH, "", df$image)
|
|
10
|
-
// df$image <- gsub(".png", "", df$image)
|
|
11
|
-
// df <- df %>%
|
|
12
|
-
// mutate(
|
|
13
|
-
// should_go = case_when(
|
|
14
|
-
// block_number == 1 & grepl("astronaut_trans_1", image) ~ TRUE,
|
|
15
|
-
// block_number == 2 & grepl("alien_trans_1", image) ~ TRUE,
|
|
16
|
-
// block_number == 3 & grepl("rocket_trans_1", image) ~ TRUE,
|
|
17
|
-
// block_number == 4 & !grepl("rocket_trans_1", image) ~ TRUE,
|
|
18
|
-
// TRUE ~ FALSE),
|
|
19
|
-
// did_go = !is.na(response),
|
|
20
|
-
// correct = should_go == did_go
|
|
21
|
-
// )
|
|
22
|
-
// return(df)
|
|
23
|
-
// }
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gonogo_results = exports.gonogo_extract_trials = exports.gonogo_calculate_results = void 0;
|
|
24
4
|
var gonogo_calculate_results = function (data) {
|
|
5
|
+
var trials = gonogo_extract_trials(data);
|
|
6
|
+
var results = gonogo_results(trials);
|
|
7
|
+
return results;
|
|
25
8
|
};
|
|
26
|
-
|
|
9
|
+
exports.gonogo_calculate_results = gonogo_calculate_results;
|
|
10
|
+
var gonogo_extract_trials = function (obj) {
|
|
27
11
|
// GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
|
|
12
|
+
var trials = obj.filter(function (o) { return 'image' in o && o.image !== undefined; });
|
|
13
|
+
trials.forEach(function (o) {
|
|
14
|
+
// image is in format <stimulus>_trans_<number>.png
|
|
15
|
+
// extract the stimulus and number
|
|
16
|
+
// "image": "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
|
|
17
|
+
// i need to extract the iamge name from the url
|
|
18
|
+
var match = o.image.match(/([^/]+)_(\d+)\.png$/);
|
|
19
|
+
if (match) {
|
|
20
|
+
o.stimulus = match[0];
|
|
21
|
+
o.stimulustype = match[1];
|
|
22
|
+
o.image_number = match[2];
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.warn('Image format did not match expected pattern:', o.image);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
o.should_go = false;
|
|
29
|
+
o.did_go = o.response !== null;
|
|
30
|
+
switch (o.block_number) {
|
|
31
|
+
case 1:
|
|
32
|
+
o.should_go = o.stimulus == "astronaut_trans_1.png";
|
|
33
|
+
break;
|
|
34
|
+
case 2:
|
|
35
|
+
o.should_go = o.stimulus == "alien_trans_1.png";
|
|
36
|
+
break;
|
|
37
|
+
case 3:
|
|
38
|
+
o.should_go = o.stimulus == "rocket_trans_1.png";
|
|
39
|
+
break;
|
|
40
|
+
case 4:
|
|
41
|
+
// should go in all cases where the goal is NOT the rocket
|
|
42
|
+
o.should_go = !(o.stimulus == "rocket_trans_1.png");
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
o.should_go = false;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
o.correct = o.should_go == o.did_go;
|
|
49
|
+
});
|
|
50
|
+
return trials;
|
|
28
51
|
};
|
|
52
|
+
exports.gonogo_extract_trials = gonogo_extract_trials;
|
|
29
53
|
var gonogo_results = function (data) {
|
|
54
|
+
// throw error if obj is empty
|
|
55
|
+
if (data.length === 0) {
|
|
56
|
+
throw new Error("No trials found");
|
|
57
|
+
}
|
|
58
|
+
var results = {
|
|
59
|
+
n: data.length,
|
|
60
|
+
avg_rt: data.reduce(function (a, b) { return a + b.rt; }, 0) / data.length,
|
|
61
|
+
avg_acc: data.reduce(function (a, b) { return a + b.correct; }, 0) / data.length,
|
|
62
|
+
performance: NaN
|
|
63
|
+
};
|
|
64
|
+
var best_score = 300;
|
|
65
|
+
var worst_score = 5000;
|
|
66
|
+
var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
67
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
68
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
69
|
+
return results;
|
|
30
70
|
};
|
|
71
|
+
exports.gonogo_results = gonogo_results;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { NbackResultsStructure } from './nback';
|
|
2
|
+
import { SpatialResultsStructure } from './spatial-cognition';
|
|
3
|
+
import { GonogoResultsStructure } from './gonogo';
|
|
4
|
+
import { EmotionResultsStructure } from './emotions';
|
|
5
|
+
declare const NbackResults: (obj: any[]) => NbackResultsStructure;
|
|
6
|
+
declare const SpatialCognitionResults: (obj: any[]) => SpatialResultsStructure;
|
|
7
|
+
declare const GonogoResults: (obj: any[]) => GonogoResultsStructure;
|
|
8
|
+
declare const EmotionResults: (obj: any[]) => EmotionResultsStructure;
|
|
9
|
+
export { NbackResults, SpatialCognitionResults, EmotionResults, GonogoResults };
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SpatialCognitionResults = exports.NbackResults = void 0;
|
|
3
|
+
exports.GonogoResults = exports.EmotionResults = exports.SpatialCognitionResults = exports.NbackResults = void 0;
|
|
4
4
|
var nback_1 = require("./nback");
|
|
5
5
|
var spatial_cognition_1 = require("./spatial-cognition");
|
|
6
|
+
var gonogo_1 = require("./gonogo");
|
|
7
|
+
var emotions_1 = require("./emotions");
|
|
6
8
|
var NbackResults = function (obj) {
|
|
7
9
|
return (0, nback_1.nback_calculate_results)(obj);
|
|
8
10
|
};
|
|
@@ -11,3 +13,11 @@ var SpatialCognitionResults = function (obj) {
|
|
|
11
13
|
return (0, spatial_cognition_1.spatial_calculate_results)(obj);
|
|
12
14
|
};
|
|
13
15
|
exports.SpatialCognitionResults = SpatialCognitionResults;
|
|
16
|
+
var GonogoResults = function (obj) {
|
|
17
|
+
return (0, gonogo_1.gonogo_calculate_results)(obj);
|
|
18
|
+
};
|
|
19
|
+
exports.GonogoResults = GonogoResults;
|
|
20
|
+
var EmotionResults = function (obj) {
|
|
21
|
+
return (0, emotions_1.emotion_calculate_results)(obj);
|
|
22
|
+
};
|
|
23
|
+
exports.EmotionResults = EmotionResults;
|
package/dist/cjs/nback.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
declare const nback_calculate_results: (obj: any[]) =>
|
|
1
|
+
declare const nback_calculate_results: (obj: any[]) => NbackResultsStructure;
|
|
2
2
|
declare const nback_extract_trials: (obj: any[]) => any[];
|
|
3
|
-
interface
|
|
3
|
+
interface NbackTrialResultsStructure {
|
|
4
4
|
n: number;
|
|
5
5
|
avg_rt: number;
|
|
6
6
|
avg_acc: number;
|
|
7
7
|
}
|
|
8
|
-
interface
|
|
9
|
-
total_trials:
|
|
10
|
-
target_trials:
|
|
11
|
-
non_target_trials:
|
|
8
|
+
interface NbackResultsStructure {
|
|
9
|
+
total_trials: NbackTrialResultsStructure;
|
|
10
|
+
target_trials: NbackTrialResultsStructure;
|
|
11
|
+
non_target_trials: NbackTrialResultsStructure;
|
|
12
12
|
performance: number;
|
|
13
13
|
}
|
|
14
|
-
declare const nback_results: (trials: any[]) =>
|
|
15
|
-
export { nback_extract_trials, nback_results, nback_calculate_results,
|
|
14
|
+
declare const nback_results: (trials: any[]) => NbackResultsStructure;
|
|
15
|
+
export { nback_extract_trials, nback_results, nback_calculate_results, NbackResultsStructure };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
interface
|
|
1
|
+
interface SpatialResultsStructure {
|
|
2
2
|
n: number;
|
|
3
3
|
avg_rt: number;
|
|
4
4
|
avg_acc: number;
|
|
5
5
|
performance: number;
|
|
6
6
|
}
|
|
7
|
-
declare const spatial_calculate_results: (obj: any[]) =>
|
|
7
|
+
declare const spatial_calculate_results: (obj: any[]) => SpatialResultsStructure;
|
|
8
8
|
declare const spatial_extract_trials: (obj: any[]) => any[];
|
|
9
|
-
declare const spatial_results: (obj: any[]) =>
|
|
9
|
+
declare const spatial_results: (obj: any[]) => SpatialResultsStructure;
|
|
10
10
|
declare const spatial_extract_image_info: (obj: any[]) => any[];
|
|
11
|
-
export { spatial_extract_image_info, spatial_extract_trials, spatial_results, spatial_calculate_results,
|
|
11
|
+
export { spatial_extract_image_info, spatial_extract_trials, spatial_results, spatial_calculate_results, SpatialResultsStructure };
|
|
@@ -23,13 +23,9 @@ var spatial_results = function (obj) {
|
|
|
23
23
|
var best_score = 1000;
|
|
24
24
|
var worst_score = 10000;
|
|
25
25
|
// results.avg_acc to the power of 5
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
if (performance > worst_score) {
|
|
31
|
-
performance = worst_score;
|
|
32
|
-
}
|
|
26
|
+
//let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
27
|
+
var performance = results.avg_rt / (results.avg_acc + 0.001);
|
|
28
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
33
29
|
// convert to 0-100 where 100 is the best (200)
|
|
34
30
|
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
35
31
|
return results;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface EmotionResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
6
|
+
}
|
|
7
|
+
declare const emotion_calculate_results: (obj: any[]) => EmotionResultsStructure;
|
|
8
|
+
declare const emotion_results: (obj: any[]) => EmotionResultsStructure;
|
|
9
|
+
declare const emotion_extract_trials: (obj: any[]) => any[];
|
|
10
|
+
export { EmotionResultsStructure, emotion_calculate_results, emotion_extract_trials, emotion_results };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var emotion_calculate_results = function (obj) {
|
|
2
|
+
var trials = emotion_extract_trials(obj);
|
|
3
|
+
// throw if trials is empty
|
|
4
|
+
if (trials.length === 0) {
|
|
5
|
+
throw new Error("No trials found");
|
|
6
|
+
}
|
|
7
|
+
return emotion_results(trials);
|
|
8
|
+
};
|
|
9
|
+
var emotion_results = function (obj) {
|
|
10
|
+
// throw error if obj is empty
|
|
11
|
+
if (obj.length === 0) {
|
|
12
|
+
throw new Error("No trials found");
|
|
13
|
+
}
|
|
14
|
+
var results = {
|
|
15
|
+
n: obj.length,
|
|
16
|
+
avg_rt: obj.reduce(function (a, b) { return a + b.rt; }, 0) / obj.length,
|
|
17
|
+
avg_acc: obj.reduce(function (a, b) { return a + b.correct; }, 0) / obj.length,
|
|
18
|
+
performance: NaN
|
|
19
|
+
};
|
|
20
|
+
var best_score = 1000;
|
|
21
|
+
var worst_score = 10000;
|
|
22
|
+
var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
23
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
24
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
25
|
+
return results;
|
|
26
|
+
};
|
|
27
|
+
var emotion_extract_trials = function (obj) {
|
|
28
|
+
var emotionMap = ["neutral", "sad", "happy", "surprised", "angry"];
|
|
29
|
+
// filter trials where response and rt are defined and not null
|
|
30
|
+
var trials = obj.filter(function (o) { return 'response' in o && 'rt' in o && 'emotion' in o; });
|
|
31
|
+
trials = trials.filter(function (o) { return o.response !== null && o.rt !== null; });
|
|
32
|
+
trials.forEach(function (o) {
|
|
33
|
+
var match = o.emotion.match(/\/([^/]+)_([0-9]+)\.png/);
|
|
34
|
+
if (match) {
|
|
35
|
+
o.stimulus = match[0];
|
|
36
|
+
o.emotion = match[1];
|
|
37
|
+
o.image_number = match[2];
|
|
38
|
+
//this is <emotion>_<number>.png
|
|
39
|
+
o.image = "".concat(match[1], "_").concat(match[2], ".png");
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
trials.forEach(function (o) {
|
|
43
|
+
o.emotion_response = emotionMap[o.response] || "unknown";
|
|
44
|
+
o.correct = o.emotion === o.emotion_response;
|
|
45
|
+
// in the older ones there were 15 trials per rotation
|
|
46
|
+
});
|
|
47
|
+
return trials;
|
|
48
|
+
};
|
|
49
|
+
export { emotion_calculate_results, emotion_extract_trials, emotion_results };
|
package/dist/esm/gonogo.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
interface GonogoResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
6
|
+
}
|
|
7
|
+
declare const gonogo_calculate_results: (data: any[]) => GonogoResultsStructure;
|
|
8
|
+
declare const gonogo_extract_trials: (obj: any[]) => any[];
|
|
9
|
+
declare const gonogo_results: (data: any[]) => GonogoResultsStructure;
|
|
10
|
+
export { GonogoResultsStructure, gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
|
package/dist/esm/gonogo.js
CHANGED
|
@@ -1,30 +1,66 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// gonogo_create_trial_table <- function(txt) {
|
|
3
|
-
// arr <- fromJSON(txt)
|
|
4
|
-
// df <- as.data.frame(fromJSON(arr[[1]]))
|
|
5
|
-
// GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
|
|
6
|
-
// df <- filter(df, !is.na(image))
|
|
7
|
-
// df <- select(df, trial_index, time_elapsed, rt,
|
|
8
|
-
// response, block_number, image)
|
|
9
|
-
// df$image <- gsub(GONOGO_IMAGE_PATH, "", df$image)
|
|
10
|
-
// df$image <- gsub(".png", "", df$image)
|
|
11
|
-
// df <- df %>%
|
|
12
|
-
// mutate(
|
|
13
|
-
// should_go = case_when(
|
|
14
|
-
// block_number == 1 & grepl("astronaut_trans_1", image) ~ TRUE,
|
|
15
|
-
// block_number == 2 & grepl("alien_trans_1", image) ~ TRUE,
|
|
16
|
-
// block_number == 3 & grepl("rocket_trans_1", image) ~ TRUE,
|
|
17
|
-
// block_number == 4 & !grepl("rocket_trans_1", image) ~ TRUE,
|
|
18
|
-
// TRUE ~ FALSE),
|
|
19
|
-
// did_go = !is.na(response),
|
|
20
|
-
// correct = should_go == did_go
|
|
21
|
-
// )
|
|
22
|
-
// return(df)
|
|
23
|
-
// }
|
|
24
1
|
var gonogo_calculate_results = function (data) {
|
|
2
|
+
var trials = gonogo_extract_trials(data);
|
|
3
|
+
var results = gonogo_results(trials);
|
|
4
|
+
return results;
|
|
25
5
|
};
|
|
26
|
-
var gonogo_extract_trials = function (
|
|
6
|
+
var gonogo_extract_trials = function (obj) {
|
|
27
7
|
// GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
|
|
8
|
+
var trials = obj.filter(function (o) { return 'image' in o && o.image !== undefined; });
|
|
9
|
+
trials.forEach(function (o) {
|
|
10
|
+
// image is in format <stimulus>_trans_<number>.png
|
|
11
|
+
// extract the stimulus and number
|
|
12
|
+
// "image": "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
|
|
13
|
+
// i need to extract the iamge name from the url
|
|
14
|
+
var match = o.image.match(/([^/]+)_(\d+)\.png$/);
|
|
15
|
+
if (match) {
|
|
16
|
+
o.stimulus = match[0];
|
|
17
|
+
o.stimulustype = match[1];
|
|
18
|
+
o.image_number = match[2];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
console.warn('Image format did not match expected pattern:', o.image);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
o.should_go = false;
|
|
25
|
+
o.did_go = o.response !== null;
|
|
26
|
+
switch (o.block_number) {
|
|
27
|
+
case 1:
|
|
28
|
+
o.should_go = o.stimulus == "astronaut_trans_1.png";
|
|
29
|
+
break;
|
|
30
|
+
case 2:
|
|
31
|
+
o.should_go = o.stimulus == "alien_trans_1.png";
|
|
32
|
+
break;
|
|
33
|
+
case 3:
|
|
34
|
+
o.should_go = o.stimulus == "rocket_trans_1.png";
|
|
35
|
+
break;
|
|
36
|
+
case 4:
|
|
37
|
+
// should go in all cases where the goal is NOT the rocket
|
|
38
|
+
o.should_go = !(o.stimulus == "rocket_trans_1.png");
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
o.should_go = false;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
o.correct = o.should_go == o.did_go;
|
|
45
|
+
});
|
|
46
|
+
return trials;
|
|
28
47
|
};
|
|
29
48
|
var gonogo_results = function (data) {
|
|
49
|
+
// throw error if obj is empty
|
|
50
|
+
if (data.length === 0) {
|
|
51
|
+
throw new Error("No trials found");
|
|
52
|
+
}
|
|
53
|
+
var results = {
|
|
54
|
+
n: data.length,
|
|
55
|
+
avg_rt: data.reduce(function (a, b) { return a + b.rt; }, 0) / data.length,
|
|
56
|
+
avg_acc: data.reduce(function (a, b) { return a + b.correct; }, 0) / data.length,
|
|
57
|
+
performance: NaN
|
|
58
|
+
};
|
|
59
|
+
var best_score = 300;
|
|
60
|
+
var worst_score = 5000;
|
|
61
|
+
var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
62
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
63
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
64
|
+
return results;
|
|
30
65
|
};
|
|
66
|
+
export { gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { NbackResultsStructure } from './nback';
|
|
2
|
+
import { SpatialResultsStructure } from './spatial-cognition';
|
|
3
|
+
import { GonogoResultsStructure } from './gonogo';
|
|
4
|
+
import { EmotionResultsStructure } from './emotions';
|
|
5
|
+
declare const NbackResults: (obj: any[]) => NbackResultsStructure;
|
|
6
|
+
declare const SpatialCognitionResults: (obj: any[]) => SpatialResultsStructure;
|
|
7
|
+
declare const GonogoResults: (obj: any[]) => GonogoResultsStructure;
|
|
8
|
+
declare const EmotionResults: (obj: any[]) => EmotionResultsStructure;
|
|
9
|
+
export { NbackResults, SpatialCognitionResults, EmotionResults, GonogoResults };
|
package/dist/esm/index.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { nback_calculate_results } from './nback';
|
|
2
2
|
import { spatial_calculate_results } from './spatial-cognition';
|
|
3
|
+
import { gonogo_calculate_results } from './gonogo';
|
|
4
|
+
import { emotion_calculate_results } from './emotions';
|
|
3
5
|
var NbackResults = function (obj) {
|
|
4
6
|
return nback_calculate_results(obj);
|
|
5
7
|
};
|
|
6
8
|
var SpatialCognitionResults = function (obj) {
|
|
7
9
|
return spatial_calculate_results(obj);
|
|
8
10
|
};
|
|
9
|
-
|
|
11
|
+
var GonogoResults = function (obj) {
|
|
12
|
+
return gonogo_calculate_results(obj);
|
|
13
|
+
};
|
|
14
|
+
var EmotionResults = function (obj) {
|
|
15
|
+
return emotion_calculate_results(obj);
|
|
16
|
+
};
|
|
17
|
+
export { NbackResults, SpatialCognitionResults, EmotionResults, GonogoResults };
|
package/dist/esm/nback.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
declare const nback_calculate_results: (obj: any[]) =>
|
|
1
|
+
declare const nback_calculate_results: (obj: any[]) => NbackResultsStructure;
|
|
2
2
|
declare const nback_extract_trials: (obj: any[]) => any[];
|
|
3
|
-
interface
|
|
3
|
+
interface NbackTrialResultsStructure {
|
|
4
4
|
n: number;
|
|
5
5
|
avg_rt: number;
|
|
6
6
|
avg_acc: number;
|
|
7
7
|
}
|
|
8
|
-
interface
|
|
9
|
-
total_trials:
|
|
10
|
-
target_trials:
|
|
11
|
-
non_target_trials:
|
|
8
|
+
interface NbackResultsStructure {
|
|
9
|
+
total_trials: NbackTrialResultsStructure;
|
|
10
|
+
target_trials: NbackTrialResultsStructure;
|
|
11
|
+
non_target_trials: NbackTrialResultsStructure;
|
|
12
12
|
performance: number;
|
|
13
13
|
}
|
|
14
|
-
declare const nback_results: (trials: any[]) =>
|
|
15
|
-
export { nback_extract_trials, nback_results, nback_calculate_results,
|
|
14
|
+
declare const nback_results: (trials: any[]) => NbackResultsStructure;
|
|
15
|
+
export { nback_extract_trials, nback_results, nback_calculate_results, NbackResultsStructure };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
interface
|
|
1
|
+
interface SpatialResultsStructure {
|
|
2
2
|
n: number;
|
|
3
3
|
avg_rt: number;
|
|
4
4
|
avg_acc: number;
|
|
5
5
|
performance: number;
|
|
6
6
|
}
|
|
7
|
-
declare const spatial_calculate_results: (obj: any[]) =>
|
|
7
|
+
declare const spatial_calculate_results: (obj: any[]) => SpatialResultsStructure;
|
|
8
8
|
declare const spatial_extract_trials: (obj: any[]) => any[];
|
|
9
|
-
declare const spatial_results: (obj: any[]) =>
|
|
9
|
+
declare const spatial_results: (obj: any[]) => SpatialResultsStructure;
|
|
10
10
|
declare const spatial_extract_image_info: (obj: any[]) => any[];
|
|
11
|
-
export { spatial_extract_image_info, spatial_extract_trials, spatial_results, spatial_calculate_results,
|
|
11
|
+
export { spatial_extract_image_info, spatial_extract_trials, spatial_results, spatial_calculate_results, SpatialResultsStructure };
|
|
@@ -18,13 +18,9 @@ var spatial_results = function (obj) {
|
|
|
18
18
|
var best_score = 1000;
|
|
19
19
|
var worst_score = 10000;
|
|
20
20
|
// results.avg_acc to the power of 5
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
if (performance > worst_score) {
|
|
26
|
-
performance = worst_score;
|
|
27
|
-
}
|
|
21
|
+
//let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
22
|
+
var performance = results.avg_rt / (results.avg_acc + 0.001);
|
|
23
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
28
24
|
// convert to 0-100 where 100 is the best (200)
|
|
29
25
|
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
30
26
|
return results;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "compileprofile-spacetests",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "A package for evaluating cognitive test results",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "A package for evaluating cognitive test results from Vzhuru do vesmiru",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/cjs/index.d.ts",
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { emotion_extract_trials, emotion_results,
|
|
2
|
+
emotion_calculate_results } from '../../emotions';
|
|
3
|
+
import { loadTestData } from '../test-utils/testData';
|
|
4
|
+
|
|
5
|
+
describe('Emotions test module', () => {
|
|
6
|
+
const emotionsData = loadTestData('emotions').emotions;
|
|
7
|
+
|
|
8
|
+
describe('emotion_extract_trials', () => {
|
|
9
|
+
it('should extract trials from raw data', () => {
|
|
10
|
+
const trials = emotion_extract_trials(emotionsData);
|
|
11
|
+
expect(trials.length).toBeLessThan(emotionsData.length);
|
|
12
|
+
trials.forEach(trial => {
|
|
13
|
+
expect(trial).toHaveProperty('rt');
|
|
14
|
+
expect(trial).toHaveProperty('emotion');
|
|
15
|
+
expect(trial).toHaveProperty('emotion_response');
|
|
16
|
+
expect(trial).toHaveProperty('correct');
|
|
17
|
+
expect(trial).toHaveProperty('image_number');
|
|
18
|
+
expect(typeof trial.emotion).toBe('string');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should handle empty data array', () => {
|
|
23
|
+
const trials = emotion_extract_trials([]);
|
|
24
|
+
expect(trials).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('emotion_results', () => {
|
|
29
|
+
it('should calculate correct averages', () => {
|
|
30
|
+
// Create sample trial data
|
|
31
|
+
const sampleTrials = [
|
|
32
|
+
{ rt: 600, correct: true, emotion: 'happy', emotion_response: 'happy' },
|
|
33
|
+
{ rt: 1000, correct: true, emotion: 'sad', emotion_response: 'sad' },
|
|
34
|
+
{ rt: 800, correct: false, emotion: 'angry', emotion_response: 'happy' },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const results = emotion_results(sampleTrials);
|
|
38
|
+
|
|
39
|
+
expect(results.n).toBe(3);
|
|
40
|
+
expect(results.avg_rt).toBe(800); // (1000 + 1500 + 2000) / 3
|
|
41
|
+
expect(results.avg_acc).toBe(2/3); // (1 + 1 + 0) / 3
|
|
42
|
+
expect(results.performance).toBeGreaterThan(0);
|
|
43
|
+
expect(results.performance).toBeLessThanOrEqual(100);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should handle empty trials array', () => {
|
|
47
|
+
// When given an empty array, it should handle it gracefully
|
|
48
|
+
expect(() => emotion_results([])).toThrow();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('emotion_calculate_results', () => {
|
|
53
|
+
it('should process raw data and return valid results', () => {
|
|
54
|
+
const results = emotion_calculate_results(emotionsData);
|
|
55
|
+
console.log(results);
|
|
56
|
+
expect(results).toHaveProperty('n');
|
|
57
|
+
expect(results).toHaveProperty('avg_rt');
|
|
58
|
+
expect(results).toHaveProperty('avg_acc');
|
|
59
|
+
expect(results).toHaveProperty('performance');
|
|
60
|
+
|
|
61
|
+
expect(results.performance).toBeGreaterThan(0);
|
|
62
|
+
expect(results.performance).toBeLessThanOrEqual(100);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { gonogo_extract_trials, gonogo_results, gonogo_calculate_results } from '../../gonogo';
|
|
2
|
+
import { loadTestData } from '../test-utils/testData';
|
|
3
|
+
|
|
4
|
+
describe('Gonogo test module', () => {
|
|
5
|
+
// If gonogo data is available in your test data, load it
|
|
6
|
+
// const gonogoData = loadTestData('gonogo').gonogo;
|
|
7
|
+
|
|
8
|
+
const gonogoData = loadTestData('gonogo').gonogo;
|
|
9
|
+
|
|
10
|
+
const mockTrials = [
|
|
11
|
+
{
|
|
12
|
+
image: "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
|
|
13
|
+
rt: 846,
|
|
14
|
+
response: 0,
|
|
15
|
+
block_number:1
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
image: "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/alien_trans_1.png",
|
|
19
|
+
rt: null,
|
|
20
|
+
response: null,
|
|
21
|
+
block_number: 1
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
describe('gonogo_extract_trials', () => {
|
|
26
|
+
it('should extract trials from raw data', () => {
|
|
27
|
+
const trials = gonogo_extract_trials(gonogoData);
|
|
28
|
+
// consolo log trials which have block number 3
|
|
29
|
+
expect(trials.length).toBeLessThan(gonogoData.length);
|
|
30
|
+
|
|
31
|
+
trials.forEach(trial => {
|
|
32
|
+
expect(trial).toHaveProperty('stimulus');
|
|
33
|
+
expect(trial).toHaveProperty('stimulustype');
|
|
34
|
+
expect(trial).toHaveProperty('should_go');
|
|
35
|
+
expect(trial).toHaveProperty('did_go');
|
|
36
|
+
expect(trial).toHaveProperty('correct');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should handle empty data array', () => {
|
|
41
|
+
const trials = gonogo_extract_trials([]);
|
|
42
|
+
expect(trials).toEqual([]);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('gonogo_results', () => {
|
|
47
|
+
it('should calculate correct averages', () => {
|
|
48
|
+
const sampleTrials = [
|
|
49
|
+
{ rt: 500, correct: true, should_go: true, did_go: true },
|
|
50
|
+
{ rt: 600, correct: true, should_go: false, did_go: false },
|
|
51
|
+
{ rt: 700, correct: false, should_go: true, did_go: false },
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const results = gonogo_results(sampleTrials);
|
|
55
|
+
console.log(results)
|
|
56
|
+
expect(results.n).toBe(3);
|
|
57
|
+
expect(results.avg_rt).toBe(600); // (500 + 600 + 700) / 3
|
|
58
|
+
expect(results.avg_acc).toBe(2/3); // (1 + 1 + 0) / 3
|
|
59
|
+
expect(results.performance).toBeGreaterThan(0);
|
|
60
|
+
expect(results.performance).toBeLessThanOrEqual(100);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should handle empty trials array', () => {
|
|
64
|
+
expect(() => gonogo_results([])).toThrow();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('gonogo_calculate_results', () => {
|
|
69
|
+
it('should process raw data and return valid results', () => {
|
|
70
|
+
const results = gonogo_calculate_results(gonogoData);
|
|
71
|
+
console.log(results);
|
|
72
|
+
expect(results).toHaveProperty('n');
|
|
73
|
+
expect(results).toHaveProperty('avg_rt');
|
|
74
|
+
expect(results).toHaveProperty('avg_acc');
|
|
75
|
+
expect(results).toHaveProperty('performance');
|
|
76
|
+
|
|
77
|
+
expect(results.performance).toBeGreaterThan(0);
|
|
78
|
+
expect(results.performance).toBeLessThanOrEqual(100);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// test out the spatial_extract_image_info function
|
|
2
|
-
import { spatial_extract_image_info,
|
|
2
|
+
import { spatial_extract_image_info, spatial_calculate_results,
|
|
3
|
+
spatial_results } from '../../spatial-cognition';
|
|
3
4
|
import { loadTestData } from '../test-utils/testData';
|
|
4
5
|
|
|
5
6
|
const ImageInfoTestData = [
|
|
@@ -55,5 +56,11 @@ describe('spatial_results test data', () => {
|
|
|
55
56
|
console.log(resultsTestData);
|
|
56
57
|
expect(resultsTestData).toBeDefined();
|
|
57
58
|
});
|
|
59
|
+
test('processes real data correctly', () => {
|
|
60
|
+
const testData = loadTestData('spatialCognition').spatialCognition;
|
|
61
|
+
const resultData = spatial_calculate_results(testData);
|
|
62
|
+
console.log(resultData);
|
|
63
|
+
expect(resultData).toBeDefined();
|
|
64
|
+
});
|
|
58
65
|
});
|
|
59
66
|
|
package/src/emotions.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface EmotionResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const emotion_calculate_results = (obj: any[]): EmotionResultsStructure => {
|
|
9
|
+
const trials = emotion_extract_trials(obj);
|
|
10
|
+
// throw if trials is empty
|
|
11
|
+
if (trials.length === 0) {
|
|
12
|
+
throw new Error("No trials found");
|
|
13
|
+
}
|
|
14
|
+
return emotion_results(trials);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const emotion_results = (obj: any[]): EmotionResultsStructure => {
|
|
18
|
+
// throw error if obj is empty
|
|
19
|
+
if (obj.length === 0) {
|
|
20
|
+
throw new Error("No trials found");
|
|
21
|
+
}
|
|
22
|
+
let results = {
|
|
23
|
+
n: obj.length,
|
|
24
|
+
avg_rt: obj.reduce((a, b) => a + b.rt, 0) / obj.length,
|
|
25
|
+
avg_acc: obj.reduce((a, b) => a + b.correct, 0) / obj.length,
|
|
26
|
+
performance: NaN
|
|
27
|
+
};
|
|
28
|
+
const best_score = 1000;
|
|
29
|
+
const worst_score = 10000;
|
|
30
|
+
let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
31
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
32
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const emotion_extract_trials = (obj: any[]) => {
|
|
37
|
+
const emotionMap = ["neutral", "sad", "happy", "surprised", "angry"];
|
|
38
|
+
// filter trials where response and rt are defined and not null
|
|
39
|
+
let trials = obj.filter((o: any) => 'response' in o && 'rt' in o && 'emotion' in o);
|
|
40
|
+
trials = trials.filter((o: any) => o.response !== null && o.rt !== null);
|
|
41
|
+
trials.forEach((o: any) => {
|
|
42
|
+
const match = o.emotion.match(/\/([^/]+)_([0-9]+)\.png/);
|
|
43
|
+
if (match) {
|
|
44
|
+
o.stimulus = match[0];
|
|
45
|
+
o.emotion = match[1];
|
|
46
|
+
o.image_number = match[2];
|
|
47
|
+
//this is <emotion>_<number>.png
|
|
48
|
+
o.image = `${match[1]}_${match[2]}.png`;
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
trials.forEach((o: any) => {
|
|
52
|
+
o.emotion_response = emotionMap[o.response] || "unknown";
|
|
53
|
+
o.correct = o.emotion === o.emotion_response;
|
|
54
|
+
// in the older ones there were 15 trials per rotation
|
|
55
|
+
});
|
|
56
|
+
return trials;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {EmotionResultsStructure, emotion_calculate_results, emotion_extract_trials, emotion_results };
|
package/src/gonogo.ts
CHANGED
|
@@ -1,37 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// df <- select(df, trial_index, time_elapsed, rt,
|
|
7
|
-
// response, block_number, image)
|
|
8
|
-
// df$image <- gsub(GONOGO_IMAGE_PATH, "", df$image)
|
|
9
|
-
// df$image <- gsub(".png", "", df$image)
|
|
10
|
-
// df <- df %>%
|
|
11
|
-
// mutate(
|
|
12
|
-
// should_go = case_when(
|
|
13
|
-
// block_number == 1 & grepl("astronaut_trans_1", image) ~ TRUE,
|
|
14
|
-
// block_number == 2 & grepl("alien_trans_1", image) ~ TRUE,
|
|
15
|
-
// block_number == 3 & grepl("rocket_trans_1", image) ~ TRUE,
|
|
16
|
-
// block_number == 4 & !grepl("rocket_trans_1", image) ~ TRUE,
|
|
17
|
-
// TRUE ~ FALSE),
|
|
18
|
-
// did_go = !is.na(response),
|
|
19
|
-
// correct = should_go == did_go
|
|
20
|
-
// )
|
|
21
|
-
// return(df)
|
|
22
|
-
// }
|
|
23
|
-
|
|
24
|
-
const gonogo_calculate_results = (data: any) => {
|
|
25
|
-
|
|
1
|
+
interface GonogoResultsStructure {
|
|
2
|
+
n: number;
|
|
3
|
+
avg_rt: number;
|
|
4
|
+
avg_acc: number;
|
|
5
|
+
performance: number;
|
|
26
6
|
}
|
|
27
7
|
|
|
28
|
-
const
|
|
8
|
+
const gonogo_calculate_results = (data: any[]): GonogoResultsStructure => {
|
|
9
|
+
const trials = gonogo_extract_trials(data);
|
|
10
|
+
const results = gonogo_results(trials);
|
|
11
|
+
return results;
|
|
12
|
+
}
|
|
29
13
|
|
|
30
|
-
|
|
14
|
+
const gonogo_extract_trials = (obj: any[]): any[] => {
|
|
15
|
+
// GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
|
|
16
|
+
let trials = obj.filter((o: any) => 'image' in o && o.image !== undefined);
|
|
17
|
+
trials.forEach((o: any) => {
|
|
18
|
+
// image is in format <stimulus>_trans_<number>.png
|
|
19
|
+
// extract the stimulus and number
|
|
31
20
|
|
|
21
|
+
// "image": "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/aliens/astronaut_trans_1.png",
|
|
22
|
+
// i need to extract the iamge name from the url
|
|
23
|
+
const match = o.image.match(/([^/]+)_(\d+)\.png$/);
|
|
24
|
+
if (match) {
|
|
25
|
+
o.stimulus = match[0];
|
|
26
|
+
o.stimulustype = match[1];
|
|
27
|
+
o.image_number = match[2];
|
|
28
|
+
} else {
|
|
29
|
+
console.warn('Image format did not match expected pattern:', o.image);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
o.should_go = false;
|
|
33
|
+
o.did_go = o.response !== null;
|
|
34
|
+
switch (o.block_number) {
|
|
35
|
+
case 1:
|
|
36
|
+
o.should_go = o.stimulus == "astronaut_trans_1.png";
|
|
37
|
+
break;
|
|
38
|
+
case 2:
|
|
39
|
+
o.should_go = o.stimulus == "alien_trans_1.png";
|
|
40
|
+
break;
|
|
41
|
+
case 3:
|
|
42
|
+
o.should_go = o.stimulus == "rocket_trans_1.png";
|
|
43
|
+
break;
|
|
44
|
+
case 4:
|
|
45
|
+
// should go in all cases where the goal is NOT the rocket
|
|
46
|
+
o.should_go = !(o.stimulus == "rocket_trans_1.png");
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
o.should_go = false;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
o.correct = o.should_go == o.did_go;
|
|
53
|
+
})
|
|
54
|
+
return trials;
|
|
32
55
|
}
|
|
33
56
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
const gonogo_results = (data: any[]): GonogoResultsStructure => {
|
|
58
|
+
// throw error if obj is empty
|
|
59
|
+
if (data.length === 0) {
|
|
60
|
+
throw new Error("No trials found");
|
|
61
|
+
}
|
|
62
|
+
let results = {
|
|
63
|
+
n: data.length,
|
|
64
|
+
avg_rt: data.reduce((a, b) => a + b.rt, 0) / data.length,
|
|
65
|
+
avg_acc: data.reduce((a, b) => a + b.correct, 0) / data.length,
|
|
66
|
+
performance: NaN
|
|
67
|
+
};
|
|
68
|
+
const best_score = 300;
|
|
69
|
+
const worst_score = 5000;
|
|
70
|
+
let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
71
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
72
|
+
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
73
|
+
return results;
|
|
37
74
|
}
|
|
75
|
+
|
|
76
|
+
export { GonogoResultsStructure, gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { NbackResultsStructure, nback_calculate_results } from './nback';
|
|
2
|
+
import { SpatialResultsStructure, spatial_calculate_results } from './spatial-cognition';
|
|
3
|
+
import { GonogoResultsStructure, gonogo_calculate_results } from './gonogo';
|
|
4
|
+
import { EmotionResultsStructure, emotion_calculate_results } from './emotions';
|
|
3
5
|
|
|
4
|
-
const NbackResults = (obj: any[]):
|
|
6
|
+
const NbackResults = (obj: any[]): NbackResultsStructure => {
|
|
5
7
|
return nback_calculate_results(obj);
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
const SpatialCognitionResults = (obj: any[]):
|
|
10
|
+
const SpatialCognitionResults = (obj: any[]): SpatialResultsStructure => {
|
|
9
11
|
return spatial_calculate_results(obj);
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
const GonogoResults = (obj: any[]): GonogoResultsStructure => {
|
|
15
|
+
return gonogo_calculate_results(obj);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const EmotionResults = (obj: any[]): EmotionResultsStructure => {
|
|
19
|
+
return emotion_calculate_results(obj);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { NbackResults, SpatialCognitionResults,
|
|
23
|
+
EmotionResults, GonogoResults };
|
package/src/nback.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// from the passed json extract those objects that have field is_target
|
|
2
|
-
const nback_calculate_results = (obj: any[]):
|
|
2
|
+
const nback_calculate_results = (obj: any[]): NbackResultsStructure => {
|
|
3
3
|
const trials = nback_extract_trials(obj);
|
|
4
4
|
return nback_results(trials);
|
|
5
5
|
}
|
|
@@ -9,20 +9,20 @@ const nback_extract_trials = (obj: any[]): any[] => {
|
|
|
9
9
|
return trials;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
interface
|
|
12
|
+
interface NbackTrialResultsStructure {
|
|
13
13
|
n: number;
|
|
14
14
|
avg_rt: number;
|
|
15
15
|
avg_acc: number;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
interface
|
|
19
|
-
total_trials:
|
|
20
|
-
target_trials:
|
|
21
|
-
non_target_trials:
|
|
18
|
+
interface NbackResultsStructure {
|
|
19
|
+
total_trials: NbackTrialResultsStructure;
|
|
20
|
+
target_trials: NbackTrialResultsStructure;
|
|
21
|
+
non_target_trials: NbackTrialResultsStructure;
|
|
22
22
|
performance: number;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const nback_results = (trials: any[]):
|
|
25
|
+
const nback_results = (trials: any[]): NbackResultsStructure => {
|
|
26
26
|
const target_trials = trials.filter((o: any) => o.is_target);
|
|
27
27
|
const non_target_trials = trials.filter((o: any) => !o.is_target);
|
|
28
28
|
|
|
@@ -50,4 +50,4 @@ const nback_results = (trials: any[]): NBackResults => {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export { nback_extract_trials, nback_results,
|
|
53
|
-
nback_calculate_results,
|
|
53
|
+
nback_calculate_results, NbackResultsStructure };
|
package/src/spatial-cognition.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
interface
|
|
1
|
+
interface SpatialResultsStructure {
|
|
2
2
|
n: number;
|
|
3
3
|
avg_rt: number;
|
|
4
4
|
avg_acc: number;
|
|
5
5
|
performance: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const spatial_calculate_results = (obj: any[]):
|
|
8
|
+
const spatial_calculate_results = (obj: any[]): SpatialResultsStructure => {
|
|
9
9
|
const trials = spatial_extract_trials(obj);
|
|
10
10
|
return spatial_results(trials);
|
|
11
11
|
}
|
|
@@ -17,7 +17,7 @@ const spatial_extract_trials = (obj: any[]) => {
|
|
|
17
17
|
return trials;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const spatial_results = (obj: any[]):
|
|
20
|
+
const spatial_results = (obj: any[]): SpatialResultsStructure => {
|
|
21
21
|
const results = {
|
|
22
22
|
n: obj.length,
|
|
23
23
|
avg_rt: obj.reduce((a, b) => a + b.rt, 0) / obj.length,
|
|
@@ -27,13 +27,9 @@ const spatial_results = (obj: any[]): SpatialResults => {
|
|
|
27
27
|
const best_score = 1000;
|
|
28
28
|
const worst_score = 10000;
|
|
29
29
|
// results.avg_acc to the power of 5
|
|
30
|
-
let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
if (performance > worst_score) {
|
|
35
|
-
performance = worst_score;
|
|
36
|
-
}
|
|
30
|
+
//let performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
|
|
31
|
+
let performance = results.avg_rt / (results.avg_acc + 0.001);
|
|
32
|
+
performance = Math.min(Math.max(performance, best_score), worst_score);
|
|
37
33
|
// convert to 0-100 where 100 is the best (200)
|
|
38
34
|
results.performance = (1 - ((performance - best_score) / (worst_score - best_score))) * 100;
|
|
39
35
|
return results;
|
|
@@ -56,4 +52,4 @@ const spatial_extract_image_info = (obj: any[]) => {
|
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
export { spatial_extract_image_info, spatial_extract_trials,
|
|
59
|
-
spatial_results, spatial_calculate_results,
|
|
55
|
+
spatial_results, spatial_calculate_results, SpatialResultsStructure };
|