-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimportConverted.js
297 lines (256 loc) · 8.52 KB
/
importConverted.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
module.exports = function(xnat){
const fs = require('fs');
const Promise = require('bluebird');
const path = require('path');
const argv = require('minimist')(process.argv.slice(2));
const _ = require('underscore');
const os = require('os');
const help = function(){
console.error("Upload converted files from DICOM to XNAT.");
console.error("Usage: node", process.argv[1],"-d <dicom directory> -f <converted dicom file> -p <project id>");
console.error("Options:");
console.error("-d <DICOM directory>, directory with DICOM files corresponding to the converted file");
console.error("-f <converted dicom file>, The corresponding file either in .nrrd or .nii.gz format");
console.error("-p <project id>, project id in XNAT to upload the files.");
console.error("--check <int value>, wait a maximum number of minutes if the session exists before importing. Checks every minute for the session. default 0");
console.error("--force , Force import of files. If the file exists in XNAT it will delete it first and import the new one.");
console.error("--pid <patient id>, If patient id is specified, the patient id won't be extracted from the DICOM file.");
console.error("--expid <experiment id>, If experiment id is specified, the session id won't be extracted from the DICOM file. This tag is equivalent to the Study Date but is used in xnat as experimentid");
console.error("--server <server url>, XNAT server url");
console.error("--prompt , If set, forces prompt for login information again. It will use the previous server URL saved in the configuration file");
}
if(!argv["d"] || !argv["p"] || !argv["f"] || argv["h"] || argv["help"]){
help();
process.exit(1);
}
var projectid = argv["p"];
var convertedFile = argv["f"];
var directory = argv["d"];
var patientid = argv["pid"];
var experimentid = argv["expid"];
var promptlogin = argv["prompt"];
var noext = argv["noext"];
var forceImport = argv["force"];
var checkSession = 0;
if(argv["check"]){
checkSession = argv["check"];
}
const getConfigFile = function () {
return new Promise(function(resolve, reject){
try {
// Try to load the user's personal configuration file
var conf = path.join(os.homedir(), '.xnat.json');
resolve(require(conf));
} catch (e) {
reject(e);
}
});
};
const testSubjectSessionRec = function(projectid, pid, expid, repeat){
return xnat.getSubjectSession(projectid, pid)
.then(function(sessions){
if(sessions.ResultSet && sessions.ResultSet.Result){
var allsessions = sessions.ResultSet.Result;
var session = _.find(allsessions, function(sess){
return sess.date.replace(/-/g,'') == expid;
});
if(session){
return session;
}else if(checkSession){
var wait;
if(repeat > 0){
console.log("Waiting:", repeat, "minute(s) left, the subject is not there yet");
wait = Promise.delay(60000)
.then(function(){
repeat--;
return testSubjectSessionRec(projectid, pid, expid, repeat);
});
}else{
wait = Promise.resolve();
}
return wait;
}
}
return Promise.reject("Session not found using acquisition date");
});
}
const testSubjectRec = function(projectid, pid, repeat){
return xnat.getSubjectSession(projectid, pid)
.catch(function(e){
var wait;
if(repeat > 0){
console.log("Waiting:", repeat, "minute(s) left, the session is not there yet");
wait = Promise.delay(60000)
.then(function(){
repeat--;
return testSubjectRec(projectid, pid, repeat);
});
}else{
wait = Promise.resolve();
}
return wait;
});
}
xnat.useDCMExtensionOff();
var loginprom = undefined;
if(argv["server"]){
var conf = {};
conf.server = argv["server"];
loginprom = xnat.promptUsernamePassword()
.then(function(user){
conf.user = user;
xnat.writeConfFile(conf);
return conf;
});
}else{
loginprom = getConfigFile()
.then(function(conf){
if(promptlogin){
return xnat.promptUsernamePassword()
.then(function(user){
conf.user = user;
xnat.writeConfFile(conf);
return conf;
});
}else{
return conf;
}
})
.catch(function(e){
throw "Config file not found. Use -h or --help to learn how to use this program";
});
}
loginprom
.then(function(conf){
console.log("Setting server url to ", conf.server);
xnat.setXnatUrl(conf.server);
console.log("Login to xnat.", conf.server);
return xnat.login(conf.user);
})
.then(function(){
console.log("Find dicom files in directory:", directory);
return xnat.findFiles(directory)
.then(function(files){
return Promise.any(_.map(files, function(file){
return xnat.dicomDump(file);
}));
});
})
.then(function(dcmData){
console.log("Importing converted file", convertedFile);
var pid;
if(patientid){
pid = patientid;
}else{
pid = dcmData.dataset["00100020"].value;
console.log("Replacing invalid characters in patient id (pid)");
pid = pid.replace(/[ .:|&;$%@"<>()+,]/g, "_");
console.log("The pid looks like this now:", pid);
}
var expid;
if(experimentid){
expid = experimentid;
}else{
//This dicom tag is the studydate but is used as experiment id
expid = dcmData.dataset["00080020"].value;
}
var seriesdes = dcmData.dataset["0008103E"].value;
seriesdes = seriesdes.trim();
var seriesnum = dcmData.dataset["00200011"].value;
var promGetSubjectSession;
if(checkSession > 0){
promGetSubjectSession = testSubjectRec(projectid, pid, checkSession);
}else{
promGetSubjectSession = xnat.getSubjectSession(projectid, pid);
}
return promGetSubjectSession
.bind({})
.then(function(sessions){
this.expid = expid;
this.pid = pid;
if(sessions.ResultSet && sessions.ResultSet.Result){
var allsessions = sessions.ResultSet.Result;
var session = _.find(allsessions, function(sess){
return sess.date.replace(/-/g,'') == expid;
});
if(session){
this.expid = session.ID;
return xnat.getSubjectSession(projectid, this.pid, session.ID);
}else if(checkSession > 0){
return testSubjectSessionRec(projectid, this.pid, this.expid, checkSession)
.bind(this)
.then(function(session){
this.expid = session.ID;
return xnat.getSubjectSession(projectid, this.pid, session.ID);
});
}
}
return Promise.reject("Session not found using acquisition date");
})
.then(function(sessions){
var allsessions = _.map(sessions.items, function(item){
return _.map(item.children, function(child){
return _.map(_.pluck(child.items, "data_fields"), function(data_field){
return {
ID: data_field.ID,
image_session_ID: data_field.image_session_ID,
series_description: data_field.series_description.trim()
}
});
});
});
return _.flatten(allsessions);
})
.then(function(subjectsessions){
var subjectsession = _.find(subjectsessions, function(sess){
return sess.series_description === seriesdes && seriesnum == sess.ID;
});
if(subjectsession === undefined){
console.log("I did not find the series number, using series description only.");
subjectsession = _.find(subjectsessions, function(sess){
return sess.series_description === seriesdes;
});
if(subjectsession === undefined){
return Promise.reject({
error: "session not found",
file: convertedFile,
dicomDir: directory
});
}
}
this.subjectsessionid = subjectsession.ID;
return xnat.getScanFiles(projectid, this.pid, this.expid, this.subjectsessionid);
})
.then(function(scanfiles){
var convertedFileName = path.basename(convertedFile);
var scan = _.find(scanfiles, function(sc){
return convertedFileName == sc.Name;
});
var deleteFile;
if(scan && forceImport){
deleteFile = xnat.deleteFile(scan.URI);
}else{
deleteFile = Promise.resolve();
}
return deleteFile;
})
.then(function(){
return xnat.createResources(projectid, this.pid, this.expid, this.subjectsessionid, "NRRD")
.catch(function(err){
console.error(err);
});
})
.then(function(){
return xnat.uploadResourceFile(projectid, this.pid, this.expid, this.subjectsessionid, "NRRD", convertedFile);
})
.catch(console.error);
})
.then(function(res){
console.log(res);
return xnat.logout();
})
.catch(function(error){
console.error(error);
return xnat.logout();
});
}