Skip to content

Commit 5c56fcf

Browse files
authored
Merge pull request #314 from rdvincent/rdv-nifti-orient
Handle unusual transforms by setting dimension order correctly.
2 parents d1cfd15 + cffe225 commit 5c56fcf

File tree

1 file changed

+63
-22
lines changed
  • src/brainbrowser/volume-viewer/volume-loaders

1 file changed

+63
-22
lines changed

src/brainbrowser/volume-viewer/volume-loaders/nifti1.js

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
c0[2] * (c1[0] * c2[1] - c1[1] * c2[0]));
9595
}
9696

97+
9798
// Now that we have the transform, need to convert it to MINC-like
9899
// steps and direction_cosines.
99100

@@ -141,7 +142,7 @@
141142

142143
function parseNifti1Header(raw_data, callback) {
143144
var header = {
144-
order: ["zspace", "yspace", "xspace"],
145+
order: [],
145146
xspace: {},
146147
yspace: {},
147148
zspace: {}
@@ -175,9 +176,6 @@
175176
throw new Error(error_message);
176177
}
177178

178-
header.xspace.space_length = dview.getUint16(42, littleEndian);
179-
header.yspace.space_length = dview.getUint16(44, littleEndian);
180-
header.zspace.space_length = dview.getUint16(46, littleEndian);
181179
var tlength = dview.getUint16(48, littleEndian);
182180

183181
var datatype = dview.getUint16(70, littleEndian);
@@ -199,7 +197,7 @@
199197
var qform_code = dview.getUint16(252, littleEndian);
200198
var sform_code = dview.getUint16(254, littleEndian);
201199

202-
var transform = [
200+
var nifti_xfm = [
203201
[1, 0, 0, 0],
204202
[0, 1, 0, 0],
205203
[0, 0, 1, 0],
@@ -212,7 +210,6 @@
212210
header.time.step = tstep;
213211
header.time.start = 0;
214212
header.time.name = "time";
215-
header.order = ["time", "zspace", "yspace", "xspace"];
216213
}
217214

218215
/* Record the number of bytes per voxel, and note whether we need
@@ -226,18 +223,18 @@
226223
* generally assumed to correspond to some standard coordinate
227224
* space (e.g. Talairach).
228225
*/
229-
transform[0][0] = dview.getFloat32(280, littleEndian);
230-
transform[0][1] = dview.getFloat32(284, littleEndian);
231-
transform[0][2] = dview.getFloat32(288, littleEndian);
232-
transform[0][3] = dview.getFloat32(292, littleEndian);
233-
transform[1][0] = dview.getFloat32(296, littleEndian);
234-
transform[1][1] = dview.getFloat32(300, littleEndian);
235-
transform[1][2] = dview.getFloat32(304, littleEndian);
236-
transform[1][3] = dview.getFloat32(308, littleEndian);
237-
transform[2][0] = dview.getFloat32(312, littleEndian);
238-
transform[2][1] = dview.getFloat32(316, littleEndian);
239-
transform[2][2] = dview.getFloat32(320, littleEndian);
240-
transform[2][3] = dview.getFloat32(324, littleEndian);
226+
nifti_xfm[0][0] = dview.getFloat32(280, littleEndian);
227+
nifti_xfm[0][1] = dview.getFloat32(284, littleEndian);
228+
nifti_xfm[0][2] = dview.getFloat32(288, littleEndian);
229+
nifti_xfm[0][3] = dview.getFloat32(292, littleEndian);
230+
nifti_xfm[1][0] = dview.getFloat32(296, littleEndian);
231+
nifti_xfm[1][1] = dview.getFloat32(300, littleEndian);
232+
nifti_xfm[1][2] = dview.getFloat32(304, littleEndian);
233+
nifti_xfm[1][3] = dview.getFloat32(308, littleEndian);
234+
nifti_xfm[2][0] = dview.getFloat32(312, littleEndian);
235+
nifti_xfm[2][1] = dview.getFloat32(316, littleEndian);
236+
nifti_xfm[2][2] = dview.getFloat32(320, littleEndian);
237+
nifti_xfm[2][3] = dview.getFloat32(324, littleEndian);
241238
}
242239
else if (qform_code > 0) {
243240
/* The "Qform", if present, defines a quaternion which specifies
@@ -251,18 +248,62 @@
251248
var qoffset_z = dview.getFloat32(276, littleEndian);
252249
var qfac = (dview.getFloat32(76, littleEndian) < 0) ? -1.0 : 1.0;
253250

254-
transform = niftiQuaternToMat44(quatern_b, quatern_c, quatern_d,
251+
nifti_xfm = niftiQuaternToMat44(quatern_b, quatern_c, quatern_d,
255252
qoffset_x, qoffset_y, qoffset_z,
256253
xstep, ystep, zstep, qfac);
257254
}
258255
else {
259-
transform[0][0] = xstep;
260-
transform[1][1] = ystep;
261-
transform[2][2] = zstep;
256+
nifti_xfm[0][0] = xstep;
257+
nifti_xfm[1][1] = ystep;
258+
nifti_xfm[2][2] = zstep;
259+
}
260+
261+
var i, j;
262+
var axis_index_from_file = [0, 1, 2];
263+
var transform = [[0, 0, 0, 0],
264+
[0, 0, 0, 0],
265+
[0, 0, 0, 0],
266+
[0, 0, 0, 1]];
267+
268+
for (i = 0; i < 3; i++) {
269+
var c_x = Math.abs(nifti_xfm[0][i]);
270+
var c_y = Math.abs(nifti_xfm[1][i]);
271+
var c_z = Math.abs(nifti_xfm[2][i]);
272+
273+
if (c_x > c_y && c_x > c_z) {
274+
header.order[2 - i] = "xspace";
275+
axis_index_from_file[i] = 0;
276+
}
277+
else if (c_y > c_x && c_y > c_z) {
278+
header.order[2 - i] = "yspace";
279+
axis_index_from_file[i] = 1;
280+
}
281+
else {
282+
header.order[2 - i] = "zspace";
283+
axis_index_from_file[i] = 2;
284+
}
285+
}
286+
287+
for (i = 0; i < 3; i++) {
288+
for (j = 0; j < 4; j++) {
289+
var volume_axis = j;
290+
if (j < 3) {
291+
volume_axis = axis_index_from_file[j];
292+
}
293+
transform[i][volume_axis] = nifti_xfm[i][j];
294+
}
262295
}
263296

264297
VolumeViewer.utils.transformToMinc(transform, header);
265298

299+
header[header.order[2]].space_length = dview.getUint16(42, littleEndian);
300+
header[header.order[1]].space_length = dview.getUint16(44, littleEndian);
301+
header[header.order[0]].space_length = dview.getUint16(46, littleEndian);
302+
303+
if (tlength >= 1) {
304+
header.order.unshift("time");
305+
}
306+
266307
header.datatype = datatype;
267308
header.vox_offset = vox_offset;
268309
header.scl_slope = scl_slope;

0 commit comments

Comments
 (0)