Skip to content

Commit 4d8592b

Browse files
authored
Merge pull request #345 from suyashdb/phenotypetsvSubjectlistMismatch
Check participants listed in phenotype/*.tsv and subjects list
2 parents 5f1c353 + ae43867 commit 4d8592b

File tree

3 files changed

+75
-34
lines changed

3 files changed

+75
-34
lines changed

tests/tsv.spec.js

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ describe('TSV', function(){
1212

1313
it('should not allow empty values saved as empty cells.', function () {
1414
var tsv = "1.0\t\t0.2\tresponse 1\t12.32";
15-
validate.TSV(file, tsv, [], function (issues) {
15+
validate.TSV.TSV(file, tsv, [], function (issues) {
1616
assert(issues.length === 1 && issues[0].code === 23);
1717
});
1818

1919
});
2020

2121
it('should not allow missing values that are specified by something other than "n/a".', function () {
2222
var tsv = "1.0\tNA\t0.2\tresponse 1\t12.32";
23-
validate.TSV(file, tsv, [], function (issues) {
23+
validate.TSV.TSV(file, tsv, [], function (issues) {
2424
assert(issues.length === 1 && issues[0].code === 24);
2525
});
2626
});
@@ -29,7 +29,7 @@ describe('TSV', function(){
2929
var tsv = 'header-one\theader-two\theader-three\n' +
3030
'value-one\tvalue-two\n' +
3131
'value-one\tvalue-two\tvalue-three';
32-
validate.TSV(file, tsv, [], function (issues) {
32+
validate.TSV.TSV(file, tsv, [], function (issues) {
3333
assert(issues.length === 1 && issues[0].code === 22);
3434
});
3535
});
@@ -44,23 +44,23 @@ describe('TSV', function(){
4444
it('should require events files to have "onset" as first header', function () {
4545
var tsv = 'header-one\tduration\t4eader-three\n' +
4646
'value-one\tvalue-two\tvalue-three';
47-
validate.TSV(eventsFile, tsv, [], function (issues) {
47+
validate.TSV.TSV(eventsFile, tsv, [], function (issues) {
4848
assert(issues.length === 1 && issues[0].code === 20);
4949
});
5050
});
5151

5252
it('should require events files to have "duration" as second header', function () {
5353
var tsv = 'onset\theader-two\t4eader-three\n' +
5454
'value-one\tvalue-two\tvalue-three';
55-
validate.TSV(eventsFile, tsv, [], function (issues) {
55+
validate.TSV.TSV(eventsFile, tsv, [], function (issues) {
5656
assert(issues.length === 1 && issues[0].code === 21);
5757
});
5858
});
5959

6060
it('should not throw issues for a valid events file', function () {
6161
var tsv = 'onset\tduration\t4eader-three\n' +
6262
'value-one\tvalue-two\tvalue-three';
63-
validate.TSV(eventsFile, tsv, [], function (issues) {
63+
validate.TSV.TSV(eventsFile, tsv, [], function (issues) {
6464
assert.deepEqual(issues, []);
6565
});
6666
});
@@ -69,12 +69,12 @@ describe('TSV', function(){
6969
var tsv = 'onset\tduration\tstim_file\n' +
7070
'value-one\tvalue-two\timages/red-square.jpg';
7171
var fileList = [{relativePath: '/stimuli/images/blue-square.jpg'}];
72-
validate.TSV(eventsFile, tsv, fileList, function (issues) {
72+
validate.TSV.TSV(eventsFile, tsv, fileList, function (issues) {
7373
assert(issues.length === 1 && issues[0].code === 52);
7474
});
7575

7676
fileList.push({relativePath: '/stimuli/images/red-square.jpg'});
77-
validate.TSV(eventsFile, tsv, fileList, function (issues) {
77+
validate.TSV.TSV(eventsFile, tsv, fileList, function (issues) {
7878
assert.deepEqual(issues, []);
7979
});
8080
});
@@ -89,24 +89,51 @@ describe('TSV', function(){
8989
it("should not allow participants.tsv files without participant_id columns", function () {
9090
var tsv = 'subject_id\theader-two\t4eader-three\n' +
9191
'value-one\tvalue-two\tvalue-three';
92-
validate.TSV(participantsFile, tsv, [], function (issues) {
92+
validate.TSV.TSV(participantsFile, tsv, [], function (issues) {
9393
assert(issues.length === 1 && issues[0].code === 48);
9494
});
9595
});
9696

9797
it("should allow a valid participants.tsv file", function () {
9898
var tsv = 'participant_id\theader-two\t4eader-three\n' +
9999
'value-one\tvalue-two\tvalue-three';
100-
validate.TSV(participantsFile, tsv, [], function (issues) {
100+
validate.TSV.TSV(participantsFile, tsv, [], function (issues) {
101101
assert.deepEqual(issues, []);
102102
});
103103
});
104104

105105
it("should not allow particpants with age 89 and above in participants.tsv file", function () {
106106
var tsv = 'participant_id\theader-two\tage\n' + 'sub-01\tvalue-two\t89';
107-
validate.TSV(participantsFile, tsv, [], function (issues) {
107+
validate.TSV.TSV(participantsFile, tsv, [], function (issues) {
108108
assert(issues.length === 1 && issues[0].code === 56);
109109
});
110110
});
111111

112+
it("should check participants listed in phenotype/*tsv and sub-ids ", function () {
113+
var phenotypeParticipants= [{
114+
list:
115+
[
116+
'10159',
117+
'10171',
118+
'10189'
119+
],
120+
file:
121+
{ name: 'vmnm.tsv',
122+
path: '/corral-repl/utexas/poldracklab/openfmri/shared2/ds000030/ds030_R1.0.5/ds000030_R1.0.5//phenotype/vmnm.tsv',
123+
relativePath: '/phenotype/vmnm.tsv'}}];
124+
var summary = { sessions: [],
125+
subjects:
126+
[
127+
'10159',
128+
'10171'
129+
],
130+
tasks: [ ],
131+
totalFiles: 43,
132+
size: 11845 };
133+
var issues = [];
134+
validate.TSV.checkphenotype(phenotypeParticipants, summary, issues, function(issues){
135+
assert(issues.length === 1 && issues[0].code === 51);
136+
});
137+
});
138+
112139
});

validators/bids.js

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var path = require('path');
44
var utils = require('../utils');
55
var Issue = utils.issues.Issue;
66

7+
78
var TSV = require('./tsv');
89
var json = require('./json');
910
var NIFTI = require('./nii');
@@ -256,7 +257,7 @@ BIDS = {
256257
if (file.name.endsWith('_events.tsv')) {
257258
events.push(file.relativePath);
258259
}
259-
TSV(file, contents, fileList, function (issues, participantList) {
260+
TSV.TSV(file, contents, fileList, function (issues, participantList) {
260261
if (participantList) {
261262
if (file.name.endsWith('participants.tsv')) {
262263
participants = {
@@ -402,7 +403,6 @@ BIDS = {
402403
self.issues.push(new Issue({code: 57}));
403404
}
404405
// check if participants file match found subjects
405-
406406
if (participants) {
407407
var participantsFromFile = participants.list.sort();
408408
var participantsFromFolders = summary.subjects.sort();
@@ -422,19 +422,10 @@ BIDS = {
422422
}));
423423
}
424424

425-
if (phenotypeParticipants && phenotypeParticipants.length > 0) {
426-
for (var j = 0; j < phenotypeParticipants.length; j++) {
427-
var fileParticpants = phenotypeParticipants[j];
428-
var diff = utils.array.diff(fileParticpants.list, summary.subjects)[0];
429-
if (diff && diff.length > 0) {
430-
self.issues.push(new Issue({
431-
code: 51,
432-
evidence: 'sub-' + diff.join(', sub-'),
433-
file: fileParticpants.file
434-
}));
435-
}
436-
}
437-
}
425+
//check for equal number of participants from ./phenotype/*.tsv and participants in dataset
426+
TSV.checkphenotype(phenotypeParticipants, summary, self.issues);
427+
428+
438429
self.issues = self.issues.concat(headerFields(headers));
439430
self.issues = self.issues.concat(session(fileList));
440431
self.issues = self.issues.concat(checkAnyDataPresent(fileList, summary.subjects));

validators/tsv.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
/* eslint-disable no-unused-vars */
12
var Issue = require('../utils').issues.Issue;
3+
var files = require('../utils/files');
4+
var utils = require('../utils');
25

