compileprofile-spacetests 0.1.0 → 0.2.0

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.
@@ -0,0 +1,10 @@
1
+ interface EmotionResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
6
+ }
7
+ declare const emotion_calculate_results: (obj: any[]) => EmotionResults;
8
+ declare const emotion_results: (obj: any[]) => EmotionResults;
9
+ declare const emotion_extract_trials: (obj: any[]) => any[];
10
+ export { 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;
@@ -1,3 +1,10 @@
1
- declare const gonogo_calculate_results: (data: any) => void;
2
- declare const gonogo_extract_trials: (data: any) => void;
3
- declare const gonogo_results: (data: any) => void;
1
+ interface GonogoResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
6
+ }
7
+ declare const gonogo_calculate_results: (data: any[]) => GonogoResults;
8
+ declare const gonogo_extract_trials: (obj: any[]) => any[];
9
+ declare const gonogo_results: (data: any[]) => GonogoResults;
10
+ export { gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
@@ -1,30 +1,71 @@
1
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
- // }
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
- var gonogo_extract_trials = function (data) {
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;
@@ -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
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
27
- if (performance < best_score) {
28
- performance = best_score;
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 EmotionResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
6
+ }
7
+ declare const emotion_calculate_results: (obj: any[]) => EmotionResults;
8
+ declare const emotion_results: (obj: any[]) => EmotionResults;
9
+ declare const emotion_extract_trials: (obj: any[]) => any[];
10
+ export { 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 };
@@ -1,3 +1,10 @@
1
- declare const gonogo_calculate_results: (data: any) => void;
2
- declare const gonogo_extract_trials: (data: any) => void;
3
- declare const gonogo_results: (data: any) => void;
1
+ interface GonogoResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
6
+ }
7
+ declare const gonogo_calculate_results: (data: any[]) => GonogoResults;
8
+ declare const gonogo_extract_trials: (obj: any[]) => any[];
9
+ declare const gonogo_results: (data: any[]) => GonogoResults;
10
+ export { gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
@@ -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 (data) {
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 };
@@ -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
- var performance = results.avg_rt / (Math.pow(results.avg_acc, 5) + 0.001);
22
- if (performance < best_score) {
23
- performance = best_score;
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;
@@ -460,4 +460,4 @@
460
460
  "time_elapsed": 189520,
461
461
  "attempted": false
462
462
  }
463
- ]{aa{aasdasaadasdasd}}
463
+ ]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "compileprofile-spacetests",
3
- "version": "0.1.0",
4
- "description": "A package for evaluating cognitive test results",
3
+ "version": "0.2.0",
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, spatial_results } from '../../spatial-cognition';
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
 
@@ -0,0 +1,59 @@
1
+ interface EmotionResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
6
+ }
7
+
8
+ const emotion_calculate_results = (obj: any[]): EmotionResults => {
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[]): EmotionResults => {
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 { emotion_calculate_results, emotion_extract_trials, emotion_results };
package/src/gonogo.ts CHANGED
@@ -1,37 +1,76 @@
1
- // gonogo_create_trial_table <- function(txt) {
2
- // arr <- fromJSON(txt)
3
- // df <- as.data.frame(fromJSON(arr[[1]]))
4
- // GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
5
- // df <- filter(df, !is.na(image))
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 GonogoResults {
2
+ n: number;
3
+ avg_rt: number;
4
+ avg_acc: number;
5
+ performance: number;
26
6
  }
27
7
 
28
- const gonogo_extract_trials = (data: any) => {
8
+ const gonogo_calculate_results = (data: any[]): GonogoResults => {
9
+ const trials = gonogo_extract_trials(data);
10
+ const results = gonogo_results(trials);
11
+ return results;
12
+ }
29
13
 
30
- // GONOGO_IMAGE_PATH <- "https://unyavwofnmwihnpvkjji.supabase.co/storage/v1/object/public/test-stimuli/gonogo/"
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
- const gonogo_results = (data: any) => {
36
-
57
+ const gonogo_results = (data: any[]): GonogoResults => {
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 { gonogo_calculate_results, gonogo_extract_trials, gonogo_results };
@@ -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
- if (performance < best_score) {
32
- performance = best_score;
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;