36
/**
47
* TSV
@@ -8,7 +11,7 @@ var Issue = require('../utils').issues.Issue;
811
* it finds while validating against the BIDS
912
* specification.
1013
*/
11-
module.exports = function TSV (file, contents, fileList, callback) {
14+
var TSV = function TSV (file, contents, fileList, callback) {
1215

1316
var issues = [];
1417
var rows = contents.split('\n');
@@ -145,9 +148,28 @@ module.exports = function TSV (file, contents, fileList, callback) {
145148
// check partcipants.tsv for age 89+
146149

147150
if (file.name === 'participants.tsv'){
148-
var header = rows[0].trim().split('\t');
149-
var ageIdColumn = header.indexOf("age");
150-
for (var a = 0; a < rows.length; a++) {
151+
checkage89_plus(rows, file, issues);
152+
}
153+
154+
callback(issues, participants);
155+
};
156+
var checkphenotype = function (phenotypeParticipants, summary, issues) {
157+
for (var j=0; j < phenotypeParticipants.length; j++){
158+
var fileParticpants = phenotypeParticipants[j];
159+
if (phenotypeParticipants && phenotypeParticipants.length > 0 && (!utils.array.equals(fileParticpants.list, summary.subjects.sort(), true))) {
160+
issues.push(new Issue({
161+
code: 51,
162+
evidence: fileParticpants.file + "- " + fileParticpants.list + " Subjects -" + fileParticpants,
163+
file: fileParticpants.file
164+
}));
165+
}
166+
}
167+
};
168+
169+
var checkage89_plus = function(rows, file, issues){
170+
var header = rows[0].trim().split('\t');
171+
var ageIdColumn = header.indexOf("age");
172+
for (var a = 0; a < rows.length; a++) {
151173
var line = rows[a];
152174
var line_values = line.trim().split('\t');
153175
var age = line_values[ageIdColumn];
@@ -159,9 +181,10 @@ module.exports = function TSV (file, contents, fileList, callback) {
159181
character: "age of partcipant is above 89 ",
160182
code: 56
161183
}));
162-
}
163-
}
184+
}
164185
}
165-
166-
callback(issues, participants);
186+
};
187+
module.exports = {
188+
TSV: TSV,
189+
checkphenotype : checkphenotype
167190
};

0 commit comments

Comments
 (0)