searchlight ready. missing nifti-image-write support. added timing to FBS
Christoph Budziszewski

Christoph Budziszewski commited on 2009-03-30 17:54:25
Zeige 40 geänderte Dateien mit 11578 Einfügungen und 27 Löschungen.


git-svn-id: https://svn.discofish.de/MATLAB/spmtoolbox/SVMCrossVal@167 83ab2cfd-5345-466c-8aeb-2b2739fb922d
... ...
@@ -0,0 +1,554 @@
1
+%  Using 2D or 3D affine matrix to rotate, translate, scale, reflect and
2
+%  shear a 2D image or 3D volume. 2D image is represented by a 2D matrix,
3
+%  3D volume is represented by a 3D matrix, and data type can be real 
4
+%  integer or floating-point.
5
+%
6
+%  You may notice that MATLAB has a function called 'imtransform.m' for
7
+%  2D spatial transformation. However, keep in mind that 'imtransform.m'
8
+%  assumes y for the 1st dimension, and x for the 2nd dimension. They are
9
+%  equivalent otherwise.
10
+%
11
+%  In addition, if you adjust the 'new_elem_size' parameter, this 'affine.m'
12
+%  is equivalent to 'interp2.m' for 2D image, and equivalent to 'interp3.m'
13
+%  for 3D volume.
14
+%
15
+%  Usage: [new_img new_M] = ...
16
+%	affine(old_img, old_M, [new_elem_size], [verbose], [bg], [method]);
17
+%
18
+%  old_img  -	original 2D image or 3D volume. We assume x for the 1st
19
+%		dimension, y for the 2nd dimension, and z for the 3rd
20
+%		dimension.
21
+%
22
+%  old_M  -	a 3x3 2D affine matrix for 2D image, or a 4x4 3D affine
23
+%		matrix for 3D volume. We assume x for the 1st dimension,
24
+%		y for the 2nd dimension, and z for the 3rd dimension.
25
+%
26
+%  new_elem_size (optional)  -  size of voxel along x y z direction for 
27
+%		a transformed 3D volume, or size of pixel along x y for
28
+%		a transformed 2D image. We assume x for the 1st dimension
29
+%		y for the 2nd dimension, and z for the 3rd dimension.
30
+%		'new_elem_size' is 1 if it is default or empty.
31
+%
32
+%		You can increase its value to decrease the resampling rate,
33
+%		and make the 2D image or 3D volume more coarse. It works
34
+%		just like 'interp3'.
35
+%
36
+%  verbose (optional) - 1, 0
37
+%		1:  show transforming progress in percentage
38
+%		2:  progress will not be displayed
39
+%		'verbose' is 1 if it is default or empty.
40
+%
41
+%  bg (optional)  -	background voxel intensity in any extra corner that
42
+%		is caused by the interpolation. 0 in most cases. If it is
43
+%		default or empty, 'bg' will be the average of two corner
44
+%		voxel intensities in original data.
45
+%
46
+%  method (optional)  -	1, 2, or 3
47
+%		1:  for Trilinear interpolation
48
+%		2:  for Nearest Neighbor interpolation
49
+%		3:  for Fischer's Bresenham interpolation
50
+%		'method' is 1 if it is default or empty.
51
+%
52
+%  new_img  -	transformed 2D image or 3D volume
53
+%
54
+%  new_M  -	transformed affine matrix
55
+%
56
+%  Example 1 (3D rotation):
57
+%	load mri.mat;   old_img = double(squeeze(D));
58
+%	old_M = [0.88 0.5 3 -90; -0.5 0.88 3 -126; 0 0 2 -72; 0 0 0 1];
59
+%	new_img = affine(old_img, old_M, 2);
60
+%	[x y z] = meshgrid(1:128,1:128,1:27);
61
+%	sz = size(new_img);
62
+%	[x1 y1 z1] = meshgrid(1:sz(2),1:sz(1),1:sz(3));
63
+%	figure; slice(x, y, z, old_img, 64, 64, 13.5);
64
+%	shading flat; colormap(map); view(-66, 66);
65
+%	figure; slice(x1, y1, z1, new_img, sz(1)/2, sz(2)/2, sz(3)/2);
66
+%	shading flat; colormap(map); view(-66, 66);
67
+%
68
+%  Example 2 (2D interpolation):
69
+%	load mri.mat;   old_img=D(:,:,1,13)';
70
+%	old_M = [1 0 0; 0 1 0; 0 0 1];
71
+%	new_img = affine(old_img, old_M, [.2 .4]);
72
+%	figure; image(old_img); colormap(map);
73
+%	figure; image(new_img); colormap(map);
74
+%
75
+%  This program is inspired by:
76
+%  SPM5 Software from Wellcome Trust Centre for Neuroimaging
77
+%	http://www.fil.ion.ucl.ac.uk/spm/software
78
+%  Fischer, J., A. del Rio (2004). A Fast Method for Applying Rigid
79
+%	Transformations to Volume Data, WSCG2004 Conference.
80
+%	http://wscg.zcu.cz/wscg2004/Papers_2004_Short/M19.pdf
81
+%  
82
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
83
+%
84
+function [new_img, new_M] = affine(old_img, old_M, new_elem_size, verbose, bg, method)
85
+
86
+   if ~exist('old_img','var') | ~exist('old_M','var')
87
+      error('Usage: [new_img new_M] = affine(old_img, old_M, [new_elem_size], [verbose], [bg], [method]);');
88
+   end
89
+
90
+   if ndims(old_img) == 3
91
+      if ~isequal(size(old_M),[4 4])
92
+         error('old_M should be a 4x4 affine matrix for 3D volume.');
93
+      end
94
+   elseif ndims(old_img) == 2
95
+      if ~isequal(size(old_M),[3 3])
96
+         error('old_M should be a 3x3 affine matrix for 2D image.');
97
+      end
98
+   else
99
+      error('old_img should be either 2D image or 3D volume.');
100
+   end
101
+
102
+   if ~exist('new_elem_size','var') | isempty(new_elem_size)
103
+      new_elem_size = [1 1 1];
104
+   elseif length(new_elem_size) < 2
105
+      new_elem_size = new_elem_size(1)*ones(1,3);
106
+   elseif length(new_elem_size) < 3
107
+      new_elem_size = [new_elem_size(:); 1]';
108
+   end
109
+
110
+   if ~exist('method','var') | isempty(method)
111
+      method = 1;
112
+   elseif ~exist('bresenham_line3d.m','file') & method == 3
113
+      error([char(10) char(10) 'Please download 3D Bresenham''s line generation program from:' char(10) char(10) 'http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=21057' char(10) char(10) 'to test Fischer''s Bresenham interpolation method.' char(10) char(10)]);
114
+   end
115
+
116
+   %  Make compatible to MATLAB earlier than version 7 (R14), which
117
+   %  can only perform arithmetic on double data type
118
+   %
119
+   old_img = double(old_img);
120
+   old_dim = size(old_img);
121
+
122
+   if ~exist('bg','var') | isempty(bg)
123
+      bg = mean([old_img(1) old_img(end)]);
124
+   end
125
+
126
+   if ~exist('verbose','var') | isempty(verbose)
127
+      verbose = 1;
128
+   end
129
+
130
+   if ndims(old_img) == 2
131
+      old_dim(3) = 1;
132
+      old_M = old_M(:, [1 2 3 3]);
133
+      old_M = old_M([1 2 3 3], :);
134
+      old_M(3,:) = [0 0 1 0];
135
+      old_M(:,3) = [0 0 1 0]';
136
+   end
137
+
138
+   %  Vertices of img in voxel
139
+   %
140
+   XYZvox = [	1		1		1
141
+		1		1		old_dim(3)
142
+		1		old_dim(2)	1
143
+		1		old_dim(2)	old_dim(3)
144
+		old_dim(1)	1		1
145
+		old_dim(1)	1		old_dim(3)
146
+		old_dim(1)	old_dim(2)	1
147
+		old_dim(1)	old_dim(2)	old_dim(3)   ]';
148
+
149
+   old_R = old_M(1:3,1:3);
150
+   old_T = old_M(1:3,4);
151
+
152
+   %  Vertices of img in millimeter
153
+   %
154
+   XYZmm = old_R*(XYZvox-1) + repmat(old_T, [1, 8]);
155
+
156
+   %  Make scale of new_M according to new_elem_size
157
+   %
158
+   new_M = diag([new_elem_size 1]);
159
+
160
+   %  Make translation so minimum vertex is moved to [1,1,1]
161
+   %
162
+   new_M(1:3,4) = round( min(XYZmm,[],2) );
163
+
164
+   %  New dimensions will be the maximum vertices in XYZ direction (dim_vox)
165
+   %  i.e. compute   dim_vox   via   dim_mm = R*(dim_vox-1)+T
166
+   %  where, dim_mm = round(max(XYZmm,[],2));
167
+   %
168
+   new_dim = ceil(new_M(1:3,1:3) \ ( round(max(XYZmm,[],2))-new_M(1:3,4) )+1)';
169
+
170
+   %  Initialize new_img with new_dim
171
+   %
172
+   new_img = zeros(new_dim(1:3));
173
+
174
+   %  Mask out any changes from Z axis of transformed volume, since we
175
+   %  will traverse it voxel by voxel below. We will only apply unit
176
+   %  increment of mask_Z(3,4) to simulate the cursor movement
177
+   %
178
+   %  i.e. we will use   mask_Z * new_XYZvox   to replace   new_XYZvox
179
+   %
180
+   mask_Z = diag(ones(1,4));
181
+   mask_Z(3,3) = 0;
182
+
183
+   %  It will be easier to do the interpolation if we invert the process
184
+   %  by not traversing the original volume. Instead, we traverse the
185
+   %  transformed volume, and backproject each voxel in the transformed 
186
+   %  volume back into the original volume. If the backprojected voxel
187
+   %  in original volume is within its boundary, the intensity of that
188
+   %  voxel can be used by the cursor location in the transformed volume.
189
+   %
190
+   %  First, we traverse along Z axis of transformed volume voxel by voxel
191
+   %
192
+   for z = 1:new_dim(3)
193
+
194
+      if verbose & ~mod(z,10)
195
+         fprintf('%.2f percent is done.\n', 100*z/new_dim(3));
196
+      end
197
+
198
+      %  We need to find out the mapping from voxel in the transformed
199
+      %  volume (new_XYZvox) to voxel in the original volume (old_XYZvox)
200
+      %
201
+      %  The following equation works, because they all equal to XYZmm:
202
+      %  new_R*(new_XYZvox-1) + new_T  ==  old_R*(old_XYZvox-1) + old_T
203
+      %
204
+      %  We can use modified new_M1 & old_M1 to substitute new_M & old_M
205
+      %      new_M1 * new_XYZvox       ==       old_M1 * old_XYZvox
206
+      %
207
+      %  where: M1 = M;   M1(:,4) = M(:,4) - sum(M(:,1:3),2);
208
+      %  and:             M(:,4) == [T; 1] == sum(M1,2)
209
+      %
210
+      %  Therefore:   old_XYZvox = old_M1 \ new_M1 * new_XYZvox;
211
+      %
212
+      %  Since we are traverse Z axis, and   new_XYZvox   is replaced
213
+      %  by   mask_Z * new_XYZvox, the above formula can be rewritten
214
+      %  as:    old_XYZvox = old_M1 \ new_M1 * mask_Z * new_XYZvox;
215
+      %
216
+      %  i.e. we find the mapping from new_XYZvox to old_XYZvox:
217
+      %  M = old_M1 \ new_M1 * mask_Z;
218
+      %
219
+      %  First, compute modified old_M1 & new_M1
220
+      %
221
+      old_M1 = old_M;   old_M1(:,4) = old_M(:,4) - sum(old_M(:,1:3),2);
222
+      new_M1 = new_M;   new_M1(:,4) = new_M(:,4) - sum(new_M(:,1:3),2);
223
+
224
+      %  Then, apply unit increment of mask_Z(3,4) to simulate the
225
+      %  cursor movement
226
+      %
227
+      mask_Z(3,4) = z;
228
+
229
+      %  Here is the mapping from new_XYZvox to old_XYZvox
230
+      %
231
+      M = old_M1 \ new_M1 * mask_Z;
232
+
233
+      switch method
234
+      case 1
235
+         new_img(:,:,z) = trilinear(old_img, new_dim, old_dim, M, bg);
236
+      case 2
237
+         new_img(:,:,z) = nearest_neighbor(old_img, new_dim, old_dim, M, bg);
238
+      case 3
239
+         new_img(:,:,z) = bresenham(old_img, new_dim, old_dim, M, bg);
240
+      end
241
+
242
+   end;			% for z
243
+
244
+   if ndims(old_img) == 2
245
+      new_M(3,:) = [];
246
+      new_M(:,3) = [];
247
+   end
248
+
249
+   return;					% affine
250
+
251
+
252
+%--------------------------------------------------------------------
253
+function img_slice = trilinear(img, dim1, dim2, M, bg)
254
+
255
+   img_slice = zeros(dim1(1:2));
256
+   TINY = 5e-2;					% tolerance
257
+
258
+   %  Dimension of transformed 3D volume
259
+   %
260
+   xdim1 = dim1(1);
261
+   ydim1 = dim1(2);
262
+
263
+   %  Dimension of original 3D volume
264
+   %
265
+   xdim2 = dim2(1);
266
+   ydim2 = dim2(2);
267
+   zdim2 = dim2(3);
268
+
269
+   %  initialize new_Y accumulation
270
+   %
271
+   Y2X = 0;
272
+   Y2Y = 0;
273
+   Y2Z = 0;
274
+
275
+   for y = 1:ydim1
276
+
277
+      %  increment of new_Y accumulation
278
+      %
279
+      Y2X = Y2X + M(1,2);		% new_Y to old_X
280
+      Y2Y = Y2Y + M(2,2);		% new_Y to old_Y
281
+      Y2Z = Y2Z + M(3,2);		% new_Y to old_Z
282
+
283
+      %  backproject new_Y accumulation and translation to old_XYZ
284
+      %
285
+      old_X = Y2X + M(1,4);
286
+      old_Y = Y2Y + M(2,4);
287
+      old_Z = Y2Z + M(3,4);
288
+
289
+      for x = 1:xdim1
290
+
291
+         %  accumulate the increment of new_X, and apply it
292
+         %  to the backprojected old_XYZ
293
+         %
294
+         old_X = M(1,1) + old_X  ;
295
+         old_Y = M(2,1) + old_Y  ;
296
+         old_Z = M(3,1) + old_Z  ;
297
+
298
+         %  within boundary of original image
299
+         %
300
+         if (	old_X > 1-TINY & old_X < xdim2+TINY & ...
301
+		old_Y > 1-TINY & old_Y < ydim2+TINY & ...
302
+		old_Z > 1-TINY & old_Z < zdim2+TINY	)
303
+
304
+            %  Calculate distance of old_XYZ to its neighbors for
305
+            %  weighted intensity average
306
+            %
307
+            dx = old_X - floor(old_X);
308
+            dy = old_Y - floor(old_Y);
309
+            dz = old_Z - floor(old_Z);
310
+
311
+            x000 = floor(old_X);
312
+            x100 = x000 + 1;
313
+
314
+            if floor(old_X) < 1
315
+               x000 = 1;
316
+               x100 = x000;
317
+            elseif floor(old_X) > xdim2-1
318
+               x000 = xdim2;
319
+               x100 = x000;
320
+            end
321
+
322
+            x010 = x000;
323
+            x001 = x000;
324
+            x011 = x000;
325
+
326
+            x110 = x100;
327
+            x101 = x100;
328
+            x111 = x100;
329
+
330
+            y000 = floor(old_Y);
331
+            y010 = y000 + 1;
332
+
333
+            if floor(old_Y) < 1
334
+               y000 = 1;
335
+               y100 = y000;
336
+            elseif floor(old_Y) > ydim2-1
337
+               y000 = ydim2;
338
+               y010 = y000;
339
+            end
340
+
341
+            y100 = y000;
342
+            y001 = y000;
343
+            y101 = y000;
344
+
345
+            y110 = y010;
346
+            y011 = y010;
347
+            y111 = y010;
348
+
349
+            z000 = floor(old_Z);
350
+            z001 = z000 + 1;
351
+
352
+            if floor(old_Z) < 1
353
+               z000 = 1;
354
+               z001 = z000;
355
+            elseif floor(old_Z) > zdim2-1
356
+               z000 = zdim2;
357
+               z001 = z000;
358
+            end
359
+
360
+            z100 = z000;
361
+            z010 = z000;
362
+            z110 = z000;
363
+
364
+            z101 = z001;
365
+            z011 = z001;
366
+            z111 = z001;
367
+
368
+            x010 = x000;
369
+            x001 = x000;
370
+            x011 = x000;
371
+
372
+            x110 = x100;
373
+            x101 = x100;
374
+            x111 = x100;
375
+
376
+            v000 = double(img(x000, y000, z000));
377
+            v010 = double(img(x010, y010, z010));
378
+            v001 = double(img(x001, y001, z001));
379
+            v011 = double(img(x011, y011, z011));
380
+
381
+            v100 = double(img(x100, y100, z100));
382
+            v110 = double(img(x110, y110, z110));
383
+            v101 = double(img(x101, y101, z101));
384
+            v111 = double(img(x111, y111, z111));
385
+
386
+            img_slice(x,y) = v000*(1-dx)*(1-dy)*(1-dz) + ...
387
+               v010*(1-dx)*dy*(1-dz) + ...
388
+               v001*(1-dx)*(1-dy)*dz + ...
389
+               v011*(1-dx)*dy*dz + ...
390
+               v100*dx*(1-dy)*(1-dz) + ...
391
+               v110*dx*dy*(1-dz) + ...
392
+               v101*dx*(1-dy)*dz + ...
393
+               v111*dx*dy*dz;
394
+
395
+         else
396
+            img_slice(x,y) = bg;
397
+
398
+         end	% if boundary
399
+
400
+      end	% for x
401
+   end		% for y
402
+
403
+   return;					% trilinear
404
+
405
+
406
+%--------------------------------------------------------------------
407
+function img_slice = nearest_neighbor(img, dim1, dim2, M, bg)
408
+
409
+   img_slice = zeros(dim1(1:2));
410
+
411
+   %  Dimension of transformed 3D volume
412
+   %
413
+   xdim1 = dim1(1);
414
+   ydim1 = dim1(2);
415
+
416
+   %  Dimension of original 3D volume
417
+   %
418
+   xdim2 = dim2(1);
419
+   ydim2 = dim2(2);
420
+   zdim2 = dim2(3);
421
+
422
+   %  initialize new_Y accumulation
423
+   %
424
+   Y2X = 0;
425
+   Y2Y = 0;
426
+   Y2Z = 0;
427
+
428
+   for y = 1:ydim1
429
+
430
+      %  increment of new_Y accumulation
431
+      %
432
+      Y2X = Y2X + M(1,2);		% new_Y to old_X
433
+      Y2Y = Y2Y + M(2,2);		% new_Y to old_Y
434
+      Y2Z = Y2Z + M(3,2);		% new_Y to old_Z
435
+
436
+      %  backproject new_Y accumulation and translation to old_XYZ
437
+      %
438
+      old_X = Y2X + M(1,4);
439
+      old_Y = Y2Y + M(2,4);
440
+      old_Z = Y2Z + M(3,4);
441
+
442
+      for x = 1:xdim1
443
+
444
+         %  accumulate the increment of new_X and apply it
445
+         %  to the backprojected old_XYZ
446
+         %
447
+         old_X = M(1,1) + old_X  ;
448
+         old_Y = M(2,1) + old_Y  ;
449
+         old_Z = M(3,1) + old_Z  ;
450
+
451
+         xi = round(old_X);
452
+         yi = round(old_Y);
453
+         zi = round(old_Z);
454
+
455
+         %  within boundary of original image
456
+         %
457
+         if (	xi >= 1 & xi <= xdim2 & ...
458
+		yi >= 1 & yi <= ydim2 & ...
459
+		zi >= 1 & zi <= zdim2	)
460
+
461
+            img_slice(x,y) = img(xi,yi,zi);
462
+
463
+         else
464
+            img_slice(x,y) = bg;
465
+
466
+         end	% if boundary
467
+
468
+      end	% for x
469
+   end		% for y
470
+
471
+   return;					% nearest_neighbor
472
+
473
+
474
+%--------------------------------------------------------------------
475
+function img_slice = bresenham(img, dim1, dim2, M, bg)
476
+
477
+   img_slice = zeros(dim1(1:2));
478
+
479
+   %  Dimension of transformed 3D volume
480
+   %
481
+   xdim1 = dim1(1);
482
+   ydim1 = dim1(2);
483
+
484
+   %  Dimension of original 3D volume
485
+   %
486
+   xdim2 = dim2(1);
487
+   ydim2 = dim2(2);
488
+   zdim2 = dim2(3);
489
+
490
+   for y = 1:ydim1
491
+
492
+      start_old_XYZ = round(M*[0     y 0 1]');
493
+      end_old_XYZ   = round(M*[xdim1 y 0 1]');
494
+
495
+      [X Y Z] = bresenham_line3d(start_old_XYZ, end_old_XYZ);
496
+
497
+      %  line error correction
498
+      %
499
+%      del = end_old_XYZ - start_old_XYZ;
500
+ %     del_dom = max(del);
501
+  %    idx_dom = find(del==del_dom);
502
+   %   idx_dom = idx_dom(1);
503
+    %  idx_other = [1 2 3];
504
+     % idx_other(idx_dom) = [];
505
+      %del_x1 = del(idx_other(1));
506
+%      del_x2 = del(idx_other(2));
507
+ %     line_slope = sqrt((del_x1/del_dom)^2 + (del_x2/del_dom)^2 + 1);
508
+  %    line_error = line_slope - 1;
509
+% line error correction removed because it is too slow
510
+
511
+      for x = 1:xdim1
512
+
513
+         %  rescale ratio
514
+         %
515
+         i = round(x * length(X) / xdim1);
516
+
517
+         if i < 1
518
+            i = 1;
519
+         elseif i > length(X)
520
+            i = length(X);
521
+         end
522
+
523
+         xi = X(i);
524
+         yi = Y(i);
525
+         zi = Z(i);
526
+
527
+         %  within boundary of the old XYZ space
528
+         %
529
+         if (	xi >= 1 & xi <= xdim2 & ...
530
+		yi >= 1 & yi <= ydim2 & ...
531
+		zi >= 1 & zi <= zdim2	)
532
+
533
+            img_slice(x,y) = img(xi,yi,zi);
534
+
535
+%            if line_error > 1
536
+ %              x = x + 1;
537
+
538
+%               if x <= xdim1
539
+ %                 img_slice(x,y) = img(xi,yi,zi);
540
+  %                line_error = line_slope - 1;
541
+   %            end
542
+    %        end		% if line_error
543
+% line error correction removed because it is too slow
544
+
545
+         else
546
+            img_slice(x,y) = bg;
547
+
548
+         end	% if boundary
549
+
550
+      end	% for x
551
+   end		% for y
552
+
553
+   return;					% bresenham
554
+
... ...
@@ -0,0 +1,94 @@
1
+%BIPOLAR returns an M-by-3 matrix containing a blue-red colormap, in
2
+%	in which red stands for positive, blue stands for negative, 
3
+%	and white stands for 0.
4
+%
5
+%  Usage: cmap = bipolar(M, lo, hi, contrast);  or  cmap = bipolar;
6
+%
7
+%  cmap:  output M-by-3 matrix for BIPOLAR colormap.
8
+%  M:	  number of shades in the colormap. By default, it is the
9
+%	  same length as the current colormap.
10
+%  lo:	  the lowest value to represent.
11
+%  hi:	  the highest value to represent.
12
+%
13
+%  Inspired from the LORETA PASCAL program:
14
+%	http://www.unizh.ch/keyinst/NewLORETA
15
+%
16
+%  jimmy@rotman-baycrest.on.ca
17
+%
18
+%----------------------------------------------------------------
19
+function cmap = bipolar(M, lo, hi, contrast)
20
+
21
+   if ~exist('contrast','var')
22
+      contrast = 128;
23
+   end
24
+
25
+   if ~exist('lo','var')
26
+      lo = -1;
27
+   end
28
+
29
+   if ~exist('hi','var')
30
+      hi = 1;
31
+   end
32
+
33
+   if ~exist('M','var')
34
+      cmap = colormap;
35
+      M = size(cmap,1);
36
+   end
37
+
38
+   steepness = 10 ^ (1 - (contrast-1)/127);
39
+   pos_infs = 1e-99;
40
+   neg_infs = -1e-99;
41
+
42
+   doubleredc = [];
43
+   doublebluec = [];
44
+
45
+   if lo >= 0		% all positive
46
+
47
+      if lo == 0
48
+         lo = pos_infs;
49
+      end
50
+
51
+      for i=linspace(hi/M, hi, M)
52
+         t = exp(log(i/hi)*steepness);
53
+         doubleredc = [doubleredc; [(1-t)+t,(1-t)+0,(1-t)+0]];
54
+      end
55
+
56
+      cmap = doubleredc;
57
+
58
+   elseif hi <= 0	% all negative
59
+
60
+      if hi == 0
61
+         hi = neg_infs;
62
+      end
63
+
64
+      for i=linspace(abs(lo)/M, abs(lo), M)
65
+         t = exp(log(i/abs(lo))*steepness);
66
+         doublebluec = [doublebluec; [(1-t)+0,(1-t)+0,(1-t)+t]];
67
+      end
68
+
69
+      cmap = flipud(doublebluec);
70
+
71
+   else
72
+
73
+      if hi > abs(lo)
74
+         maxc = hi;
75
+      else
76
+         maxc = abs(lo);
77
+      end
78
+
79
+      for i=linspace(maxc/M, hi, round(M*hi/(hi-lo)))
80
+         t = exp(log(i/maxc)*steepness);
81
+         doubleredc = [doubleredc; [(1-t)+t,(1-t)+0,(1-t)+0]];
82
+      end      
83
+
84
+      for i=linspace(maxc/M, abs(lo), round(M*abs(lo)/(hi-lo)))
85
+         t = exp(log(i/maxc)*steepness);
86
+         doublebluec = [doublebluec; [(1-t)+0,(1-t)+0,(1-t)+t]];
87
+      end
88
+
89
+      cmap = [flipud(doublebluec); doubleredc];
90
+
91
+   end
92
+
93
+   return;					% bipolar
94
+
... ...
@@ -0,0 +1,189 @@
1
+%  Generate X Y Z coordinates of a 3D Bresenham's line between
2
+%  two given points.
3
+%
4
+%  A very useful application of this algorithm can be found in the
5
+%  implementation of Fischer's Bresenham interpolation method in my
6
+%  another program that can rotate three dimensional image volume
7
+%  with an affine matrix:
8
+%  http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=21080
9
+%
10
+%  Usage: [X Y Z] = bresenham_line3d(P1, P2, [precision]);
11
+%
12
+%  P1	- vector for Point1, where P1 = [x1 y1 z1]
13
+%
14
+%  P2	- vector for Point2, where P2 = [x2 y2 z2]
15
+%
16
+%  precision (optional) - Although according to Bresenham's line
17
+%	algorithm, point coordinates x1 y1 z1 and x2 y2 z2 should
18
+%	be integer numbers, this program extends its limit to all
19
+%	real numbers. If any of them are floating numbers, you
20
+%	should specify how many digits of decimal that you would
21
+%	like to preserve. Be aware that the length of output X Y
22
+%	Z coordinates will increase in 10 times for each decimal
23
+%	digit that you want to preserve. By default, the precision
24
+%	is 0, which means that they will be rounded to the nearest
25
+%	integer.
26
+%
27
+%  X	- a set of x coordinates on Bresenham's line
28
+%
29
+%  Y	- a set of y coordinates on Bresenham's line
30
+%
31
+%  Z	- a set of z coordinates on Bresenham's line
32
+%
33
+%  Therefore, all points in XYZ set (i.e. P(i) = [X(i) Y(i) Z(i)])
34
+%  will constitute the Bresenham's line between P1 and P1.
35
+%
36
+%  Example:
37
+%	P1 = [12 37 6];     P2 = [46 3 35];
38
+%	[X Y Z] = bresenham_line3d(P1, P2);
39
+%	figure; plot3(X,Y,Z,'s','markerface','b');
40
+%
41
+%  This program is ported to MATLAB from:
42
+%
43
+%  B.Pendleton.  line3d - 3D Bresenham's (a 3D line drawing algorithm)
44
+%  ftp://ftp.isc.org/pub/usenet/comp.sources.unix/volume26/line3d, 1992
45
+%
46
+%  Which is also referenced by:
47
+%
48
+%  Fischer, J., A. del Rio (2004).  A Fast Method for Applying Rigid
49
+%  Transformations to Volume Data, WSCG2004 Conference.
50
+%  http://wscg.zcu.cz/wscg2004/Papers_2004_Short/M19.pdf
51
+%
52
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
53
+%
54
+function [X,Y,Z] = bresenham_line3d(P1, P2, precision)
55
+
56
+   if ~exist('precision','var') | isempty(precision) | round(precision) == 0
57
+      precision = 0;
58
+      P1 = round(P1);
59
+      P2 = round(P2);
60
+   else
61
+      precision = round(precision);
62
+      P1 = round(P1*(10^precision));
63
+      P2 = round(P2*(10^precision));
64
+   end
65
+
66
+   d = max(abs(P2-P1)+1);
67
+   X = zeros(1, d);
68
+   Y = zeros(1, d);
69
+   Z = zeros(1, d);
70
+
71
+   x1 = P1(1);
72
+   y1 = P1(2);
73
+   z1 = P1(3);
74
+
75
+   x2 = P2(1);
76
+   y2 = P2(2);
77
+   z2 = P2(3);
78
+
79
+   dx = x2 - x1;
80
+   dy = y2 - y1;
81
+   dz = z2 - z1;
82
+
83
+   ax = abs(dx)*2;
84
+   ay = abs(dy)*2;
85
+   az = abs(dz)*2;
86
+
87
+   sx = sign(dx);
88
+   sy = sign(dy);
89
+   sz = sign(dz);
90
+
91
+   x = x1;
92
+   y = y1;
93
+   z = z1;
94
+   idx = 1;
95
+
96
+   if(ax>=max(ay,az))			% x dominant
97
+      yd = ay - ax/2;
98
+      zd = az - ax/2;
99
+
100
+      while(1)
101
+         X(idx) = x;
102
+         Y(idx) = y;
103
+         Z(idx) = z;
104
+         idx = idx + 1;
105
+
106
+         if(x == x2)		% end
107
+            break;
108
+         end
109
+
110
+         if(yd >= 0)		% move along y
111
+            y = y + sy;
112
+            yd = yd - ax;
113
+         end
114
+
115
+         if(zd >= 0)		% move along z
116
+            z = z + sz;
117
+            zd = zd - ax;
118
+         end
119
+
120
+         x  = x  + sx;		% move along x
121
+         yd = yd + ay;
122
+         zd = zd + az;
123
+      end
124
+   elseif(ay>=max(ax,az))		% y dominant
125
+      xd = ax - ay/2;
126
+      zd = az - ay/2;
127
+
128
+      while(1)
129
+         X(idx) = x;
130
+         Y(idx) = y;
131
+         Z(idx) = z;
132
+         idx = idx + 1;
133
+
134
+         if(y == y2)		% end
135
+            break;
136
+         end
137
+
138
+         if(xd >= 0)		% move along x
139
+            x = x + sx;
140
+            xd = xd - ay;
141
+         end
142
+
143
+         if(zd >= 0)		% move along z
144
+            z = z + sz;
145
+            zd = zd - ay;
146
+         end
147
+
148
+         y  = y  + sy;		% move along y
149
+         xd = xd + ax;
150
+         zd = zd + az;
151
+      end
152
+   elseif(az>=max(ax,ay))		% z dominant
153
+      xd = ax - az/2;
154
+      yd = ay - az/2;
155
+
156
+      while(1)
157
+         X(idx) = x;
158
+         Y(idx) = y;
159
+         Z(idx) = z;
160
+         idx = idx + 1;
161
+
162
+         if(z == z2)		% end
163
+            break;
164
+         end
165
+
166
+         if(xd >= 0)		% move along x
167
+            x = x + sx;
168
+            xd = xd - az;
169
+         end
170
+
171
+         if(yd >= 0)		% move along y
172
+            y = y + sy;
173
+            yd = yd - az;
174
+         end
175
+
176
+         z  = z  + sz;		% move along z
177
+         xd = xd + ax;
178
+         yd = yd + ay;
179
+      end
180
+   end
181
+
182
+   if precision ~= 0
183
+      X = X/(10^precision);
184
+      Y = Y/(10^precision);
185
+      Z = Z/(10^precision);
186
+   end
187
+
188
+   return;					% bresenham_line3d
189
+
... ...
@@ -0,0 +1,202 @@
1
+%  Collapse multiple single-scan NIFTI files into a multiple-scan NIFTI file
2
+%
3
+%  Usage: collapse_nii_scan(scan_file_pattern, [collapsed_filename], [scan_file_folder])
4
+%
5
+%  Here, scan_file_pattern should look like: 'myscan_0*.img'
6
+%  If collapsed_filename is omit, 'multi_scan.nii' will be used
7
+%  If scan_file_folder is omit, current file folder will be used
8
+%
9
+%  The order of volumes in the collapsed file will be the order of 
10
+%  corresponding filenames for those selected scan files.
11
+%
12
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
13
+%
14
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
15
+%
16
+function collapse_nii_scan(scan_pattern, fileprefix, scan_path)
17
+
18
+   if ~exist('fileprefix','var'), fileprefix = 'multi_scan.nii'; end
19
+   if ~exist('scan_path','var'), scan_path = pwd; end
20
+
21
+   filetype = 1;
22
+
23
+   %  Note: fileprefix is actually the filename you want to save
24
+   %   
25
+   if findstr('.nii',fileprefix)
26
+      filetype = 2;
27
+      fileprefix = strrep(fileprefix,'.nii','');
28
+   end
29
+   
30
+   if findstr('.hdr',fileprefix)
31
+      fileprefix = strrep(fileprefix,'.hdr','');
32
+   end
33
+   
34
+   if findstr('.img',fileprefix)
35
+      fileprefix = strrep(fileprefix,'.img','');
36
+   end
37
+
38
+   pnfn = fullfile(scan_path, scan_pattern);
39
+
40
+   file_lst = dir(pnfn);
41
+   flist = {file_lst.name};
42
+   flist = flist(:);
43
+
44
+   nii = load_nii(flist{1});
45
+   nii.hdr.dime.dim(5) = length(flist);
46
+   hdr = nii.hdr;
47
+
48
+   if isfield(nii,'ext') & ~isempty(nii.ext)
49
+      ext = nii.ext;
50
+      [ext, esize_total] = verify_nii_ext(ext);
51
+   else
52
+      ext = [];
53
+   end
54
+
55
+   switch double(hdr.dime.datatype),
56
+   case   1,
57
+      hdr.dime.bitpix = int16(1 ); precision = 'ubit1';
58
+   case   2,
59
+      hdr.dime.bitpix = int16(8 ); precision = 'uint8';
60
+   case   4,
61
+      hdr.dime.bitpix = int16(16); precision = 'int16';
62
+   case   8,
63
+      hdr.dime.bitpix = int16(32); precision = 'int32';
64
+   case  16,
65
+      hdr.dime.bitpix = int16(32); precision = 'float32';
66
+   case  32,
67
+      hdr.dime.bitpix = int16(64); precision = 'float32';
68
+   case  64,
69
+      hdr.dime.bitpix = int16(64); precision = 'float64';
70
+   case 128,
71
+      hdr.dime.bitpix = int16(24); precision = 'uint8';
72
+   case 256 
73
+      hdr.dime.bitpix = int16(8 ); precision = 'int8';
74
+   case 512 
75
+      hdr.dime.bitpix = int16(16); precision = 'uint16';
76
+   case 768 
77
+      hdr.dime.bitpix = int16(32); precision = 'uint32';
78
+   case 1024
79
+      hdr.dime.bitpix = int16(64); precision = 'int64';
80
+   case 1280
81
+      hdr.dime.bitpix = int16(64); precision = 'uint64';
82
+   case 1792,
83
+      hdr.dime.bitpix = int16(128); precision = 'float64';
84
+   otherwise
85
+      error('This datatype is not supported');
86
+   end
87
+
88
+   if filetype == 2
89
+      fid = fopen(sprintf('%s.nii',fileprefix),'w');
90
+      
91
+      if fid < 0,
92
+         msg = sprintf('Cannot open file %s.nii.',fileprefix);
93
+         error(msg);
94
+      end
95
+      
96
+      hdr.dime.vox_offset = 352;
97
+
98
+      if ~isempty(ext)
99
+         hdr.dime.vox_offset = hdr.dime.vox_offset + esize_total;
100
+      end
101
+
102
+      hdr.hist.magic = 'n+1';
103
+      save_nii_hdr(hdr, fid);
104
+
105
+      if ~isempty(ext)
106
+         save_nii_ext(ext, fid);
107
+      end
108
+   else
109
+      fid = fopen(sprintf('%s.hdr',fileprefix),'w');
110
+      
111
+      if fid < 0,
112
+         msg = sprintf('Cannot open file %s.hdr.',fileprefix);
113
+         error(msg);
114
+      end
115
+      
116
+      hdr.dime.vox_offset = 0;
117
+      hdr.hist.magic = 'ni1';
118
+      save_nii_hdr(hdr, fid);
119
+
120
+      if ~isempty(ext)
121
+         save_nii_ext(ext, fid);
122
+      end
123
+      
124
+      fclose(fid);
125
+      fid = fopen(sprintf('%s.img',fileprefix),'w');
126
+   end
127
+
128
+   if filetype == 2 & isempty(ext)
129
+      skip_bytes = double(hdr.dime.vox_offset) - 348;
130
+   else
131
+      skip_bytes = 0;
132
+   end
133
+
134
+   glmax = -inf;
135
+   glmin = inf;
136
+
137
+   for i = 1:length(flist)
138
+      nii = load_nii(flist{i});
139
+
140
+      if double(hdr.dime.datatype) == 128
141
+
142
+         %  RGB planes are expected to be in the 4th dimension of nii.img
143
+         %
144
+         if(size(nii.img,4)~=3)
145
+            error(['The NII structure does not appear to have 3 RGB color planes in the 4th dimension']);
146
+         end
147
+
148
+         if old_RGB
149
+            nii.img = permute(nii.img, [1 2 4 3 5 6 7 8]);
150
+         else
151
+            nii.img = permute(nii.img, [4 1 2 3 5 6 7 8]);
152
+         end
153
+      end
154
+
155
+      %  For complex float32 or complex float64, voxel values
156
+      %  include [real, imag]
157
+      %
158
+      if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
159
+         real_img = real(nii.img(:))';
160
+         nii.img = imag(nii.img(:))';
161
+         nii.img = [real_img; nii.img];
162
+      end
163
+
164
+      if nii.hdr.dime.glmax > glmax
165
+         glmax = nii.hdr.dime.glmax;
166
+      end
167
+
168
+      if nii.hdr.dime.glmin < glmin
169
+         glmin = nii.hdr.dime.glmin;
170
+      end
171
+
172
+      fwrite(fid, nii.img, precision);
173
+   end
174
+
175
+   hdr.dime.glmax = round(glmax);
176
+   hdr.dime.glmin = round(glmin);
177
+
178
+   if filetype == 2
179
+      fseek(fid, 140, 'bof');
180
+      fwrite(fid, hdr.dime.glmax, 'int32');
181
+      fwrite(fid, hdr.dime.glmin, 'int32');
182
+   else
183
+      fid2 = fopen(sprintf('%s.hdr',fileprefix),'w');
184
+
185
+      if fid2 < 0,
186
+         msg = sprintf('Cannot open file %s.hdr.',fileprefix);
187
+         error(msg);
188
+      end
189
+
190
+      save_nii_hdr(hdr, fid2);
191
+
192
+      if ~isempty(ext)
193
+         save_nii_ext(ext, fid2);
194
+      end
195
+
196
+      fclose(fid2);
197
+   end
198
+
199
+   fclose(fid);
200
+
201
+   return;					% collapse_nii_scan
202
+
... ...
@@ -0,0 +1,120 @@
1
+
2
+- Examples to load, make and save a nii struct:
3
+
4
+	To load Analyze data or NIFTI data to a structure:
5
+
6
+		nii = load_nii(NIFTI_file_name, [img_idx], [old_RGB24]);
7
+
8
+	img_idx is a numerical array of image indices along the temporal
9
+	axis, which is only available in NIFTI data. After you specify 
10
+	img_idx, only those images indexed by img_idx will be loaded. If
11
+	there is no img_idx or img_idx is empty, all available images 
12
+	will be loaded.
13
+
14
+	For RGB image, most people use RGB triple sequentially for each
15
+	voxel, like [R1 G1 B1 R2 G2 B2 ...]. However, some program like
16
+	Analyze 6.0 developed by AnalyzeDirect uses old RGB24, in a way
17
+	like [R1 R2 ... G1 G2 ... B1 B2 ...] for each slices. In this
18
+	case, you can set old_RGB24 flag to 1 and load data correctly:
19
+
20
+		nii = load_nii(NIFTI_file_name, [], 1);
21
+
22
+	To get a total number of images along the temporal axis:
23
+
24
+		num_scan = get_nii_frame(NIFTI_file_name);
25
+
26
+	You can also load the header extension if it exists:
27
+
28
+		nii.ext = load_nii_ext(NIFTI_file_name);
29
+
30
+	You can just load the Analyze or NIFTI header:
31
+	(header contains: hk, dime, and hist)
32
+
33
+		hdr = load_nii_hdr(NIFTI_file_name);
34
+
35
+	You can also save the structure to a new file:
36
+	(header extension will be saved if there is nii.ext structure)
37
+
38
+		save_nii(nii, NIFTI_file_name);
39
+
40
+	To make the structure from any 3D (or 4D) data:
41
+
42
+		img = rand(91,109,91); or
43
+		img = rand(64,64,21,18);
44
+		nii = make_nii(img [, voxel_size, origin, datatype] );
45
+
46
+	Use "help load_nii", "help save_nii", "help make_nii" etc.
47
+	to get more detail information.
48
+
49
+
50
+- Examples to plot a nii struct:
51
+  (More detail descriptions are available on top of "view_nii.m")
52
+
53
+	Simple way to plot a nii struct:
54
+
55
+		view_nii(nii);
56
+
57
+	The default colormap will use the Gray if all data values are
58
+	non-negative; otherwise, the default colormap will use BiPolar.
59
+	You can choose other colormap, including customized colormap
60
+	from panel.
61
+
62
+	To imbed the plot into your existing figure:
63
+
64
+		h = gcf;
65
+		opt.command = 'init';
66
+		opt.setarea = [0.3 0.1 0.6 0.8];
67
+		view_nii(h, nii, opt);
68
+
69
+	To add a colorbar:
70
+
71
+		opt.usecolorbar = 1;
72
+		view_nii(gcf, opt);
73
+
74
+		Here, opt.command is implicitly set to 'update'.
75
+
76
+	To display in real aspect ratio:
77
+
78
+		opt.usestretch = 0;
79
+		view_nii(gcf, opt);
80
+
81
+	If you want the data value to be directly used as the index
82
+	of colormap, instead of scale to the whole colormap:
83
+
84
+		opt.useimagesc = 0;
85
+		view_nii(gcf, opt);
86
+
87
+	If you modified the data value without changing the dimension,
88
+	voxel_size, and origin, you can update the display by:
89
+
90
+		opt.command = 'updateimg';
91
+		view_nii(gcf, nii.img, opt);
92
+
93
+	If the data is completely different, display can be updated by:
94
+
95
+		opt.command = 'updatenii';
96
+		view_nii(gcf, nii, opt);
97
+
98
+
99
+- Contrast and Brightness are available under Gray and Bipolar colormap:
100
+
101
+
102
+	Increase contrast in Gray colormap will make high end values
103
+	more distinguishable by sacrificing the low end values; The
104
+	minimum contrast (default) will display the whole range.
105
+
106
+	Increase or decrease contrast in BiPolar colormap will shift
107
+	the distinguishable position for both positive and negative
108
+	values.
109
+
110
+	Increase or decrease brightness in Gray colormap will shift
111
+	the distinguishable position.
112
+
113
+	Increase or decrease brightness in BiPolar colormap will make
114
+	both positive and negative values more distinguishable.
115
+
116
+
117
+- Required files:
118
+
119
+	All files in this package.
120
+
... ...
@@ -0,0 +1,24 @@
1
+%  Expand a multiple-scan NIFTI file into multiple single-scan NIFTI files
2
+%
3
+%  Usage: expand_nii_scan(multi_scan_filename, [img_idx], [path_to_save])
4
+%
5
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
6
+%
7
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
8
+%
9
+function expand_nii_scan(filename, img_idx, newpath)
10
+
11
+   if ~exist('newpath','var'), newpath = pwd; end
12
+   if ~exist('img_idx','var'), img_idx = 1:get_nii_frame(filename); end
13
+
14
+   for i=img_idx
15
+      nii_i = load_nii(filename, i);
16
+
17
+      fn = [nii_i.fileprefix '_' sprintf('%04d',i)];
18
+      pnfn = fullfile(newpath, fn);
19
+
20
+      save_nii(nii_i, pnfn);
21
+   end
22
+
23
+   return;					% expand_nii_scan
24
+
... ...
@@ -0,0 +1,255 @@
1
+%  Decode extra NIFTI header information into hdr.extra
2
+%
3
+%  Usage: hdr = extra_nii_hdr(hdr)
4
+%
5
+%  hdr can be obtained from load_nii_hdr
6
+%
7
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
8
+%
9
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
10
+%
11
+function hdr = extra_nii_hdr(hdr)
12
+
13
+   switch hdr.dime.datatype
14
+   case 1
15
+      extra.NIFTI_DATATYPES = 'DT_BINARY';
16
+   case 2
17
+      extra.NIFTI_DATATYPES = 'DT_UINT8';
18
+   case 4
19
+      extra.NIFTI_DATATYPES = 'DT_INT16';
20
+   case 8
21
+      extra.NIFTI_DATATYPES = 'DT_INT32';
22
+   case 16
23
+      extra.NIFTI_DATATYPES = 'DT_FLOAT32';
24
+   case 32
25
+      extra.NIFTI_DATATYPES = 'DT_COMPLEX64';
26
+   case 64
27
+      extra.NIFTI_DATATYPES = 'DT_FLOAT64';
28
+   case 128
29
+      extra.NIFTI_DATATYPES = 'DT_RGB24';
30
+   case 256
31
+      extra.NIFTI_DATATYPES = 'DT_INT8';
32
+   case 512
33
+      extra.NIFTI_DATATYPES = 'DT_UINT16';
34
+   case 768
35
+      extra.NIFTI_DATATYPES = 'DT_UINT32';
36
+   case 1024
37
+      extra.NIFTI_DATATYPES = 'DT_INT64';
38
+   case 1280
39
+      extra.NIFTI_DATATYPES = 'DT_UINT64';
40
+   case 1536
41
+      extra.NIFTI_DATATYPES = 'DT_FLOAT128';
42
+   case 1792
43
+      extra.NIFTI_DATATYPES = 'DT_COMPLEX128';
44
+   case 2048
45
+      extra.NIFTI_DATATYPES = 'DT_COMPLEX256';
46
+   otherwise
47
+      extra.NIFTI_DATATYPES = 'DT_UNKNOWN';
48
+   end
49
+
50
+   switch hdr.dime.intent_code
51
+   case 2
52
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_CORREL';
53
+   case 3
54
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_TTEST';
55
+   case 4
56
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_FTEST';
57
+   case 5
58
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_ZSCORE';
59
+   case 6
60
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_CHISQ';
61
+   case 7
62
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_BETA';
63
+   case 8
64
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_BINOM';
65
+   case 9
66
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_GAMMA';
67
+   case 10
68
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_POISSON';
69
+   case 11
70
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_NORMAL';
71
+   case 12
72
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_FTEST_NONC';
73
+   case 13
74
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_CHISQ_NONC';
75
+   case 14
76
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_LOGISTIC';
77
+   case 15
78
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_LAPLACE';
79
+   case 16
80
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_UNIFORM';
81
+   case 17
82
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_TTEST_NONC';
83
+   case 18
84
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_WEIBULL';
85
+   case 19
86
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_CHI';
87
+   case 20
88
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_INVGAUSS';
89
+   case 21
90
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_EXTVAL';
91
+   case 22
92
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_PVAL';
93
+   case 23
94
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_LOGPVAL';
95
+   case 24
96
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_LOG10PVAL';
97
+   case 1001
98
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_ESTIMATE';
99
+   case 1002
100
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_LABEL';
101
+   case 1003
102
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_NEURONAME';
103
+   case 1004
104
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_GENMATRIX';
105
+   case 1005
106
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_SYMMATRIX';
107
+   case 1006
108
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_DISPVECT';
109
+   case 1007
110
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_VECTOR';
111
+   case 1008
112
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_POINTSET';
113
+   case 1009
114
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_TRIANGLE';
115
+   case 1010
116
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_QUATERNION';
117
+   case 1011
118
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_DIMLESS';
119
+   otherwise
120
+      extra.NIFTI_INTENT_CODES = 'NIFTI_INTENT_NONE';
121
+   end
122
+
123
+   extra.NIFTI_INTENT_NAMES = hdr.hist.intent_name;
124
+
125
+   if hdr.hist.sform_code > 0
126
+      switch hdr.hist.sform_code
127
+      case 1
128
+         extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_SCANNER_ANAT';
129
+      case 2
130
+         extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_ALIGNED_ANAT';
131
+      case 3
132
+         extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_TALAIRACH';
133
+      case 4
134
+         extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_MNI_152';
135
+      otherwise
136
+         extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
137
+      end
138
+
139
+      extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
140
+   elseif hdr.hist.qform_code > 0
141
+      extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
142
+
143
+      switch hdr.hist.qform_code
144
+      case 1
145
+         extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_SCANNER_ANAT';
146
+      case 2
147
+         extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_ALIGNED_ANAT';
148
+      case 3
149
+         extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_TALAIRACH';
150
+      case 4
151
+         extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_MNI_152';
152
+      otherwise
153
+         extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
154
+      end
155
+   else
156
+      extra.NIFTI_SFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
157
+      extra.NIFTI_QFORM_CODES = 'NIFTI_XFORM_UNKNOWN';
158
+   end
159
+
160
+   switch bitand(hdr.dime.xyzt_units, 7)	% mask with 0x07
161
+   case 1
162
+      extra.NIFTI_SPACE_UNIT = 'NIFTI_UNITS_METER';
163
+   case 2
164
+      extra.NIFTI_SPACE_UNIT = 'NIFTI_UNITS_MM';	% millimeter
165
+   case 3
166
+      extra.NIFTI_SPACE_UNIT = 'NIFTI_UNITS_MICRO';
167
+   otherwise
168
+      extra.NIFTI_SPACE_UNIT = 'NIFTI_UNITS_UNKNOWN';
169
+   end
170
+
171
+   switch bitand(hdr.dime.xyzt_units, 56)	% mask with 0x38
172
+   case 8
173
+      extra.NIFTI_TIME_UNIT = 'NIFTI_UNITS_SEC';
174
+   case 16
175
+      extra.NIFTI_TIME_UNIT = 'NIFTI_UNITS_MSEC';
176
+   case 24
177
+      extra.NIFTI_TIME_UNIT = 'NIFTI_UNITS_USEC';	% microsecond
178
+   otherwise
179
+      extra.NIFTI_TIME_UNIT = 'NIFTI_UNITS_UNKNOWN';
180
+   end
181
+
182
+   switch hdr.dime.xyzt_units
183
+   case 32
184
+      extra.NIFTI_SPECTRAL_UNIT = 'NIFTI_UNITS_HZ';
185
+   case 40
186
+      extra.NIFTI_SPECTRAL_UNIT = 'NIFTI_UNITS_PPM';	% part per million
187
+   case 48
188
+      extra.NIFTI_SPECTRAL_UNIT = 'NIFTI_UNITS_RADS';	% radians per second
189
+   otherwise
190
+      extra.NIFTI_SPECTRAL_UNIT = 'NIFTI_UNITS_UNKNOWN';
191
+   end
192
+
193
+   %  MRI-specific spatial and temporal information
194
+   %
195
+   dim_info = hdr.hk.dim_info;
196
+   extra.NIFTI_FREQ_DIM = bitand(dim_info, 3);
197
+   extra.NIFTI_PHASE_DIM = bitand(bitshift(dim_info, -2), 3);
198
+   extra.NIFTI_SLICE_DIM = bitand(bitshift(dim_info, -4), 3);
199
+
200
+   %  Check slice code
201
+   %
202
+   switch hdr.dime.slice_code
203
+   case 1
204
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_SEQ_INC';	% sequential increasing
205
+   case 2
206
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_SEQ_DEC';	% sequential decreasing
207
+   case 3
208
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_ALT_INC';	% alternating increasing
209
+   case 4
210
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_ALT_DEC';	% alternating decreasing
211
+   case 5
212
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_ALT_INC2';	% ALT_INC # 2
213
+   case 6
214
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_ALT_DEC2';	% ALT_DEC # 2
215
+   otherwise
216
+      extra.NIFTI_SLICE_ORDER = 'NIFTI_SLICE_UNKNOWN';
217
+   end
218
+
219
+   %  Check NIFTI version
220
+   %
221
+   if     ~isempty(hdr.hist.magic) & strcmp(hdr.hist.magic(1),'n') & ...
222
+	( strcmp(hdr.hist.magic(2),'i') | strcmp(hdr.hist.magic(2),'+') ) & ...
223
+	  str2num(hdr.hist.magic(3)) >= 1 & str2num(hdr.hist.magic(3)) <= 9
224
+
225
+      extra.NIFTI_VERSION = str2num(hdr.hist.magic(3));
226
+   else
227
+      extra.NIFTI_VERSION = 0;
228
+   end
229
+
230
+   %  Check if data stored in the same file (*.nii) or separate
231
+   %  files (*.hdr/*.img)
232
+   %
233
+   if isempty(hdr.hist.magic)
234
+      extra.NIFTI_ONEFILE = 0;
235
+   else
236
+      extra.NIFTI_ONEFILE = strcmp(hdr.hist.magic(2), '+');
237
+   end
238
+
239
+   %  Swap has been taken care of by checking whether sizeof_hdr is
240
+   %  348 (machine is 'ieee-le' or 'ieee-be' etc)
241
+   %
242
+   % extra.NIFTI_NEEDS_SWAP = (hdr.dime.dim(1) < 0 | hdr.dime.dim(1) > 7);
243
+
244
+   %  Check NIFTI header struct contains a 5th (vector) dimension
245
+   %
246
+   if hdr.dime.dim(1) > 4 & hdr.dime.dim(6) > 1
247
+      extra.NIFTI_5TH_DIM = hdr.dime.dim(6);
248
+   else
249
+      extra.NIFTI_5TH_DIM = 0;
250
+   end
251
+
252
+   hdr.extra = extra;
253
+
254
+   return;					% extra_nii_hdr
255
+
... ...
@@ -0,0 +1,81 @@
1
+%  When you load any ANALYZE or NIfTI file with 'load_nii.m', and view
2
+%  it with 'view_nii.m', you may find that the image is L-R flipped.
3
+%  This is because of the confusion of radiological and neurological
4
+%  convention in the medical image before NIfTI format is adopted.
5
+%
6
+%  Sometime, people even want to convert RAS (standard orientation) back
7
+%  to LAS orientation to satisfy the legend programs or processes. This
8
+%  program is only written for those purpose. So PLEASE BE VERY CAUTIOUS
9
+%  WHEN USING THIS 'FLIP_LR.M' PROGRAM.
10
+%
11
+%  With 'flip_lr.m', you can convert any ANALYZE or NIfTI (no matter
12
+%  3D or 4D) file to a flipped NIfTI file. This is implemented simply
13
+%  by flipping the affine matrix in the NIfTI header. Since the L-R
14
+%  orientation is determined there, so the image will be flipped.
15
+%
16
+%  Usage: flip_lr(original_fn, flipped_fn, [old_RGB],[tolerance],[preferredForm])
17
+%
18
+%  original_fn  -  filename of the original ANALYZE or NIfTI (3D or 4D) file
19
+%
20
+%  flipped_fn  -  filename of the L-R flipped NIfTI file
21
+%
22
+%  old_RGB (optional)  -  a scale number to tell difference of new RGB24
23
+%	from old RGB24. New RGB24 uses RGB triple sequentially for each
24
+%	voxel, like [R1 G1 B1 R2 G2 B2 ...]. Analyze 6.0 from AnalyzeDirect
25
+%	uses old RGB24, in a way like [R1 R2 ... G1 G2 ... B1 B2 ...] for
26
+%	each slices. If the image that you view is garbled, try to set 
27
+%	old_RGB variable to 1 and try again, because it could be in
28
+%	old RGB24. It will be set to 0, if it is default or empty.
29
+%
30
+%  tolerance (optional) - distortion allowed for non-orthogonal rotation
31
+%	or shearing in NIfTI affine matrix. It will be set to 0.1 (10%),
32
+%	if it is default or empty.
33
+%
34
+%  preferredForm (optional)  -  selects which transformation from voxels
35
+%	to RAS coordinates; values are s,q,S,Q.  Lower case s,q indicate
36
+%	"prefer sform or qform, but use others if preferred not present". 
37
+%	Upper case indicate the program is forced to use the specificied
38
+%	tranform or fail loading.  'preferredForm' will be 's', if it is
39
+%	default or empty.	- Jeff Gunter
40
+%
41
+%  Example: flip_lr('avg152T1_LR_nifti.nii', 'flipped_lr.nii');
42
+%           flip_lr('avg152T1_RL_nifti.nii', 'flipped_rl.nii');
43
+%
44
+%  You will find that 'avg152T1_LR_nifti.nii' and 'avg152T1_RL_nifti.nii'
45
+%  are the same, and 'flipped_lr.nii' and 'flipped_rl.nii' are also the
46
+%  the same, but they are L-R flipped from 'avg152T1_*'.
47
+%
48
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
49
+%
50
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
51
+%
52
+function flip_lr(original_fn, flipped_fn, old_RGB, tolerance, preferredForm)
53
+
54
+   if ~exist('original_fn','var') | ~exist('flipped_fn','var')
55
+      error('Usage: flip_lr(original_fn, flipped_fn, [old_RGB],[tolerance])');
56
+   end
57
+
58
+   if ~exist('old_RGB','var') | isempty(old_RGB)
59
+      old_RGB = 0;
60
+   end
61
+
62
+   if ~exist('tolerance','var') | isempty(tolerance)
63
+      tolerance = 0.1;
64
+   end
65
+
66
+   if ~exist('preferredForm','var') | isempty(preferredForm)
67
+      preferredForm= 's';				% Jeff
68
+   end
69
+
70
+   nii = load_nii(original_fn, [], [], [], [], old_RGB, tolerance, preferredForm);
71
+   M = diag(nii.hdr.dime.pixdim(2:5));
72
+   M(1:3,4) = -M(1:3,1:3)*(nii.hdr.hist.originator(1:3)-1)';
73
+   M(1,:) = -1*M(1,:);
74
+   nii.hdr.hist.sform_code = 1;
75
+   nii.hdr.hist.srow_x = M(1,:);
76
+   nii.hdr.hist.srow_y = M(2,:);
77
+   nii.hdr.hist.srow_z = M(3,:);
78
+   save_nii(nii, flipped_fn);
79
+
80
+   return;					% flip_lr
81
+
... ...
@@ -0,0 +1,108 @@
1
+%  Return time frame of a NIFTI dataset. Support both *.nii and 
2
+%  *.hdr/*.img file extension. If file extension is not provided,
3
+%  *.hdr/*.img will be used as default. 
4
+%
5
+%  It is a lightweighted "load_nii_hdr", and is equivalent to
6
+%  hdr.dime.dim(5)
7
+%  
8
+%  Usage: [ total_scan ] = get_nii_frame(filename)
9
+%
10
+%  filename - NIFTI file name.
11
+%
12
+%  Returned values:
13
+%
14
+%  total_scan - total number of image scans for the time frame
15
+%
16
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
17
+%
18
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
19
+%
20
+function [ total_scan ] = get_nii_frame(fileprefix)
21
+
22
+   if ~exist('fileprefix','var'),
23
+      error('Usage: [ hdr, fileprefix, machine ] = get_nii_frame(filename)');
24
+   end
25
+
26
+   if ~exist('machine','var'), machine = 'ieee-le'; end
27
+
28
+   new_ext = 0;
29
+
30
+   if findstr('.nii',fileprefix)
31
+      new_ext = 1;
32
+      fileprefix = strrep(fileprefix,'.nii','');
33
+   end
34
+
35
+   if findstr('.hdr',fileprefix)
36
+      fileprefix = strrep(fileprefix,'.hdr','');
37
+   end
38
+
39
+   if findstr('.img',fileprefix)
40
+      fileprefix = strrep(fileprefix,'.img','');
41
+   end
42
+
43
+   if new_ext
44
+      fn = sprintf('%s.nii',fileprefix);
45
+
46
+      if ~exist(fn)
47
+         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
48
+         error(msg);
49
+      end
50
+   else
51
+      fn = sprintf('%s.hdr',fileprefix);
52
+
53
+      if ~exist(fn)
54
+         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
55
+         error(msg);
56
+      end
57
+   end
58
+
59
+   fid = fopen(fn,'r',machine);
60
+    
61
+   if fid < 0,
62
+      msg = sprintf('Cannot open file %s.',fn);
63
+      error(msg);
64
+   else
65
+      hdr = read_header(fid);
66
+      fclose(fid);
67
+   end
68
+   
69
+   if hdr.sizeof_hdr ~= 348
70
+      % first try reading the opposite endian to 'machine'
71
+      switch machine,
72
+      case 'ieee-le', machine = 'ieee-be';
73
+      case 'ieee-be', machine = 'ieee-le';
74
+      end
75
+        
76
+      fid = fopen(fn,'r',machine);
77
+        
78
+      if fid < 0,
79
+         msg = sprintf('Cannot open file %s.',fn);
80
+         error(msg);
81
+      else
82
+         hdr = read_header(fid);
83
+         fclose(fid);
84
+      end
85
+   end
86
+
87
+   if hdr.sizeof_hdr ~= 348
88
+      % Now throw an error
89
+      msg = sprintf('File "%s" is corrupted.',fn);
90
+      error(msg);
91
+   end
92
+
93
+   total_scan = hdr.dim(5);
94
+
95
+   return;					% get_nii_frame
96
+
97
+
98
+%---------------------------------------------------------------------
99
+function [ dsr ] = read_header(fid)
100
+
101
+    fseek(fid,0,'bof');
102
+    dsr.sizeof_hdr    = fread(fid,1,'int32')';  % should be 348!
103
+
104
+    fseek(fid,40,'bof');
105
+    dsr.dim           = fread(fid,8,'int16')';
106
+
107
+    return;					% read_header
108
+
... ...
@@ -0,0 +1,230 @@
1
+		        GNU GENERAL PUBLIC LICENSE
2
+		           Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+		    GNU GENERAL PUBLIC LICENSE
10
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
11
+
12
+  0. This License applies to any program or other work which contains
13
+a notice placed by the copyright holder saying it may be distributed
14
+under the terms of this General Public License.  The "Program", below,
15
+refers to any such program or work, and a "work based on the Program"
16
+means either the Program or any derivative work under copyright law:
17
+that is to say, a work containing the Program or a portion of it,
18
+either verbatim or with modifications and/or translated into another
19
+language.  (Hereinafter, translation is included without limitation in
20
+the term "modification".)  Each licensee is addressed as "you".
21
+
22
+Activities other than copying, distribution and modification are not
23
+covered by this License; they are outside its scope.  The act of
24
+running the Program is not restricted, and the output from the Program
25
+is covered only if its contents constitute a work based on the
26
+Program (independent of having been made by running the Program).
27
+Whether that is true depends on what the Program does.
28
+
29
+  1. You may copy and distribute verbatim copies of the Program's
30
+source code as you receive it, in any medium, provided that you
31
+conspicuously and appropriately publish on each copy an appropriate
32
+copyright notice and disclaimer of warranty; keep intact all the
33
+notices that refer to this License and to the absence of any warranty;
34
+and give any other recipients of the Program a copy of this License
35
+along with the Program.
36
+
37
+You may charge a fee for the physical act of transferring a copy, and
38
+you may at your option offer warranty protection in exchange for a fee.
39
+
40
+  2. You may modify your copy or copies of the Program or any portion
41
+of it, thus forming a work based on the Program, and copy and
42
+distribute such modifications or work under the terms of Section 1
43
+above, provided that you also meet all of these conditions:
44
+
45
+    a) You must cause the modified files to carry prominent notices
46
+    stating that you changed the files and the date of any change.
47
+
48
+    b) You must cause any work that you distribute or publish, that in
49
+    whole or in part contains or is derived from the Program or any
50
+    part thereof, to be licensed as a whole at no charge to all third
51
+    parties under the terms of this License.
52
+
53
+    c) If the modified program normally reads commands interactively
54
+    when run, you must cause it, when started running for such
55
+    interactive use in the most ordinary way, to print or display an
56
+    announcement including an appropriate copyright notice and a
57
+    notice that there is no warranty (or else, saying that you provide
58
+    a warranty) and that users may redistribute the program under
59
+    these conditions, and telling the user how to view a copy of this
60
+    License.  (Exception: if the Program itself is interactive but
61
+    does not normally print such an announcement, your work based on
62
+    the Program is not required to print an announcement.)
63
+
64
+These requirements apply to the modified work as a whole.  If
65
+identifiable sections of that work are not derived from the Program,
66
+and can be reasonably considered independent and separate works in
67
+themselves, then this License, and its terms, do not apply to those
68
+sections when you distribute them as separate works.  But when you
69
+distribute the same sections as part of a whole which is a work based
70
+on the Program, the distribution of the whole must be on the terms of
71
+this License, whose permissions for other licensees extend to the
72
+entire whole, and thus to each and every part regardless of who wrote it.
73
+
74
+Thus, it is not the intent of this section to claim rights or contest
75
+your rights to work written entirely by you; rather, the intent is to
76
+exercise the right to control the distribution of derivative or
77
+collective works based on the Program.
78
+
79
+In addition, mere aggregation of another work not based on the Program
80
+with the Program (or with a work based on the Program) on a volume of
81
+a storage or distribution medium does not bring the other work under
82
+the scope of this License.
83
+
84
+  3. You may copy and distribute the Program (or a work based on it,
85
+under Section 2) in object code or executable form under the terms of
86
+Sections 1 and 2 above provided that you also do one of the following:
87
+
88
+    a) Accompany it with the complete corresponding machine-readable
89
+    source code, which must be distributed under the terms of Sections
90
+    1 and 2 above on a medium customarily used for software interchange; or,
91
+
92
+    b) Accompany it with a written offer, valid for at least three
93
+    years, to give any third party, for a charge no more than your
94
+    cost of physically performing source distribution, a complete
95
+    machine-readable copy of the corresponding source code, to be
96
+    distributed under the terms of Sections 1 and 2 above on a medium
97
+    customarily used for software interchange; or,
98
+
99
+    c) Accompany it with the information you received as to the offer
100
+    to distribute corresponding source code.  (This alternative is
101
+    allowed only for noncommercial distribution and only if you
102
+    received the program in object code or executable form with such
103
+    an offer, in accord with Subsection b above.)
104
+
105
+The source code for a work means the preferred form of the work for
106
+making modifications to it.  For an executable work, complete source
107
+code means all the source code for all modules it contains, plus any
108
+associated interface definition files, plus the scripts used to
109
+control compilation and installation of the executable.  However, as a
110
+special exception, the source code distributed need not include
111
+anything that is normally distributed (in either source or binary
112
+form) with the major components (compiler, kernel, and so on) of the
113
+operating system on which the executable runs, unless that component
114
+itself accompanies the executable.
115
+
116
+If distribution of executable or object code is made by offering
117
+access to copy from a designated place, then offering equivalent
118
+access to copy the source code from the same place counts as
119
+distribution of the source code, even though third parties are not
120
+compelled to copy the source along with the object code.
121
+
122
+  4. You may not copy, modify, sublicense, or distribute the Program
123
+except as expressly provided under this License.  Any attempt
124
+otherwise to copy, modify, sublicense or distribute the Program is
125
+void, and will automatically terminate your rights under this License.
126
+However, parties who have received copies, or rights, from you under
127
+this License will not have their licenses terminated so long as such
128
+parties remain in full compliance.
129
+
130
+  5. You are not required to accept this License, since you have not
131
+signed it.  However, nothing else grants you permission to modify or
132
+distribute the Program or its derivative works.  These actions are
133
+prohibited by law if you do not accept this License.  Therefore, by
134
+modifying or distributing the Program (or any work based on the
135
+Program), you indicate your acceptance of this License to do so, and
136
+all its terms and conditions for copying, distributing or modifying
137
+the Program or works based on it.
138
+
139
+  6. Each time you redistribute the Program (or any work based on the
140
+Program), the recipient automatically receives a license from the
141
+original licensor to copy, distribute or modify the Program subject to
142
+these terms and conditions.  You may not impose any further
143
+restrictions on the recipients' exercise of the rights granted herein.
144
+You are not responsible for enforcing compliance by third parties to
145
+this License.
146
+
147
+  7. If, as a consequence of a court judgment or allegation of patent
148
+infringement or for any other reason (not limited to patent issues),
149
+conditions are imposed on you (whether by court order, agreement or
150
+otherwise) that contradict the conditions of this License, they do not
151
+excuse you from the conditions of this License.  If you cannot
152
+distribute so as to satisfy simultaneously your obligations under this
153
+License and any other pertinent obligations, then as a consequence you
154
+may not distribute the Program at all.  For example, if a patent
155
+license would not permit royalty-free redistribution of the Program by
156
+all those who receive copies directly or indirectly through you, then
157
+the only way you could satisfy both it and this License would be to
158
+refrain entirely from distribution of the Program.
159
+
160
+If any portion of this section is held invalid or unenforceable under
161
+any particular circumstance, the balance of the section is intended to
162
+apply and the section as a whole is intended to apply in other
163
+circumstances.
164
+
165
+It is not the purpose of this section to induce you to infringe any
166
+patents or other property right claims or to contest validity of any
167
+such claims; this section has the sole purpose of protecting the
168
+integrity of the free software distribution system, which is
169
+implemented by public license practices.  Many people have made
170
+generous contributions to the wide range of software distributed
171
+through that system in reliance on consistent application of that
172
+system; it is up to the author/donor to decide if he or she is willing
173
+to distribute software through any other system and a licensee cannot
174
+impose that choice.
175
+
176
+This section is intended to make thoroughly clear what is believed to
177
+be a consequence of the rest of this License.
178
+
179
+  8. If the distribution and/or use of the Program is restricted in
180
+certain countries either by patents or by copyrighted interfaces, the
181
+original copyright holder who places the Program under this License
182
+may add an explicit geographical distribution limitation excluding
183
+those countries, so that distribution is permitted only in or among
184
+countries not thus excluded.  In such case, this License incorporates
185
+the limitation as if written in the body of this License.
186
+
187
+  9. The Free Software Foundation may publish revised and/or new versions
188
+of the General Public License from time to time.  Such new versions will
189
+be similar in spirit to the present version, but may differ in detail to
190
+address new problems or concerns.
191
+
192
+Each version is given a distinguishing version number.  If the Program
193
+specifies a version number of this License which applies to it and "any
194
+later version", you have the option of following the terms and conditions
195
+either of that version or of any later version published by the Free
196
+Software Foundation.  If the Program does not specify a version number of
197
+this License, you may choose any version ever published by the Free Software
198
+Foundation.
199
+
200
+  10. If you wish to incorporate parts of the Program into other free
201
+programs whose distribution conditions are different, write to the author
202
+to ask for permission.  For software which is copyrighted by the Free
203
+Software Foundation, write to the Free Software Foundation; we sometimes
204
+make exceptions for this.  Our decision will be guided by the two goals
205
+of preserving the free status of all derivatives of our free software and
206
+of promoting the sharing and reuse of software generally.
207
+
208
+			    NO WARRANTY
209
+
210
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
211
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
212
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
213
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
214
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
215
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
216
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
217
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
218
+REPAIR OR CORRECTION.
219
+
220
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
221
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
222
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
223
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
224
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
225
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
226
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
227
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
228
+POSSIBILITY OF SUCH DAMAGES.
229
+
230
+		     END OF TERMS AND CONDITIONS
... ...
@@ -0,0 +1,138 @@
1
+%  Load NIFTI or ANALYZE dataset. Support both *.nii and *.hdr/*.img
2
+%  file extension. If file extension is not provided, *.hdr/*.img will
3
+%  be used as default.
4
+%
5
+%  A subset of NIFTI transform is included. For non-orthogonal rotation,
6
+%  shearing etc., please use 'reslice_nii.m' to reslice the NIFTI file.
7
+%  It will not cause negative effect, as long as you remember not to do
8
+%  slice time correction after reslicing the NIFTI file. Output variable
9
+%  nii will be in RAS orientation, i.e. X axis from Left to Right,
10
+%  Y axis from Posterior to Anterior, and Z axis from Inferior to
11
+%  Superior.
12
+%  
13
+%  Usage: nii = load_nii(filename, [img_idx], [dim5_idx], [dim6_idx], ...
14
+%			[dim7_idx], [old_RGB], [tolerance], [preferredForm])
15
+%  
16
+%  filename  - 	NIFTI or ANALYZE file name.
17
+%  
18
+%  img_idx (optional)  -  a numerical array of 4th dimension indices,
19
+%	which is the indices of image scan volume. The number of images
20
+%	scan volumes can be obtained from get_nii_frame.m, or simply
21
+%	hdr.dime.dim(5). Only the specified volumes will be loaded. 
22
+%	All available image volumes will be loaded, if it is default or
23
+%	empty.
24
+%
25
+%  dim5_idx (optional)  -  a numerical array of 5th dimension indices.
26
+%	Only the specified range will be loaded. All available range
27
+%	will be loaded, if it is default or empty.
28
+%
29
+%  dim6_idx (optional)  -  a numerical array of 6th dimension indices.
30
+%	Only the specified range will be loaded. All available range
31
+%	will be loaded, if it is default or empty.
32
+%
33
+%  dim7_idx (optional)  -  a numerical array of 7th dimension indices.
34
+%	Only the specified range will be loaded. All available range
35
+%	will be loaded, if it is default or empty.
36
+%
37
+%  old_RGB (optional)  -  a scale number to tell difference of new RGB24
38
+%	from old RGB24. New RGB24 uses RGB triple sequentially for each
39
+%	voxel, like [R1 G1 B1 R2 G2 B2 ...]. Analyze 6.0 from AnalyzeDirect
40
+%	uses old RGB24, in a way like [R1 R2 ... G1 G2 ... B1 B2 ...] for
41
+%	each slices. If the image that you view is garbled, try to set 
42
+%	old_RGB variable to 1 and try again, because it could be in
43
+%	old RGB24. It will be set to 0, if it is default or empty.
44
+%
45
+%  tolerance (optional) - distortion allowed in the loaded image for any
46
+%	non-orthogonal rotation or shearing of NIfTI affine matrix. If 
47
+%	you set 'tolerance' to 0, it means that you do not allow any 
48
+%	distortion. If you set 'tolerance' to 1, it means that you do 
49
+%	not care any distortion. The image will fail to be loaded if it
50
+%	can not be tolerated. The tolerance will be set to 0.1 (10%), if
51
+%	it is default or empty.
52
+%
53
+%  preferredForm (optional)  -  selects which transformation from voxels
54
+%	to RAS coordinates; values are s,q,S,Q.  Lower case s,q indicate
55
+%	"prefer sform or qform, but use others if preferred not present". 
56
+%	Upper case indicate the program is forced to use the specificied
57
+%	tranform or fail loading.  'preferredForm' will be 's', if it is
58
+%	default or empty.	- Jeff Gunter
59
+%
60
+%  Returned values:
61
+%  
62
+%  nii structure:
63
+%
64
+%	hdr -		struct with NIFTI header fields.
65
+%
66
+%	filetype -	Analyze format .hdr/.img (0); 
67
+%			NIFTI .hdr/.img (1);
68
+%			NIFTI .nii (2)
69
+%
70
+%	fileprefix - 	NIFTI filename without extension.
71
+%
72
+%	machine - 	machine string variable.
73
+%
74
+%	img - 		3D (or 4D) matrix of NIFTI data.
75
+%
76
+%	original -	the original header before any affine transform.
77
+%  
78
+%  Part of this file is copied and modified under GNU license from
79
+%  MRI_TOOLBOX developed by CNSP in Flinders University, Australia
80
+%  
81
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
82
+%  
83
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
84
+%
85
+function nii = load_nii(filename, img_idx, dim5_idx, dim6_idx, dim7_idx, ...
86
+			old_RGB, tolerance, preferredForm)
87
+
88
+   if ~exist('filename','var')
89
+      error('Usage: nii = load_nii(filename, [img_idx], [dim5_idx], [dim6_idx], [dim7_idx], [old_RGB], [tolerance], [preferredForm])');
90
+   end
91
+
92
+   if ~exist('img_idx','var') | isempty(img_idx)
93
+      img_idx = [];
94
+   end
95
+
96
+   if ~exist('dim5_idx','var') | isempty(dim5_idx)
97
+      dim5_idx = [];
98
+   end
99
+
100
+   if ~exist('dim6_idx','var') | isempty(dim6_idx)
101
+      dim6_idx = [];
102
+   end
103
+
104
+   if ~exist('dim7_idx','var') | isempty(dim7_idx)
105
+      dim7_idx = [];
106
+   end
107
+
108
+   if ~exist('old_RGB','var') | isempty(old_RGB)
109
+      old_RGB = 0;
110
+   end
111
+
112
+   if ~exist('tolerance','var') | isempty(tolerance)
113
+      tolerance = 0.1;			% 10 percent
114
+   end
115
+
116
+   if ~exist('preferredForm','var') | isempty(preferredForm)
117
+      preferredForm= 's';		% Jeff
118
+   end
119
+
120
+   %  Read the dataset header
121
+   %
122
+   [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename);
123
+
124
+   %  Read the header extension
125
+   %
126
+%   nii.ext = load_nii_ext(filename);
127
+
128
+   %  Read the dataset body
129
+   %
130
+   [nii.img,nii.hdr] = load_nii_img(nii.hdr,nii.filetype,nii.fileprefix, ...
131
+		nii.machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB);
132
+
133
+   %  Perform some of sform/qform transform
134
+   %
135
+   nii = xform_nii(nii, tolerance, preferredForm);
136
+
137
+   return					% load_nii
138
+
... ...
@@ -0,0 +1,148 @@
1
+%  Load NIFTI header extension after its header is loaded using load_nii_hdr.
2
+%
3
+%  Usage: ext = load_nii_ext(filename)
4
+%
5
+%  filename - NIFTI file name.
6
+%
7
+%  Returned values:
8
+%
9
+%  ext - Structure of NIFTI header extension, which includes num_ext,
10
+%       and all the extended header sections in the header extension.
11
+%       Each extended header section will have its esize, ecode, and
12
+%       edata, where edata can be plain text, xml, or any raw data
13
+%       that was saved in the extended header section.
14
+%
15
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
16
+%
17
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
18
+%
19
+function ext = load_nii_ext(fileprefix)
20
+
21
+   if ~exist('fileprefix','var'),
22
+      error('Usage: ext = load_nii_ext(filename)');
23
+   end
24
+
25
+   machine = 'ieee-le';
26
+   new_ext = 0;
27
+
28
+   if findstr('.nii',fileprefix)
29
+      new_ext = 1;
30
+      fileprefix = strrep(fileprefix,'.nii','');
31
+   end
32
+
33
+   if findstr('.hdr',fileprefix)
34
+      fileprefix = strrep(fileprefix,'.hdr','');
35
+   end
36
+
37
+   if findstr('.img',fileprefix)
38
+      fileprefix = strrep(fileprefix,'.img','');
39
+   end
40
+
41
+   if new_ext
42
+      fn = sprintf('%s.nii',fileprefix);
43
+
44
+      if ~exist(fn)
45
+         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
46
+         error(msg);
47
+      end
48
+   else
49
+      fn = sprintf('%s.hdr',fileprefix);
50
+
51
+      if ~exist(fn)
52
+         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
53
+         error(msg);
54
+      end
55
+   end
56
+
57
+   fid = fopen(fn,'r',machine);
58
+   vox_offset = 0;
59
+    
60
+   if fid < 0,
61
+      msg = sprintf('Cannot open file %s.',fn);
62
+      error(msg);
63
+   else
64
+      fseek(fid,0,'bof');
65
+
66
+      if fread(fid,1,'int32') == 348
67
+         if new_ext
68
+            fseek(fid,108,'bof');
69
+            vox_offset = fread(fid,1,'float32');
70
+         end
71
+
72
+         ext = read_extension(fid, vox_offset);
73
+         fclose(fid);
74
+      else
75
+         fclose(fid);
76
+
77
+         %  first try reading the opposite endian to 'machine'
78
+         %
79
+         switch machine,
80
+         case 'ieee-le', machine = 'ieee-be';
81
+         case 'ieee-be', machine = 'ieee-le';
82
+         end
83
+
84
+         fid = fopen(fn,'r',machine);
85
+
86
+         if fid < 0,
87
+            msg = sprintf('Cannot open file %s.',fn);
88
+            error(msg);
89
+         else
90
+            fseek(fid,0,'bof');
91
+
92
+            if fread(fid,1,'int32') ~= 348
93
+
94
+               %  Now throw an error
95
+               %
96
+               msg = sprintf('File "%s" is corrupted.',fn);
97
+               error(msg);
98
+            end
99
+
100
+            if new_ext
101
+               fseek(fid,108,'bof');
102
+               vox_offset = fread(fid,1,'float32');
103
+            end
104
+
105
+            ext = read_extension(fid, vox_offset);
106
+            fclose(fid);
107
+         end
108
+      end
109
+   end
110
+
111
+   return                                       % load_nii_ext
112
+
113
+
114
+%---------------------------------------------------------------------
115
+function ext = read_extension(fid, vox_offset)
116
+
117
+   ext = [];
118
+
119
+   if vox_offset
120
+      end_of_ext = vox_offset;
121
+   else
122
+      fseek(fid, 0, 'eof');
123
+      end_of_ext = ftell(fid);
124
+   end
125
+
126
+   if end_of_ext > 352
127
+      fseek(fid, 348, 'bof');
128
+      ext.extension = fread(fid,4)';
129
+   end
130
+
131
+   if isempty(ext) | ext.extension(1) == 0
132
+      ext = [];
133
+      return;
134
+   end
135
+
136
+   i = 1;
137
+
138
+   while(ftell(fid) < end_of_ext)
139
+      ext.section(i).esize = fread(fid,1,'int32');
140
+      ext.section(i).ecode = fread(fid,1,'int32');
141
+      ext.section(i).edata = char(fread(fid,ext.section(i).esize-8)');
142
+      i = i + 1;
143
+   end
144
+
145
+   ext.num_ext = length(ext.section);
146
+
147
+   return                                               % read_extension
148
+
... ...
@@ -0,0 +1,320 @@
1
+%  Load NIFTI dataset header. Support both *.nii and *.hdr/*.img file
2
+%  extension. If file extension is not provided, *.hdr/*.img will be 
3
+%  used as default.
4
+%  
5
+%  Usage: [hdr, filetype, fileprefix, machine] = load_nii_hdr(filename)
6
+%  
7
+%  filename - NIFTI file name.
8
+%  
9
+%  Returned values:
10
+%  
11
+%  hdr - struct with NIFTI header fields.
12
+%  
13
+%  filetype	- 0 for Analyze format (*.hdr/*.img);
14
+%		  1 for NIFTI format in 2 files (*.hdr/*.img);
15
+%		  2 for NIFTI format in 1 file (*.nii).
16
+%  
17
+%  fileprefix - NIFTI file name without extension.
18
+%  
19
+%  machine    - a string, see below for details. The default here is 'ieee-le'.
20
+%
21
+%    'native'      or 'n' - local machine format - the default
22
+%    'ieee-le'     or 'l' - IEEE floating point with little-endian
23
+%                           byte ordering
24
+%    'ieee-be'     or 'b' - IEEE floating point with big-endian
25
+%                           byte ordering
26
+%    'vaxd'        or 'd' - VAX D floating point and VAX ordering
27
+%    'vaxg'        or 'g' - VAX G floating point and VAX ordering
28
+%    'cray'        or 'c' - Cray floating point with big-endian
29
+%                           byte ordering
30
+%    'ieee-le.l64' or 'a' - IEEE floating point with little-endian
31
+%                           byte ordering and 64 bit long data type
32
+%    'ieee-be.l64' or 's' - IEEE floating point with big-endian byte
33
+%                           ordering and 64 bit long data type.
34
+%  
35
+%  Number of scanned images in the file can be obtained by:
36
+%  num_scan = hdr.dime.dim(5)
37
+%
38
+%  Part of this file is copied and modified under GNU license from
39
+%  MRI_TOOLBOX developed by CNSP in Flinders University, Australia
40
+%
41
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
42
+%
43
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
44
+%
45
+function [hdr, filetype, fileprefix, machine] = load_nii_hdr(fileprefix)
46
+
47
+   if ~exist('fileprefix','var'),
48
+      error('Usage: [hdr, filetype, fileprefix, machine] = load_nii_hdr(filename)');
49
+   end
50
+
51
+   machine = 'ieee-le';
52
+   new_ext = 0;
53
+
54
+   if findstr('.nii',fileprefix)
55
+      new_ext = 1;
56
+      fileprefix = strrep(fileprefix,'.nii','');
57
+   end
58
+
59
+   if findstr('.hdr',fileprefix)
60
+      fileprefix = strrep(fileprefix,'.hdr','');
61
+   end
62
+
63
+   if findstr('.img',fileprefix)
64
+      fileprefix = strrep(fileprefix,'.img','');
65
+   end
66
+
67
+   if new_ext
68
+      fn = sprintf('%s.nii',fileprefix);
69
+
70
+      if ~exist(fn)
71
+         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
72
+         error(msg);
73
+      end
74
+   else
75
+      fn = sprintf('%s.hdr',fileprefix);
76
+
77
+      if ~exist(fn)
78
+         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
79
+         error(msg);
80
+      end
81
+   end
82
+
83
+   fid = fopen(fn,'r',machine);
84
+    
85
+   if fid < 0,
86
+      msg = sprintf('Cannot open file %s.',fn);
87
+      error(msg);
88
+   else
89
+      fseek(fid,0,'bof');
90
+
91
+      if fread(fid,1,'int32') == 348
92
+         hdr = read_header(fid);
93
+         fclose(fid);
94
+      else
95
+         fclose(fid);
96
+
97
+         %  first try reading the opposite endian to 'machine'
98
+         %
99
+         switch machine,
100
+         case 'ieee-le', machine = 'ieee-be';
101
+         case 'ieee-be', machine = 'ieee-le';
102
+         end
103
+
104
+         fid = fopen(fn,'r',machine);
105
+
106
+         if fid < 0,
107
+            msg = sprintf('Cannot open file %s.',fn);
108
+            error(msg);
109
+         else
110
+            fseek(fid,0,'bof');
111
+
112
+            if fread(fid,1,'int32') ~= 348
113
+
114
+               %  Now throw an error
115
+               %
116
+               msg = sprintf('File "%s" is corrupted.',fn);
117
+               error(msg);
118
+            end
119
+
120
+            hdr = read_header(fid);
121
+            fclose(fid);
122
+         end
123
+      end
124
+   end
125
+
126
+   if strcmp(hdr.hist.magic, 'n+1')
127
+      filetype = 2;
128
+   elseif strcmp(hdr.hist.magic, 'ni1')
129
+      filetype = 1;
130
+   else
131
+      filetype = 0;
132
+   end
133
+
134
+   return					% load_nii_hdr
135
+
136
+
137
+%---------------------------------------------------------------------
138
+function [ dsr ] = read_header(fid)
139
+
140
+        %  Original header structures
141
+	%  struct dsr
142
+	%       { 
143
+	%       struct header_key hk;            /*   0 +  40       */
144
+	%       struct image_dimension dime;     /*  40 + 108       */
145
+	%       struct data_history hist;        /* 148 + 200       */
146
+	%       };                               /* total= 348 bytes*/
147
+
148
+    dsr.hk   = header_key(fid);
149
+    dsr.dime = image_dimension(fid);
150
+    dsr.hist = data_history(fid);
151
+
152
+    %  For Analyze data format
153
+    %
154
+    if ~strcmp(dsr.hist.magic, 'n+1') & ~strcmp(dsr.hist.magic, 'ni1')
155
+        dsr.hist.qform_code = 0;
156
+        dsr.hist.sform_code = 0;
157
+    end
158
+
159
+    return					% read_header
160
+
161
+
162
+%---------------------------------------------------------------------
163
+function [ hk ] = header_key(fid)
164
+
165
+    fseek(fid,0,'bof');
166
+    
167
+	%  Original header structures	
168
+	%  struct header_key                     /* header key      */ 
169
+	%       {                                /* off + size      */
170
+	%       int sizeof_hdr                   /*  0 +  4         */
171
+	%       char data_type[10];              /*  4 + 10         */
172
+	%       char db_name[18];                /* 14 + 18         */
173
+	%       int extents;                     /* 32 +  4         */
174
+	%       short int session_error;         /* 36 +  2         */
175
+	%       char regular;                    /* 38 +  1         */
176
+	%       char dim_info;   % char hkey_un0;        /* 39 +  1 */
177
+	%       };                               /* total=40 bytes  */
178
+	%
179
+	% int sizeof_header   Should be 348.
180
+	% char regular        Must be 'r' to indicate that all images and 
181
+	%                     volumes are the same size. 
182
+
183
+    v6 = version;
184
+    if str2num(v6(1))<6
185
+       directchar = '*char';
186
+    else
187
+       directchar = 'uchar=>char';
188
+    end
189
+
190
+    hk.sizeof_hdr    = fread(fid, 1,'int32')';	% should be 348!
191
+    hk.data_type     = deblank(fread(fid,10,directchar)');
192
+    hk.db_name       = deblank(fread(fid,18,directchar)');
193
+    hk.extents       = fread(fid, 1,'int32')';
194
+    hk.session_error = fread(fid, 1,'int16')';
195
+    hk.regular       = fread(fid, 1,directchar)';
196
+    hk.dim_info      = fread(fid, 1,'uchar')';
197
+    
198
+    return					% header_key
199
+
200
+
201
+%---------------------------------------------------------------------
202
+function [ dime ] = image_dimension(fid)
203
+
204
+	%  Original header structures    
205
+	%  struct image_dimension
206
+	%       {                                /* off + size      */
207
+	%       short int dim[8];                /* 0 + 16          */
208
+        %       /*
209
+        %           dim[0]      Number of dimensions in database; usually 4. 
210
+        %           dim[1]      Image X dimension;  number of *pixels* in an image row. 
211
+        %           dim[2]      Image Y dimension;  number of *pixel rows* in slice. 
212
+        %           dim[3]      Volume Z dimension; number of *slices* in a volume. 
213
+        %           dim[4]      Time points; number of volumes in database
214
+        %       */
215
+	%       float intent_p1;   % char vox_units[4];   /* 16 + 4       */
216
+	%       float intent_p2;   % char cal_units[8];   /* 20 + 4       */
217
+	%       float intent_p3;   % char cal_units[8];   /* 24 + 4       */
218
+	%       short int intent_code;   % short int unused1;   /* 28 + 2 */
219
+	%       short int datatype;              /* 30 + 2          */
220
+	%       short int bitpix;                /* 32 + 2          */
221
+	%       short int slice_start;   % short int dim_un0;   /* 34 + 2 */
222
+	%       float pixdim[8];                 /* 36 + 32         */
223
+	%	/*
224
+	%		pixdim[] specifies the voxel dimensions:
225
+	%		pixdim[1] - voxel width, mm
226
+	%		pixdim[2] - voxel height, mm
227
+	%		pixdim[3] - slice thickness, mm
228
+	%		pixdim[4] - volume timing, in msec
229
+	%					..etc
230
+	%	*/
231
+	%       float vox_offset;                /* 68 + 4          */
232
+	%       float scl_slope;   % float roi_scale;     /* 72 + 4 */
233
+	%       float scl_inter;   % float funused1;      /* 76 + 4 */
234
+	%       short slice_end;   % float funused2;      /* 80 + 2 */
235
+	%       char slice_code;   % float funused2;      /* 82 + 1 */
236
+	%       char xyzt_units;   % float funused2;      /* 83 + 1 */
237
+	%       float cal_max;                   /* 84 + 4          */
238
+	%       float cal_min;                   /* 88 + 4          */
239
+	%       float slice_duration;   % int compressed; /* 92 + 4 */
240
+	%       float toffset;   % int verified;          /* 96 + 4 */
241
+	%       int glmax;                       /* 100 + 4         */
242
+	%       int glmin;                       /* 104 + 4         */
243
+	%       };                               /* total=108 bytes */
244
+	
245
+    dime.dim        = fread(fid,8,'int16')';
246
+    dime.intent_p1  = fread(fid,1,'float32')';
247
+    dime.intent_p2  = fread(fid,1,'float32')';
248
+    dime.intent_p3  = fread(fid,1,'float32')';
249
+    dime.intent_code = fread(fid,1,'int16')';
250
+    dime.datatype   = fread(fid,1,'int16')';
251
+    dime.bitpix     = fread(fid,1,'int16')';
252
+    dime.slice_start = fread(fid,1,'int16')';
253
+    dime.pixdim     = abs(fread(fid,8,'float32')');
254
+    dime.vox_offset = fread(fid,1,'float32')';
255
+    dime.scl_slope  = fread(fid,1,'float32')';
256
+    dime.scl_inter  = fread(fid,1,'float32')';
257
+    dime.slice_end  = fread(fid,1,'int16')';
258
+    dime.slice_code = fread(fid,1,'uchar')';
259
+    dime.xyzt_units = fread(fid,1,'uchar')';
260
+    dime.cal_max    = fread(fid,1,'float32')';
261
+    dime.cal_min    = fread(fid,1,'float32')';
262
+    dime.slice_duration = fread(fid,1,'float32')';
263
+    dime.toffset    = fread(fid,1,'float32')';
264
+    dime.glmax      = fread(fid,1,'int32')';
265
+    dime.glmin      = fread(fid,1,'int32')';
266
+        
267
+    return					% image_dimension
268
+
269
+
270
+%---------------------------------------------------------------------
271
+function [ hist ] = data_history(fid)
272
+        
273
+	%  Original header structures
274
+	%  struct data_history       
275
+	%       {                                /* off + size      */
276
+	%       char descrip[80];                /* 0 + 80          */
277
+	%       char aux_file[24];               /* 80 + 24         */
278
+	%       short int qform_code;            /* 104 + 2         */
279
+	%       short int sform_code;            /* 106 + 2         */
280
+	%       float quatern_b;                 /* 108 + 4         */
281
+	%       float quatern_c;                 /* 112 + 4         */
282
+	%       float quatern_d;                 /* 116 + 4         */
283
+	%       float qoffset_x;                 /* 120 + 4         */
284
+	%       float qoffset_y;                 /* 124 + 4         */
285
+	%       float qoffset_z;                 /* 128 + 4         */
286
+	%       float srow_x[4];                 /* 132 + 16        */
287
+	%       float srow_y[4];                 /* 148 + 16        */
288
+	%       float srow_z[4];                 /* 164 + 16        */
289
+	%       char intent_name[16];            /* 180 + 16        */
290
+	%       char magic[4];   % int smin;     /* 196 + 4         */
291
+	%       };                               /* total=200 bytes */
292
+
293
+    v6 = version;
294
+    if str2num(v6(1))<6
295
+       directchar = '*char';
296
+    else
297
+       directchar = 'uchar=>char';
298
+    end
299
+
300
+    hist.descrip     = deblank(fread(fid,80,directchar)');
301
+    hist.aux_file    = deblank(fread(fid,24,directchar)');
302
+    hist.qform_code  = fread(fid,1,'int16')';
303
+    hist.sform_code  = fread(fid,1,'int16')';
304
+    hist.quatern_b   = fread(fid,1,'float32')';
305
+    hist.quatern_c   = fread(fid,1,'float32')';
306
+    hist.quatern_d   = fread(fid,1,'float32')';
307
+    hist.qoffset_x   = fread(fid,1,'float32')';
308
+    hist.qoffset_y   = fread(fid,1,'float32')';
309
+    hist.qoffset_z   = fread(fid,1,'float32')';
310
+    hist.srow_x      = fread(fid,4,'float32')';
311
+    hist.srow_y      = fread(fid,4,'float32')';
312
+    hist.srow_z      = fread(fid,4,'float32')';
313
+    hist.intent_name = deblank(fread(fid,16,directchar)');
314
+    hist.magic       = deblank(fread(fid,4,directchar)');
315
+
316
+    fseek(fid,253,'bof');
317
+    hist.originator  = fread(fid, 5,'int16')';
318
+    
319
+    return					% data_history
320
+
... ...
@@ -0,0 +1,385 @@
1
+%  internal function
2
+
3
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
4
+
5
+function [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB)
6
+
7
+   if ~exist('hdr','var') | ~exist('filetype','var') | ~exist('fileprefix','var') | ~exist('machine','var')
8
+      error('Usage: [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,[img_idx],[dim5_idx],[dim6_idx],[dim7_idx],[old_RGB]);');
9
+   end
10
+
11
+   if ~exist('img_idx','var') | isempty(img_idx) | hdr.dime.dim(5)<1
12
+      img_idx = [];
13
+   end
14
+
15
+   if ~exist('dim5_idx','var') | isempty(dim5_idx) | hdr.dime.dim(6)<1
16
+      dim5_idx = [];
17
+   end
18
+
19
+   if ~exist('dim6_idx','var') | isempty(dim6_idx) | hdr.dime.dim(7)<1
20
+      dim6_idx = [];
21
+   end
22
+
23
+   if ~exist('dim7_idx','var') | isempty(dim7_idx) | hdr.dime.dim(8)<1
24
+      dim7_idx = [];
25
+   end
26
+
27
+   if ~exist('old_RGB','var') | isempty(old_RGB)
28
+      old_RGB = 0;
29
+   end
30
+
31
+   %  check img_idx
32
+   %
33
+   if ~isempty(img_idx) & ~isnumeric(img_idx)
34
+      error('"img_idx" should be a numerical array.');
35
+   end
36
+
37
+   if length(unique(img_idx)) ~= length(img_idx)
38
+      error('Duplicate image index in "img_idx"');
39
+   end
40
+
41
+   if ~isempty(img_idx) & (min(img_idx) < 1 | max(img_idx) > hdr.dime.dim(5))
42
+      max_range = hdr.dime.dim(5);
43
+
44
+      if max_range == 1
45
+         error(['"img_idx" should be 1.']);
46
+      else
47
+         range = ['1 ' num2str(max_range)];
48
+         error(['"img_idx" should be an integer within the range of [' range '].']);
49
+      end
50
+   end
51
+
52
+   %  check dim5_idx
53
+   %
54
+   if ~isempty(dim5_idx) & ~isnumeric(dim5_idx)
55
+      error('"dim5_idx" should be a numerical array.');
56
+   end
57
+
58
+   if length(unique(dim5_idx)) ~= length(dim5_idx)
59
+      error('Duplicate image index in "dim5_idx"');
60
+   end
61
+
62
+   if ~isempty(dim5_idx) & (min(dim5_idx) < 1 | max(dim5_idx) > hdr.dime.dim(6))
63
+      max_range = hdr.dime.dim(6);
64
+
65
+      if max_range == 1
66
+         error(['"dim5_idx" should be 1.']);
67
+      else
68
+         range = ['1 ' num2str(max_range)];
69
+         error(['"dim5_idx" should be an integer within the range of [' range '].']);
70
+      end
71
+   end
72
+
73
+   %  check dim6_idx
74
+   %
75
+   if ~isempty(dim6_idx) & ~isnumeric(dim6_idx)
76
+      error('"dim6_idx" should be a numerical array.');
77
+   end
78
+
79
+   if length(unique(dim6_idx)) ~= length(dim6_idx)
80
+      error('Duplicate image index in "dim6_idx"');
81
+   end
82
+
83
+   if ~isempty(dim6_idx) & (min(dim6_idx) < 1 | max(dim6_idx) > hdr.dime.dim(7))
84
+      max_range = hdr.dime.dim(7);
85
+
86
+      if max_range == 1
87
+         error(['"dim6_idx" should be 1.']);
88
+      else
89
+         range = ['1 ' num2str(max_range)];
90
+         error(['"dim6_idx" should be an integer within the range of [' range '].']);
91
+      end
92
+   end
93
+
94
+   %  check dim7_idx
95
+   %
96
+   if ~isempty(dim7_idx) & ~isnumeric(dim7_idx)
97
+      error('"dim7_idx" should be a numerical array.');
98
+   end
99
+
100
+   if length(unique(dim7_idx)) ~= length(dim7_idx)
101
+      error('Duplicate image index in "dim7_idx"');
102
+   end
103
+
104
+   if ~isempty(dim7_idx) & (min(dim7_idx) < 1 | max(dim7_idx) > hdr.dime.dim(8))
105
+      max_range = hdr.dime.dim(8);
106
+
107
+      if max_range == 1
108
+         error(['"dim7_idx" should be 1.']);
109
+      else
110
+         range = ['1 ' num2str(max_range)];
111
+         error(['"dim7_idx" should be an integer within the range of [' range '].']);
112
+      end
113
+   end
114
+
115
+   [img,hdr] = read_image(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB);
116
+
117
+   return					% load_nii_img
118
+
119
+
120
+%---------------------------------------------------------------------
121
+function [img,hdr] = read_image(hdr, filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB)
122
+
123
+   switch filetype
124
+   case {0, 1}
125
+      fn = [fileprefix '.img'];
126
+   case 2
127
+      fn = [fileprefix '.nii'];
128
+   end
129
+
130
+   fid = fopen(fn,'r',machine);
131
+
132
+   if fid < 0,
133
+      msg = sprintf('Cannot open file %s.',fn);
134
+      error(msg);
135
+   end
136
+
137
+   %  Set bitpix according to datatype
138
+   %
139
+   %  /*Acceptable values for datatype are*/ 
140
+   %
141
+   %     0 None                     (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN 
142
+   %     1 Binary                         (ubit1, bitpix=1) % DT_BINARY 
143
+   %     2 Unsigned char         (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8 
144
+   %     4 Signed short                  (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16 
145
+   %     8 Signed integer                (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32 
146
+   %    16 Floating point    (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32 
147
+   %    32 Complex, 2 float32      (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64
148
+   %    64 Double precision  (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64 
149
+   %   128 uint8 RGB                 (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24 
150
+   %   256 Signed char            (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8 
151
+   %   511 Single RGB              (Use float32, bitpix=96) % DT_RGB96, NIFTI_TYPE_RGB96
152
+   %   512 Unsigned short               (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16 
153
+   %   768 Unsigned integer             (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32 
154
+   %  1024 Signed long long              (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64
155
+   %  1280 Unsigned long long           (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64 
156
+   %  1536 Long double, float128  (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128 
157
+   %  1792 Complex128, 2 float64  (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 
158
+   %  2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 
159
+   %
160
+   switch hdr.dime.datatype
161
+   case   1,
162
+      hdr.dime.bitpix = 1;  precision = 'ubit1';
163
+   case   2,
164
+      hdr.dime.bitpix = 8;  precision = 'uint8';
165
+   case   4,
166
+      hdr.dime.bitpix = 16; precision = 'int16';
167
+   case   8,
168
+      hdr.dime.bitpix = 32; precision = 'int32';
169
+   case  16,
170
+      hdr.dime.bitpix = 32; precision = 'float32';
171
+   case  32,
172
+      hdr.dime.bitpix = 64; precision = 'float32';
173
+   case  64,
174
+      hdr.dime.bitpix = 64; precision = 'float64';
175
+   case 128,
176
+      hdr.dime.bitpix = 24; precision = 'uint8';
177
+   case 256 
178
+      hdr.dime.bitpix = 8;  precision = 'int8';
179
+   case 511 
180
+      hdr.dime.bitpix = 96; precision = 'float32';
181
+   case 512 
182
+      hdr.dime.bitpix = 16; precision = 'uint16';
183
+   case 768 
184
+      hdr.dime.bitpix = 32; precision = 'uint32';
185
+   case 1024
186
+      hdr.dime.bitpix = 64; precision = 'int64';
187
+   case 1280
188
+      hdr.dime.bitpix = 64; precision = 'uint64';
189
+   case 1792,
190
+      hdr.dime.bitpix = 128; precision = 'float64';
191
+   otherwise
192
+      error('This datatype is not supported'); 
193
+   end
194
+
195
+   hdr.dime.dim(find(hdr.dime.dim < 1)) = 1;
196
+
197
+   %  move pointer to the start of image block
198
+   %
199
+   switch filetype
200
+   case {0, 1}
201
+      fseek(fid, 0, 'bof');
202
+   case 2
203
+      fseek(fid, hdr.dime.vox_offset, 'bof');
204
+   end
205
+
206
+   %  Load whole image block for old Analyze format or binary image;
207
+   %  otherwise, load images that are specified in img_idx, dim5_idx,
208
+   %  dim6_idx, and dim7_idx
209
+   %
210
+   %  For binary image, we have to read all because pos can not be
211
+   %  seeked in bit and can not be calculated the way below.
212
+   %
213
+   if filetype == 0 | hdr.dime.datatype == 1 | isequal(hdr.dime.dim(5:8),ones(1,4)) | ...
214
+	(isempty(img_idx) & isempty(dim5_idx) & isempty(dim6_idx) & isempty(dim7_idx))
215
+
216
+      %  For each frame, precision of value will be read 
217
+      %  in img_siz times, where img_siz is only the 
218
+      %  dimension size of an image, not the byte storage
219
+      %  size of an image.
220
+      %
221
+      img_siz = prod(hdr.dime.dim(2:8));
222
+
223
+      %  For complex float32 or complex float64, voxel values
224
+      %  include [real, imag]
225
+      %
226
+      if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
227
+         img_siz = img_siz * 2;
228
+      end
229
+	 
230
+      %MPH: For RGB24, voxel values include 3 separate color planes
231
+      %
232
+      if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
233
+	 img_siz = img_siz * 3;
234
+      end
235
+
236
+      img = fread(fid, img_siz, sprintf('*%s',precision));
237
+
238
+      d1 = hdr.dime.dim(2);
239
+      d2 = hdr.dime.dim(3);
240
+      d3 = hdr.dime.dim(4);
241
+      d4 = hdr.dime.dim(5);
242
+      d5 = hdr.dime.dim(6);
243
+      d6 = hdr.dime.dim(7);
244
+      d7 = hdr.dime.dim(8);
245
+
246
+      if isempty(img_idx)
247
+         img_idx = 1:d4;
248
+      end
249
+
250
+      if isempty(dim5_idx)
251
+         dim5_idx = 1:d5;
252
+      end
253
+
254
+      if isempty(dim6_idx)
255
+         dim6_idx = 1:d6;
256
+      end
257
+
258
+      if isempty(dim7_idx)
259
+         dim7_idx = 1:d7;
260
+      end
261
+   else
262
+
263
+      img = [];
264
+
265
+      %  For each frame, precision of value will be read 
266
+      %  in img_siz times, where img_siz is only the 
267
+      %  dimension size of an image, not the byte storage
268
+      %  size of an image.
269
+      %
270
+      img_siz = prod(hdr.dime.dim(2:4));
271
+
272
+      d1 = hdr.dime.dim(2);
273
+      d2 = hdr.dime.dim(3);
274
+      d3 = hdr.dime.dim(4);
275
+      d4 = hdr.dime.dim(5);
276
+      d5 = hdr.dime.dim(6);
277
+      d6 = hdr.dime.dim(7);
278
+      d7 = hdr.dime.dim(8);
279
+
280
+      if isempty(img_idx)
281
+         img_idx = 1:d4;
282
+      end
283
+
284
+      if isempty(dim5_idx)
285
+         dim5_idx = 1:d5;
286
+      end
287
+
288
+      if isempty(dim6_idx)
289
+         dim6_idx = 1:d6;
290
+      end
291
+
292
+      if isempty(dim7_idx)
293
+         dim7_idx = 1:d7;
294
+      end
295
+
296
+      for i7=1:length(dim7_idx)
297
+         for i6=1:length(dim6_idx)
298
+            for i5=1:length(dim5_idx)
299
+               for t=1:length(img_idx)
300
+
301
+                  %  Position is seeked in bytes. To convert dimension size
302
+                  %  to byte storage size, hdr.dime.bitpix/8 will be
303
+                  %  applied.
304
+                  %
305
+                  pos = sub2ind([d1 d2 d3 d4 d5 d6 d7], 1, 1, 1, ...
306
+			img_idx(t), dim5_idx(i5),dim6_idx(i6),dim7_idx(i7)) -1;
307
+                  pos = pos * hdr.dime.bitpix/8;
308
+
309
+                  %  For complex float32 or complex float64, voxel values
310
+                  %  include [real, imag]
311
+                  %
312
+                  if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
313
+                     img_siz = img_siz * 2;
314
+                  end
315
+
316
+                  %MPH: For RGB24, voxel values include 3 separate color planes
317
+                  %
318
+                  if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
319
+	             img_siz = img_siz * 3;
320
+                  end
321
+         
322
+                  if filetype == 2
323
+                     fseek(fid, pos + hdr.dime.vox_offset, 'bof');
324
+                  else
325
+                     fseek(fid, pos, 'bof');
326
+                  end
327
+
328
+                  %  For each frame, fread will read precision of value
329
+                  %  in img_siz times
330
+                  %
331
+                  img = [img fread(fid, img_siz, sprintf('*%s',precision))];
332
+               end
333
+            end
334
+         end
335
+      end
336
+   end
337
+
338
+   %  For complex float32 or complex float64, voxel values
339
+   %  include [real, imag]
340
+   %
341
+   if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
342
+      img = reshape(img, [2, length(img)/2]);
343
+      img = complex(img(1,:)', img(2,:)');
344
+   end
345
+
346
+   fclose(fid);
347
+
348
+   %  Update the global min and max values 
349
+   %
350
+   hdr.dime.glmax = max(double(img(:)));
351
+   hdr.dime.glmin = min(double(img(:)));
352
+
353
+   if old_RGB & hdr.dime.datatype == 128 & hdr.dime.bitpix == 24
354
+      img = squeeze(reshape(img, [hdr.dime.dim(2:3) 3 hdr.dime.dim(4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
355
+      img = permute(img, [1 2 4 3 5 6 7 8]);
356
+   elseif hdr.dime.datatype == 128 & hdr.dime.bitpix == 24
357
+      img = squeeze(reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
358
+      img = permute(img, [2 3 4 1 5 6 7 8]);
359
+   elseif hdr.dime.datatype == 511 & hdr.dime.bitpix == 96
360
+      img = double(img);
361
+      img = (img - min(img))/(max(img) - min(img));
362
+      img = squeeze(reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
363
+      img = permute(img, [2 3 4 1 5 6 7 8]);
364
+   else
365
+      img = squeeze(reshape(img, [hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
366
+   end
367
+
368
+   if ~isempty(img_idx)
369
+      hdr.dime.dim(5) = length(img_idx);
370
+   end
371
+
372
+   if ~isempty(dim5_idx)
373
+      hdr.dime.dim(6) = length(dim5_idx);
374
+   end
375
+
376
+   if ~isempty(dim6_idx)
377
+      hdr.dime.dim(7) = length(dim6_idx);
378
+   end
379
+
380
+   if ~isempty(dim7_idx)
381
+      hdr.dime.dim(8) = length(dim7_idx);
382
+   end
383
+
384
+   return						% read_image
385
+
... ...
@@ -0,0 +1,200 @@
1
+%  internal function
2
+
3
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
4
+
5
+function hdr = load_nii_hdr(fileprefix, machine)
6
+
7
+   fn = sprintf('%s.hdr',fileprefix);
8
+   fid = fopen(fn,'r',machine);
9
+    
10
+   if fid < 0,
11
+      msg = sprintf('Cannot open file %s.',fn);
12
+      error(msg);
13
+   else
14
+      fseek(fid,0,'bof');
15
+      hdr = read_header(fid);
16
+      fclose(fid);
17
+   end
18
+
19
+   return					% load_nii_hdr
20
+
21
+
22
+%---------------------------------------------------------------------
23
+function [ dsr ] = read_header(fid)
24
+
25
+        %  Original header structures
26
+	%  struct dsr
27
+	%       { 
28
+	%       struct header_key hk;            /*   0 +  40       */
29
+	%       struct image_dimension dime;     /*  40 + 108       */
30
+	%       struct data_history hist;        /* 148 + 200       */
31
+	%       };                               /* total= 348 bytes*/
32
+
33
+    dsr.hk   = header_key(fid);
34
+    dsr.dime = image_dimension(fid);
35
+    dsr.hist = data_history(fid);
36
+
37
+    return					% read_header
38
+
39
+
40
+%---------------------------------------------------------------------
41
+function [ hk ] = header_key(fid)
42
+
43
+    fseek(fid,0,'bof');
44
+    
45
+	%  Original header structures	
46
+	%  struct header_key                     /* header key      */ 
47
+	%       {                                /* off + size      */
48
+	%       int sizeof_hdr                   /*  0 +  4         */
49
+	%       char data_type[10];              /*  4 + 10         */
50
+	%       char db_name[18];                /* 14 + 18         */
51
+	%       int extents;                     /* 32 +  4         */
52
+	%       short int session_error;         /* 36 +  2         */
53
+	%       char regular;                    /* 38 +  1         */
54
+	%       char hkey_un0;                   /* 39 +  1 */
55
+	%       };                               /* total=40 bytes  */
56
+	%
57
+	% int sizeof_header   Should be 348.
58
+	% char regular        Must be 'r' to indicate that all images and 
59
+	%                     volumes are the same size. 
60
+
61
+    v6 = version;
62
+    if str2num(v6(1))<6
63
+       directchar = '*char';
64
+    else
65
+       directchar = 'uchar=>char';
66
+    end
67
+	
68
+    hk.sizeof_hdr    = fread(fid, 1,'int32')';	% should be 348!
69
+    hk.data_type     = deblank(fread(fid,10,directchar)');
70
+    hk.db_name       = deblank(fread(fid,18,directchar)');
71
+    hk.extents       = fread(fid, 1,'int32')';
72
+    hk.session_error = fread(fid, 1,'int16')';
73
+    hk.regular       = fread(fid, 1,directchar)';
74
+    hk.hkey_un0      = fread(fid, 1,directchar)';
75
+    
76
+    return					% header_key
77
+
78
+
79
+%---------------------------------------------------------------------
80
+function [ dime ] = image_dimension(fid)
81
+
82
+	%struct image_dimension
83
+	%       {                                /* off + size      */
84
+	%       short int dim[8];                /* 0 + 16          */
85
+    %           /*
86
+    %           dim[0]      Number of dimensions in database; usually 4. 
87
+    %           dim[1]      Image X dimension;  number of *pixels* in an image row. 
88
+    %           dim[2]      Image Y dimension;  number of *pixel rows* in slice. 
89
+    %           dim[3]      Volume Z dimension; number of *slices* in a volume. 
90
+    %           dim[4]      Time points; number of volumes in database
91
+    %           */
92
+	%       char vox_units[4];               /* 16 + 4          */
93
+	%       char cal_units[8];               /* 20 + 8          */
94
+	%       short int unused1;               /* 28 + 2          */
95
+	%       short int datatype;              /* 30 + 2          */
96
+	%       short int bitpix;                /* 32 + 2          */
97
+	%       short int dim_un0;               /* 34 + 2          */
98
+	%       float pixdim[8];                 /* 36 + 32         */
99
+	%			/*
100
+	%				pixdim[] specifies the voxel dimensions:
101
+	%				pixdim[1] - voxel width, mm
102
+	%				pixdim[2] - voxel height, mm
103
+	%				pixdim[3] - slice thickness, mm
104
+    %               pixdim[4] - volume timing, in msec
105
+	%					..etc
106
+	%			*/
107
+	%       float vox_offset;                /* 68 + 4          */
108
+	%       float roi_scale;                 /* 72 + 4          */
109
+	%       float funused1;                  /* 76 + 4          */
110
+	%       float funused2;                  /* 80 + 4          */
111
+	%       float cal_max;                   /* 84 + 4          */
112
+	%       float cal_min;                   /* 88 + 4          */
113
+	%       int compressed;                  /* 92 + 4          */
114
+	%       int verified;                    /* 96 + 4          */
115
+	%       int glmax;                       /* 100 + 4         */
116
+	%       int glmin;                       /* 104 + 4         */
117
+	%       };                               /* total=108 bytes */
118
+
119
+    v6 = version;
120
+    if str2num(v6(1))<6
121
+       directchar = '*char';
122
+    else
123
+       directchar = 'uchar=>char';
124
+    end
125
+	
126
+    dime.dim        = fread(fid,8,'int16')';
127
+    dime.vox_units  = deblank(fread(fid,4,directchar)');
128
+    dime.cal_units  = deblank(fread(fid,8,directchar)');
129
+    dime.unused1    = fread(fid,1,'int16')';
130
+    dime.datatype   = fread(fid,1,'int16')';
131
+    dime.bitpix     = fread(fid,1,'int16')';
132
+    dime.dim_un0    = fread(fid,1,'int16')';
133
+    dime.pixdim     = fread(fid,8,'float32')';
134
+    dime.vox_offset = fread(fid,1,'float32')';
135
+    dime.roi_scale  = fread(fid,1,'float32')';
136
+    dime.funused1   = fread(fid,1,'float32')';
137
+    dime.funused2   = fread(fid,1,'float32')';
138
+    dime.cal_max    = fread(fid,1,'float32')';
139
+    dime.cal_min    = fread(fid,1,'float32')';
140
+    dime.compressed = fread(fid,1,'int32')';
141
+    dime.verified   = fread(fid,1,'int32')';
142
+    dime.glmax      = fread(fid,1,'int32')';
143
+    dime.glmin      = fread(fid,1,'int32')';
144
+        
145
+    return					% image_dimension
146
+
147
+
148
+%---------------------------------------------------------------------
149
+function [ hist ] = data_history(fid)
150
+        
151
+	%struct data_history       
152
+	%       {                                /* off + size      */
153
+	%       char descrip[80];                /* 0 + 80          */
154
+	%       char aux_file[24];               /* 80 + 24         */
155
+	%       char orient;                     /* 104 + 1         */
156
+	%       char originator[10];             /* 105 + 10        */
157
+	%       char generated[10];              /* 115 + 10        */
158
+	%       char scannum[10];                /* 125 + 10        */
159
+	%       char patient_id[10];             /* 135 + 10        */
160
+	%       char exp_date[10];               /* 145 + 10        */
161
+	%       char exp_time[10];               /* 155 + 10        */
162
+	%       char hist_un0[3];                /* 165 + 3         */
163
+	%       int views                        /* 168 + 4         */
164
+	%       int vols_added;                  /* 172 + 4         */
165
+	%       int start_field;                 /* 176 + 4         */
166
+	%       int field_skip;                  /* 180 + 4         */
167
+	%       int omax;                        /* 184 + 4         */
168
+	%       int omin;                        /* 188 + 4         */
169
+	%       int smax;                        /* 192 + 4         */
170
+	%       int smin;                        /* 196 + 4         */
171
+	%       };                               /* total=200 bytes */
172
+
173
+    v6 = version;
174
+    if str2num(v6(1))<6
175
+       directchar = '*char';
176
+    else
177
+       directchar = 'uchar=>char';
178
+    end
179
+
180
+    hist.descrip     = deblank(fread(fid,80,directchar)');
181
+    hist.aux_file    = deblank(fread(fid,24,directchar)');
182
+    hist.orient      = fread(fid, 1,'char')';
183
+    hist.originator  = fread(fid, 5,'int16')';
184
+    hist.generated   = deblank(fread(fid,10,directchar)');
185
+    hist.scannum     = deblank(fread(fid,10,directchar)');
186
+    hist.patient_id  = deblank(fread(fid,10,directchar)');
187
+    hist.exp_date    = deblank(fread(fid,10,directchar)');
188
+    hist.exp_time    = deblank(fread(fid,10,directchar)');
189
+    hist.hist_un0    = deblank(fread(fid, 3,directchar)');
190
+    hist.views       = fread(fid, 1,'int32')';
191
+    hist.vols_added  = fread(fid, 1,'int32')';
192
+    hist.start_field = fread(fid, 1,'int32')';
193
+    hist.field_skip  = fread(fid, 1,'int32')';
194
+    hist.omax        = fread(fid, 1,'int32')';
195
+    hist.omin        = fread(fid, 1,'int32')';
196
+    hist.smax        = fread(fid, 1,'int32')';
197
+    hist.smin        = fread(fid, 1,'int32')';
198
+    
199
+    return					% data_history
200
+
... ...
@@ -0,0 +1,106 @@
1
+%  Load NIFTI or ANALYZE dataset, but not applying any appropriate affine
2
+%  geometric transform or voxel intensity scaling.
3
+%
4
+%  Although according to NIFTI website, all those header information are
5
+%  supposed to be applied to the loaded NIFTI image, there are some
6
+%  situations that people do want to leave the original NIFTI header and
7
+%  data untouched. They will probably just use MATLAB to do certain image
8
+%  processing regardless of image orientation, and to save data back with
9
+%  the same NIfTI header.
10
+%
11
+%  Since this program is only served for those situations, please use it
12
+%  together with "save_untouch_nii.m", and do not use "save_nii.m" or
13
+%  "view_nii.m" for the data that is loaded by "load_untouch_nii.m". For
14
+%  normal situation, you should use "load_nii.m" instead.
15
+%  
16
+%  Usage: nii = load_untouch_nii(filename, [img_idx], [dim5_idx], [dim6_idx], [dim7_idx])
17
+%  
18
+%  filename  - 	NIFTI or ANALYZE file name.
19
+%  
20
+%  img_idx (optional)  -  a numerical array of image volume indices.
21
+%	Only the specified volumes will be loaded. All available image
22
+%	volumes will be loaded, if it is default or empty.
23
+%
24
+%	The number of images scans can be obtained from get_nii_frame.m,
25
+%	or simply: hdr.dime.dim(5).
26
+%
27
+%  dim5_idx (optional)  -  a numerical array of 5th dimension indices.
28
+%	Only the specified range will be loaded. All available range
29
+%	will be loaded, if it is default or empty.
30
+%
31
+%  dim6_idx (optional)  -  a numerical array of 6th dimension indices.
32
+%	Only the specified range will be loaded. All available range
33
+%	will be loaded, if it is default or empty.
34
+%
35
+%  dim7_idx (optional)  -  a numerical array of 7th dimension indices.
36
+%	Only the specified range will be loaded. All available range
37
+%	will be loaded, if it is default or empty.
38
+%
39
+%  Returned values:
40
+%  
41
+%  nii structure:
42
+%
43
+%	hdr -		struct with NIFTI header fields.
44
+%
45
+%	filetype -	Analyze format .hdr/.img (0); 
46
+%			NIFTI .hdr/.img (1);
47
+%			NIFTI .nii (2)
48
+%
49
+%	fileprefix - 	NIFTI filename without extension.
50
+%
51
+%	machine - 	machine string variable.
52
+%
53
+%	img - 		3D (or 4D) matrix of NIFTI data.
54
+%
55
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
56
+%
57
+function nii = load_untouch_nii(filename, img_idx, dim5_idx, dim6_idx, dim7_idx)
58
+
59
+   if ~exist('filename','var')
60
+      error('Usage: nii = load_untouch_nii(filename, [img_idx], [dim5_idx], [dim6_idx], [dim7_idx])');
61
+   end
62
+
63
+   if ~exist('img_idx','var') | isempty(img_idx)
64
+      img_idx = [];
65
+   end
66
+
67
+   if ~exist('dim5_idx','var') | isempty(dim5_idx)
68
+      dim5_idx = [];
69
+   end
70
+
71
+   if ~exist('dim6_idx','var') | isempty(dim6_idx)
72
+      dim6_idx = [];
73
+   end
74
+
75
+   if ~exist('dim7_idx','var') | isempty(dim7_idx)
76
+      dim7_idx = [];
77
+   end
78
+
79
+   %  Read the dataset header
80
+   %
81
+   [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename);
82
+
83
+   if nii.filetype == 0
84
+      nii.hdr = load_untouch0_nii_hdr(nii.fileprefix,nii.machine);
85
+      nii.ext = [];
86
+   else
87
+      nii.hdr = load_untouch_nii_hdr(nii.fileprefix,nii.machine,nii.filetype);
88
+
89
+      %  Read the header extension
90
+      %
91
+      nii.ext = load_nii_ext(filename);
92
+   end
93
+
94
+   %  Read the dataset body
95
+   %
96
+   [nii.img,nii.hdr] = load_nii_img(nii.hdr,nii.filetype,nii.fileprefix, ...
97
+		nii.machine,img_idx,dim5_idx,dim6_idx,dim7_idx);
98
+
99
+   %  Perform some of sform/qform transform
100
+   %
101
+%   nii = xform_nii(nii, tolerance, preferredForm);
102
+
103
+   nii.untouch = 1;
104
+
105
+   return					% load_untouch_nii
106
+
... ...
@@ -0,0 +1,217 @@
1
+%  internal function
2
+
3
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
4
+
5
+function hdr = load_nii_hdr(fileprefix, machine, filetype)
6
+
7
+   if filetype == 2
8
+      fn = sprintf('%s.nii',fileprefix);
9
+
10
+      if ~exist(fn)
11
+         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
12
+         error(msg);
13
+      end
14
+   else
15
+      fn = sprintf('%s.hdr',fileprefix);
16
+
17
+      if ~exist(fn)
18
+         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
19
+         error(msg);
20
+      end
21
+   end
22
+
23
+   fid = fopen(fn,'r',machine);
24
+    
25
+   if fid < 0,
26
+      msg = sprintf('Cannot open file %s.',fn);
27
+      error(msg);
28
+   else
29
+      fseek(fid,0,'bof');
30
+      hdr = read_header(fid);
31
+      fclose(fid);
32
+   end
33
+
34
+   return					% load_nii_hdr
35
+
36
+
37
+%---------------------------------------------------------------------
38
+function [ dsr ] = read_header(fid)
39
+
40
+        %  Original header structures
41
+	%  struct dsr
42
+	%       { 
43
+	%       struct header_key hk;            /*   0 +  40       */
44
+	%       struct image_dimension dime;     /*  40 + 108       */
45
+	%       struct data_history hist;        /* 148 + 200       */
46
+	%       };                               /* total= 348 bytes*/
47
+
48
+    dsr.hk   = header_key(fid);
49
+    dsr.dime = image_dimension(fid);
50
+    dsr.hist = data_history(fid);
51
+
52
+    %  For Analyze data format
53
+    %
54
+    if ~strcmp(dsr.hist.magic, 'n+1') & ~strcmp(dsr.hist.magic, 'ni1')
55
+        dsr.hist.qform_code = 0;
56
+        dsr.hist.sform_code = 0;
57
+    end
58
+
59
+    return					% read_header
60
+
61
+
62
+%---------------------------------------------------------------------
63
+function [ hk ] = header_key(fid)
64
+
65
+    fseek(fid,0,'bof');
66
+    
67
+	%  Original header structures	
68
+	%  struct header_key                     /* header key      */ 
69
+	%       {                                /* off + size      */
70
+	%       int sizeof_hdr                   /*  0 +  4         */
71
+	%       char data_type[10];              /*  4 + 10         */
72
+	%       char db_name[18];                /* 14 + 18         */
73
+	%       int extents;                     /* 32 +  4         */
74
+	%       short int session_error;         /* 36 +  2         */
75
+	%       char regular;                    /* 38 +  1         */
76
+	%       char dim_info;   % char hkey_un0;        /* 39 +  1 */
77
+	%       };                               /* total=40 bytes  */
78
+	%
79
+	% int sizeof_header   Should be 348.
80
+	% char regular        Must be 'r' to indicate that all images and 
81
+	%                     volumes are the same size. 
82
+
83
+    v6 = version;
84
+    if str2num(v6(1))<6
85
+       directchar = '*char';
86
+    else
87
+       directchar = 'uchar=>char';
88
+    end
89
+	
90
+    hk.sizeof_hdr    = fread(fid, 1,'int32')';	% should be 348!
91
+    hk.data_type     = deblank(fread(fid,10,directchar)');
92
+    hk.db_name       = deblank(fread(fid,18,directchar)');
93
+    hk.extents       = fread(fid, 1,'int32')';
94
+    hk.session_error = fread(fid, 1,'int16')';
95
+    hk.regular       = fread(fid, 1,directchar)';
96
+    hk.dim_info      = fread(fid, 1,'uchar')';
97
+    
98
+    return					% header_key
99
+
100
+
101
+%---------------------------------------------------------------------
102
+function [ dime ] = image_dimension(fid)
103
+
104
+	%  Original header structures    
105
+	%  struct image_dimension
106
+	%       {                                /* off + size      */
107
+	%       short int dim[8];                /* 0 + 16          */
108
+        %       /*
109
+        %           dim[0]      Number of dimensions in database; usually 4. 
110
+        %           dim[1]      Image X dimension;  number of *pixels* in an image row. 
111
+        %           dim[2]      Image Y dimension;  number of *pixel rows* in slice. 
112
+        %           dim[3]      Volume Z dimension; number of *slices* in a volume. 
113
+        %           dim[4]      Time points; number of volumes in database
114
+        %       */
115
+	%       float intent_p1;   % char vox_units[4];   /* 16 + 4       */
116
+	%       float intent_p2;   % char cal_units[8];   /* 20 + 4       */
117
+	%       float intent_p3;   % char cal_units[8];   /* 24 + 4       */
118
+	%       short int intent_code;   % short int unused1;   /* 28 + 2 */
119
+	%       short int datatype;              /* 30 + 2          */
120
+	%       short int bitpix;                /* 32 + 2          */
121
+	%       short int slice_start;   % short int dim_un0;   /* 34 + 2 */
122
+	%       float pixdim[8];                 /* 36 + 32         */
123
+	%	/*
124
+	%		pixdim[] specifies the voxel dimensions:
125
+	%		pixdim[1] - voxel width, mm
126
+	%		pixdim[2] - voxel height, mm
127
+	%		pixdim[3] - slice thickness, mm
128
+	%		pixdim[4] - volume timing, in msec
129
+	%					..etc
130
+	%	*/
131
+	%       float vox_offset;                /* 68 + 4          */
132
+	%       float scl_slope;   % float roi_scale;     /* 72 + 4 */
133
+	%       float scl_inter;   % float funused1;      /* 76 + 4 */
134
+	%       short slice_end;   % float funused2;      /* 80 + 2 */
135
+	%       char slice_code;   % float funused2;      /* 82 + 1 */
136
+	%       char xyzt_units;   % float funused2;      /* 83 + 1 */
137
+	%       float cal_max;                   /* 84 + 4          */
138
+	%       float cal_min;                   /* 88 + 4          */
139
+	%       float slice_duration;   % int compressed; /* 92 + 4 */
140
+	%       float toffset;   % int verified;          /* 96 + 4 */
141
+	%       int glmax;                       /* 100 + 4         */
142
+	%       int glmin;                       /* 104 + 4         */
143
+	%       };                               /* total=108 bytes */
144
+	
145
+    dime.dim        = fread(fid,8,'int16')';
146
+    dime.intent_p1  = fread(fid,1,'float32')';
147
+    dime.intent_p2  = fread(fid,1,'float32')';
148
+    dime.intent_p3  = fread(fid,1,'float32')';
149
+    dime.intent_code = fread(fid,1,'int16')';
150
+    dime.datatype   = fread(fid,1,'int16')';
151
+    dime.bitpix     = fread(fid,1,'int16')';
152
+    dime.slice_start = fread(fid,1,'int16')';
153
+    dime.pixdim     = fread(fid,8,'float32')';
154
+    dime.vox_offset = fread(fid,1,'float32')';
155
+    dime.scl_slope  = fread(fid,1,'float32')';
156
+    dime.scl_inter  = fread(fid,1,'float32')';
157
+    dime.slice_end  = fread(fid,1,'int16')';
158
+    dime.slice_code = fread(fid,1,'uchar')';
159
+    dime.xyzt_units = fread(fid,1,'uchar')';
160
+    dime.cal_max    = fread(fid,1,'float32')';
161
+    dime.cal_min    = fread(fid,1,'float32')';
162
+    dime.slice_duration = fread(fid,1,'float32')';
163
+    dime.toffset    = fread(fid,1,'float32')';
164
+    dime.glmax      = fread(fid,1,'int32')';
165
+    dime.glmin      = fread(fid,1,'int32')';
166
+        
167
+    return					% image_dimension
168
+
169
+
170
+%---------------------------------------------------------------------
171
+function [ hist ] = data_history(fid)
172
+        
173
+	%  Original header structures
174
+	%  struct data_history       
175
+	%       {                                /* off + size      */
176
+	%       char descrip[80];                /* 0 + 80          */
177
+	%       char aux_file[24];               /* 80 + 24         */
178
+	%       short int qform_code;            /* 104 + 2         */
179
+	%       short int sform_code;            /* 106 + 2         */
180
+	%       float quatern_b;                 /* 108 + 4         */
181
+	%       float quatern_c;                 /* 112 + 4         */
182
+	%       float quatern_d;                 /* 116 + 4         */
183
+	%       float qoffset_x;                 /* 120 + 4         */
184
+	%       float qoffset_y;                 /* 124 + 4         */
185
+	%       float qoffset_z;                 /* 128 + 4         */
186
+	%       float srow_x[4];                 /* 132 + 16        */
187
+	%       float srow_y[4];                 /* 148 + 16        */
188
+	%       float srow_z[4];                 /* 164 + 16        */
189
+	%       char intent_name[16];            /* 180 + 16        */
190
+	%       char magic[4];   % int smin;     /* 196 + 4         */
191
+	%       };                               /* total=200 bytes */
192
+
193
+    v6 = version;
194
+    if str2num(v6(1))<6
195
+       directchar = '*char';
196
+    else
197
+       directchar = 'uchar=>char';
198
+    end
199
+    
200
+    hist.descrip     = deblank(fread(fid,80,directchar)');
201
+    hist.aux_file    = deblank(fread(fid,24,directchar)');
202
+    hist.qform_code  = fread(fid,1,'int16')';
203
+    hist.sform_code  = fread(fid,1,'int16')';
204
+    hist.quatern_b   = fread(fid,1,'float32')';
205
+    hist.quatern_c   = fread(fid,1,'float32')';
206
+    hist.quatern_d   = fread(fid,1,'float32')';
207
+    hist.qoffset_x   = fread(fid,1,'float32')';
208
+    hist.qoffset_y   = fread(fid,1,'float32')';
209
+    hist.qoffset_z   = fread(fid,1,'float32')';
210
+    hist.srow_x      = fread(fid,4,'float32')';
211
+    hist.srow_y      = fread(fid,4,'float32')';
212
+    hist.srow_z      = fread(fid,4,'float32')';
213
+    hist.intent_name = deblank(fread(fid,16,directchar)');
214
+    hist.magic       = deblank(fread(fid,4,directchar)');
215
+    
216
+    return					% data_history
217
+
... ...
@@ -0,0 +1,240 @@
1
+%  Make nii structure specified by an N-D matrix. Usually, N is 3 for
2
+%  3D matrix [x y z], or 4 for 4D matrix with time series [x y z t]. 
3
+%  However, NIfTI allows a maximum of 7D matrix. For RGB24 datatype, an
4
+%  extra dimension for RGB should be inserted immediately after [x y z].
5
+%  Optional parameters can also be included, such as: voxel_size, 
6
+%  origin, datatype, and description.
7
+%  
8
+%  Usage: nii = make_nii(img, [voxel_size], [origin], [datatype], ...
9
+%		[description])
10
+%
11
+%  Where:
12
+%
13
+%	img:		Usually, img is a 3D matrix [x y z], or a 4D
14
+%			matrix with time series [x y z t]. However,
15
+%			NIfTI allows a maximum of 7D matrix. For RGB
16
+%			datatype, an extra dimension for RGB should
17
+%			be inserted immediately after [x y z].
18
+%
19
+%	voxel_size (optional):	Voxel size in millimeter for each
20
+%				dimension. Default is [1 1 1].
21
+%
22
+%	origin (optional):	The AC origin. Default is [0 0 0].
23
+%
24
+%	datatype (optional):	Storage data type:
25
+%		2 - uint8,  4 - int16,  8 - int32,  16 - float32,
26
+%		32 - complex64,  64 - float64,  128 - RGB24,
27
+%		256 - int8,  512 - uint16,  768 - uint32, 
28
+%		1792 - complex128
29
+%			Default will use the data type of 'img' matrix
30
+%
31
+%	description (optional):	Description of data. Default is ''.
32
+%
33
+%  e.g.:
34
+%     origin = [33 44 13]; datatype = 64;
35
+%     nii = make_nii(img, [], origin, datatype);    % default voxel_size
36
+%
37
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
38
+%
39
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
40
+%
41
+function nii = make_nii(varargin)
42
+
43
+   nii.img = varargin{1};
44
+   dims = size(nii.img);
45
+   dims = [length(dims) dims ones(1,8)];
46
+   dims = dims(1:8);
47
+
48
+   voxel_size = [0 ones(1,7)];
49
+   origin = zeros(1,5);
50
+   descrip = '';
51
+
52
+   switch class(nii.img)
53
+      case 'uint8'
54
+         datatype = 2;
55
+      case 'int16'
56
+         datatype = 4;
57
+      case 'int32'
58
+         datatype = 8;
59
+      case 'single'
60
+         datatype = 16;
61
+      case 'double'
62
+         datatype = 64;
63
+      case 'int8'
64
+         datatype = 256;
65
+      case 'uint16'
66
+         datatype = 512;
67
+      case 'uint32'
68
+         datatype = 768;
69
+      otherwise
70
+         error('Datatype is not supported by make_nii.');
71
+   end
72
+
73
+   if nargin > 1 & ~isempty(varargin{2})
74
+      voxel_size(2:4) = double(varargin{2});
75
+   end
76
+
77
+   if nargin > 2 & ~isempty(varargin{3})
78
+      origin(1:3) = double(varargin{3});
79
+   end
80
+
81
+   if nargin > 3 & ~isempty(varargin{4})
82
+      datatype = double(varargin{4});
83
+   end
84
+
85
+   if nargin > 4 & ~isempty(varargin{5})
86
+      descrip = varargin{5};
87
+   end
88
+
89
+   if datatype == 128
90
+      if ndims(nii.img) > 8
91
+         error('NIfTI only allows a maximum of 7 Dimension matrix.');
92
+      end
93
+
94
+     dims(1) = dims(1)-1;
95
+     dims(5:8) = [dims(6:8) 1];
96
+
97
+   else
98
+      if ndims(nii.img) > 7
99
+         error('NIfTI only allows a maximum of 7 Dimension matrix.');
100
+      end
101
+   end
102
+
103
+   maxval = round(double(max(nii.img(:))));
104
+   minval = round(double(min(nii.img(:))));
105
+
106
+   nii.hdr = make_header(dims, voxel_size, origin, datatype, ...
107
+	descrip, maxval, minval);
108
+
109
+   switch nii.hdr.dime.datatype
110
+   case 2
111
+      nii.img = uint8(nii.img);
112
+   case 4
113
+      nii.img = int16(nii.img);
114
+   case 8
115
+      nii.img = int32(nii.img);
116
+   case 16
117
+      nii.img = single(nii.img);
118
+   case 32
119
+      nii.img = single(nii.img);
120
+   case 64
121
+      nii.img = double(nii.img);
122
+   case 128
123
+      nii.img = uint8(nii.img);
124
+   case 256
125
+      nii.img = int8(nii.img);
126
+   case 512
127
+      nii.img = uint16(nii.img);
128
+   case 768
129
+      nii.img = uint32(nii.img);
130
+   case 1792
131
+      nii.img = double(nii.img);
132
+   otherwise
133
+      error('Datatype is not supported by make_nii.');
134
+   end
135
+
136
+   return;					% make_nii
137
+
138
+
139
+%---------------------------------------------------------------------
140
+function hdr = make_header(dims, voxel_size, origin, datatype, ...
141
+	descrip, maxval, minval)
142
+
143
+   hdr.hk   = header_key;
144
+   hdr.dime = image_dimension(dims, voxel_size, datatype, maxval, minval);
145
+   hdr.hist = data_history(origin, descrip);
146
+    
147
+   return;					% make_header
148
+
149
+
150
+%---------------------------------------------------------------------
151
+function hk = header_key
152
+
153
+    hk.sizeof_hdr       = 348;			% must be 348!
154
+    hk.data_type        = '';
155
+    hk.db_name          = '';
156
+    hk.extents          = 0;
157
+    hk.session_error    = 0;
158
+    hk.regular          = 'r';
159
+    hk.dim_info         = 0;
160
+    
161
+    return;					% header_key
162
+
163
+
164
+%---------------------------------------------------------------------
165
+function dime = image_dimension(dims, voxel_size, datatype, maxval, minval)
166
+   
167
+   dime.dim = dims;
168
+   dime.intent_p1 = 0;
169
+   dime.intent_p2 = 0;
170
+   dime.intent_p3 = 0;
171
+   dime.intent_code = 0;
172
+   dime.datatype = datatype;
173
+   
174
+   switch dime.datatype
175
+   case   2,
176
+      dime.bitpix = 8;  precision = 'uint8';
177
+   case   4,
178
+      dime.bitpix = 16; precision = 'int16';
179
+   case   8,
180
+      dime.bitpix = 32; precision = 'int32';
181
+   case  16,
182
+      dime.bitpix = 32; precision = 'float32';
183
+   case  32,
184
+      dime.bitpix = 64; precision = 'float32';
185
+   case  64,
186
+      dime.bitpix = 64; precision = 'float64';
187
+   case  128,
188
+      dime.bitpix = 24; precision = 'uint8';
189
+   case 256 
190
+      dime.bitpix = 8;  precision = 'int8';
191
+   case 512 
192
+      dime.bitpix = 16; precision = 'uint16';
193
+   case 768 
194
+      dime.bitpix = 32; precision = 'uint32';
195
+   case  1792,
196
+      dime.bitpix = 128; precision = 'float64';
197
+   otherwise
198
+      error('Datatype is not supported by make_nii.');
199
+   end
200
+   
201
+   dime.slice_start = 0;
202
+   dime.pixdim = voxel_size;
203
+   dime.vox_offset = 0;
204
+   dime.scl_slope = 0;
205
+   dime.scl_inter = 0;
206
+   dime.slice_end = 0;
207
+   dime.slice_code = 0;
208
+   dime.xyzt_units = 0;
209
+   dime.cal_max = 0;
210
+   dime.cal_min = 0;
211
+   dime.slice_duration = 0;
212
+   dime.toffset = 0;
213
+   dime.glmax = maxval;
214
+   dime.glmin = minval;
215
+   
216
+   return;					% image_dimension
217
+
218
+
219
+%---------------------------------------------------------------------
220
+function hist = data_history(origin, descrip)
221
+   
222
+   hist.descrip = descrip;
223
+   hist.aux_file = 'none';
224
+   hist.qform_code = 0;
225
+   hist.sform_code = 0;
226
+   hist.quatern_b = 0;
227
+   hist.quatern_c = 0;
228
+   hist.quatern_d = 0;
229
+   hist.qoffset_x = 0;
230
+   hist.qoffset_y = 0;
231
+   hist.qoffset_z = 0;
232
+   hist.srow_x = zeros(1,4);
233
+   hist.srow_y = zeros(1,4);
234
+   hist.srow_z = zeros(1,4);
235
+   hist.intent_name = '';
236
+   hist.magic = '';
237
+   hist.originator = origin;
238
+   
239
+   return;					% data_history
240
+
... ...
@@ -0,0 +1,83 @@
1
+%MAT_INTO_HDR  The old versions of SPM (any version before SPM5) store
2
+%	an affine matrix of the SPM Reoriented image into a matlab file 
3
+%	(.mat extension). The file name of this SPM matlab file is the
4
+%	same as the SPM Reoriented image file (.img/.hdr extension).
5
+%
6
+%	This program will convert the ANALYZE 7.5 SPM Reoriented image
7
+%	file into NIfTI format, and integrate the affine matrix in the
8
+%	SPM matlab file into its header file (.hdr extension).
9
+%
10
+%	WARNING: Before you run this program, please save the header
11
+%	file (.hdr extension) into another file name or into another
12
+%	folder location, because all header files (.hdr extension)
13
+%	will be overwritten after they are converted into NIfTI
14
+%	format.
15
+%
16
+%  Usage: mat_into_hdr(filename);
17
+%
18
+%  filename:	file name(s) with .hdr or .mat file extension, like:
19
+%		'*.hdr', or '*.mat', or a single .hdr or .mat file.
20
+%	e.g.	mat_into_hdr('T1.hdr')
21
+%		mat_into_hdr('*.mat')
22
+%
23
+
24
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
25
+%
26
+%-------------------------------------------------------------------------
27
+function mat_into_hdr(files)
28
+
29
+   pn = fileparts(files);
30
+   file_lst = dir(files);
31
+   file_lst = {file_lst.name};
32
+   file1 = file_lst{1};
33
+   [p n e]= fileparts(file1);
34
+
35
+   for i=1:length(file_lst)
36
+      [p n e]= fileparts(file_lst{i});
37
+      disp(['working on file ', num2str(i) ,' of ', num2str(length(file_lst)), ': ', n,e]);
38
+      process=1;
39
+
40
+      if isequal(e,'.hdr')
41
+         mat=fullfile(pn, [n,'.mat']);
42
+         hdr=fullfile(pn, file_lst{i});
43
+
44
+         if ~exist(mat,'file')
45
+            warning(['Cannot find file "',mat  , '". File "', n, e, '" will not be processed.']);
46
+            process=0;
47
+         end
48
+      elseif isequal(e,'.mat')
49
+         hdr=fullfile(pn, [n,'.hdr']);
50
+         mat=fullfile(pn, file_lst{i});
51
+
52
+         if ~exist(hdr,'file')
53
+            warning(['Can not find file "',hdr  , '". File "', n, e, '" will not be processed.']);
54
+            process=0;
55
+         end
56
+      else
57
+         warning(['Input file must have .mat or .hdr extension. File "', n, e, '" will not be processed.']);
58
+         process=0;
59
+      end
60
+
61
+      if process
62
+         load(mat);
63
+         R=M(1:3,1:3);
64
+         T=M(1:3,4);
65
+         T=R*ones(3,1)+T;
66
+         M(1:3,4)=T;
67
+
68
+         [h filetype fileprefix machine]=load_nii_hdr(hdr);
69
+         h.hist.qform_code=0;
70
+         h.hist.sform_code=1;
71
+         h.hist.srow_x=M(1,:);
72
+         h.hist.srow_y=M(2,:);
73
+         h.hist.srow_z=M(3,:);
74
+         h.hist.magic='ni1';
75
+
76
+         fid = fopen(hdr,'w',machine);
77
+         save_nii_hdr(h,fid);
78
+         fclose(fid);
79
+      end
80
+   end
81
+
82
+   return;				% mat_into_hdr
83
+
... ...
@@ -0,0 +1,261 @@
1
+%  The basic application of the 'reslice_nii.m' program is to perform
2
+%  any 3D affine transform defined by a NIfTI format image.
3
+%
4
+%  In addition, the 'reslice_nii.m' program can also be applied to
5
+%  generate an isotropic image from either a NIfTI format image or
6
+%  an ANALYZE format image.
7
+%
8
+%  The resliced NIfTI file will always be in RAS orientation.
9
+%
10
+%  This program only supports real integer or floating-point data type.
11
+%  For other data type, the program will exit with an error message 
12
+%  "Transform of this NIFTI data is not supported by the program".
13
+%
14
+%  Usage: reslice_nii(old_fn, new_fn, [voxel_size], [verbose], [bg], ...
15
+%			[method], [img_idx], [preferredForm]);
16
+%
17
+%  old_fn  -	filename for original NIfTI file
18
+%
19
+%  new_fn  -	filename for resliced NIfTI file
20
+%
21
+%  voxel_size (optional)  - size of a voxel in millimeter along x y z
22
+%		direction for resliced NIfTI file. 'voxel_size' will use
23
+%		the rounded minimum voxel_size in original NIfTI header,
24
+%		if it is default or empty.
25
+%
26
+%  verbose (optional) - 1, 0
27
+%			1:  show transforming progress in percentage
28
+%			2:  progress will not be displayed
29
+%			'verbose' is 1 if it is default or empty.
30
+%
31
+%  bg (optional)  -	background voxel intensity in any extra corner that
32
+%			is caused by 3D interpolation. 0 in most cases. 'bg'
33
+%			will be the average of two corner voxel intensities
34
+%			in original image volume, if it is default or empty.
35
+%
36
+%  method (optional)  -	1, 2, or 3
37
+%			1:  for Trilinear interpolation
38
+%			2:  for Nearest Neighbor interpolation
39
+%			3:  for Fischer's Bresenham interpolation
40
+%			'method' is 1 if it is default or empty.
41
+%
42
+%  img_idx (optional)  -  a numerical array of image volume indices. Only
43
+%		the specified volumes will be loaded. All available image
44
+%		volumes will be loaded, if it is default or empty.
45
+%
46
+%	The number of images scans can be obtained from get_nii_frame.m,
47
+%	or simply: hdr.dime.dim(5).
48
+%
49
+%  preferredForm (optional)  -  selects which transformation from voxels
50
+%	to RAS coordinates; values are s,q,S,Q.  Lower case s,q indicate
51
+%	"prefer sform or qform, but use others if preferred not present". 
52
+%	Upper case indicate the program is forced to use the specificied
53
+%	tranform or fail loading.  'preferredForm' will be 's', if it is
54
+%	default or empty.	- Jeff Gunter
55
+%
56
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
57
+%  
58
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
59
+%
60
+function reslice_nii(old_fn, new_fn, voxel_size, verbose, bg, method, img_idx, preferredForm)
61
+
62
+   if ~exist('old_fn','var') | ~exist('new_fn','var')
63
+      error('Usage: reslice_nii(old_fn, new_fn, [voxel_size], [verbose], [bg], [method], [img_idx])');
64
+   end
65
+
66
+   if ~exist('method','var') | isempty(method)
67
+      method = 1;
68
+   end
69
+
70
+   if ~exist('img_idx','var') | isempty(img_idx)
71
+      img_idx = [];
72
+   end
73
+
74
+   if ~exist('verbose','var') | isempty(verbose)
75
+      verbose = 1;
76
+   end
77
+
78
+   if ~exist('preferredForm','var') | isempty(preferredForm)
79
+      preferredForm= 's';				% Jeff
80
+   end
81
+
82
+   nii = load_nii_no_xform(old_fn, img_idx, 0, preferredForm);
83
+
84
+   if ~ismember(nii.hdr.dime.datatype, [2,4,8,16,64,256,512,768])
85
+      error('Transform of this NIFTI data is not supported by the program.');
86
+   end
87
+
88
+   if ~exist('voxel_size','var') | isempty(voxel_size)
89
+      voxel_size = round(min(nii.hdr.dime.pixdim(2:4)))*ones(1,3);
90
+   elseif length(voxel_size) < 3
91
+      voxel_size = voxel_size(1)*ones(1,3);
92
+   end
93
+
94
+   if ~exist('bg','var') | isempty(bg)
95
+      bg = mean([nii.img(1) nii.img(end)]);
96
+   end
97
+
98
+   old_M = nii.hdr.hist.old_affine;
99
+
100
+   if nii.hdr.dime.dim(5) > 1
101
+      for i = 1:nii.hdr.dime.dim(5)
102
+         if verbose
103
+            fprintf('Reslicing %d of %d volumes.\n', i, nii.hdr.dime.dim(5));
104
+         end
105
+
106
+         [img(:,:,:,i) M] = ...
107
+		affine(nii.img(:,:,:,i), old_M, voxel_size, verbose, bg, method);
108
+      end
109
+   else
110
+      [img M] = affine(nii.img, old_M, voxel_size, verbose, bg, method);
111
+   end
112
+
113
+   new_dim = size(img);
114
+   nii.img = img;
115
+   nii.hdr.dime.dim(2:4) = new_dim(1:3);
116
+   nii.hdr.dime.datatype = 16;
117
+   nii.hdr.dime.bitpix = 32;
118
+   nii.hdr.dime.pixdim(2:4) = voxel_size(:)';
119
+   nii.hdr.dime.glmax = max(img(:));
120
+   nii.hdr.dime.glmin = min(img(:));
121
+   nii.hdr.hist.qform_code = 0;
122
+   nii.hdr.hist.sform_code = 1;
123
+   nii.hdr.hist.srow_x = M(1,:);
124
+   nii.hdr.hist.srow_y = M(2,:);
125
+   nii.hdr.hist.srow_z = M(3,:);
126
+   nii.hdr.hist.new_affine = M;
127
+
128
+   save_nii(nii, new_fn);
129
+
130
+   return;					% reslice_nii
131
+
132
+
133
+%--------------------------------------------------------------------
134
+function [nii] = load_nii_no_xform(filename, img_idx, old_RGB, preferredForm)
135
+
136
+   if ~exist('filename','var'),
137
+      error('Usage: [nii] = load_nii(filename, [img_idx], [old_RGB])');
138
+   end
139
+   
140
+   if ~exist('img_idx','var'), img_idx = []; end
141
+   if ~exist('old_RGB','var'), old_RGB = 0; end
142
+   if ~exist('preferredForm','var'), preferredForm= 's'; end     % Jeff
143
+   
144
+   %  Read the dataset header
145
+   %
146
+   [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename);
147
+
148
+   %  Read the header extension
149
+   %
150
+%   nii.ext = load_nii_ext(filename);
151
+   
152
+   %  Read the dataset body
153
+   %
154
+   [nii.img,nii.hdr] = ...
155
+        load_nii_img(nii.hdr,nii.filetype,nii.fileprefix,nii.machine,img_idx,'','','',old_RGB);
156
+   
157
+   %  Perform some of sform/qform transform
158
+   %
159
+%   nii = xform_nii(nii, preferredForm);
160
+
161
+
162
+   hdr = nii.hdr;
163
+
164
+   %  NIFTI can have both sform and qform transform. This program
165
+   %  will check sform_code prior to qform_code by default.
166
+   %
167
+   %  If user specifys "preferredForm", user can then choose the
168
+   %  priority.					- Jeff
169
+   %
170
+   useForm=[];					% Jeff
171
+
172
+   if isequal(preferredForm,'S')
173
+       if isequal(hdr.hist.sform_code,0)
174
+           error('User requires sform, sform not set in header');
175
+       else
176
+           useForm='s';
177
+       end
178
+   end						% Jeff
179
+
180
+   if isequal(preferredForm,'Q')
181
+       if isequal(hdr.hist.qform_code,0)
182
+           error('User requires sform, sform not set in header');
183
+       else
184
+           useForm='q';
185
+       end
186
+   end						% Jeff
187
+
188
+   if isequal(preferredForm,'s')
189
+       if hdr.hist.sform_code > 0
190
+           useForm='s';
191
+       elseif hdr.hist.qform_code > 0
192
+           useForm='q';
193
+       end
194
+   end						% Jeff
195
+   
196
+   if isequal(preferredForm,'q')
197
+       if hdr.hist.qform_code > 0
198
+           useForm='q';
199
+       elseif hdr.hist.sform_code > 0
200
+           useForm='s';
201
+       end
202
+   end						% Jeff
203
+
204
+   if isequal(useForm,'s')
205
+      R = [hdr.hist.srow_x(1:3)
206
+           hdr.hist.srow_y(1:3)
207
+           hdr.hist.srow_z(1:3)];
208
+
209
+      T = [hdr.hist.srow_x(4)
210
+           hdr.hist.srow_y(4)
211
+           hdr.hist.srow_z(4)];
212
+
213
+      nii.hdr.hist.old_affine = [ [R;[0 0 0]] [T;1] ];
214
+
215
+   elseif isequal(useForm,'q')
216
+      b = hdr.hist.quatern_b;
217
+      c = hdr.hist.quatern_c;
218
+      d = hdr.hist.quatern_d;
219
+
220
+      if 1.0-(b*b+c*c+d*d) < 0
221
+         if abs(1.0-(b*b+c*c+d*d)) < 1e-5
222
+            a = 0;
223
+         else
224
+            error('Incorrect quaternion values in this NIFTI data.');
225
+         end
226
+      else
227
+         a = sqrt(1.0-(b*b+c*c+d*d));
228
+      end
229
+
230
+      qfac = hdr.dime.pixdim(1);
231
+      i = hdr.dime.pixdim(2);
232
+      j = hdr.dime.pixdim(3);
233
+      k = qfac * hdr.dime.pixdim(4);
234
+
235
+      R = [a*a+b*b-c*c-d*d     2*b*c-2*a*d        2*b*d+2*a*c
236
+           2*b*c+2*a*d         a*a+c*c-b*b-d*d    2*c*d-2*a*b
237
+           2*b*d-2*a*c         2*c*d+2*a*b        a*a+d*d-c*c-b*b];
238
+
239
+      T = [hdr.hist.qoffset_x
240
+           hdr.hist.qoffset_y
241
+           hdr.hist.qoffset_z];
242
+
243
+      nii.hdr.hist.old_affine = [ [R * diag([i j k]);[0 0 0]] [T;1] ];
244
+
245
+   elseif nii.filetype == 0 & exist([nii.fileprefix '.mat'],'file')
246
+      load([nii.fileprefix '.mat']);	% old SPM affine matrix
247
+      R=M(1:3,1:3);
248
+      T=M(1:3,4);
249
+      T=R*ones(3,1)+T;
250
+      M(1:3,4)=T;
251
+      nii.hdr.hist.old_affine = M;
252
+
253
+   else
254
+      M = diag(hdr.dime.pixdim(2:5));
255
+      M(1:3,4) = -M(1:3,1:3)*(hdr.hist.originator(1:3)-1)';
256
+      M(4,4) = 1;
257
+      nii.hdr.hist.old_affine = M;
258
+   end
259
+
260
+   return					% load_nii_no_xform
261
+
... ...
@@ -0,0 +1,179 @@
1
+%  Imbed a file menu to any figure. If file menu exist, it will append
2
+%  to the existing file menu. This file menu includes: Copy to clipboard,
3
+%  print, save, close etc.
4
+%
5
+%  Usage: rri_file_menu(fig);
6
+%
7
+%         rri_file_menu(fig,0) means no 'Close' menu.
8
+%
9
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
10
+%
11
+%--------------------------------------------------------------------
12
+
13
+function rri_file_menu(action, varargin)
14
+
15
+   if isnumeric(action)
16
+      fig = action;
17
+      action = 'init';
18
+   end
19
+
20
+   %  clear the message line,
21
+   %
22
+   h = findobj(gcf,'Tag','MessageLine');
23
+   set(h,'String','');
24
+
25
+   if ~strcmp(action, 'init')
26
+      set(gcbf, 'InvertHardcopy','off');
27
+%      set(gcbf, 'PaperPositionMode','auto');
28
+   end
29
+
30
+   switch action
31
+      case {'init'}
32
+         if nargin > 1
33
+            init(fig, 1);		% no 'close' menu
34
+         else
35
+            init(fig, 0);
36
+         end
37
+      case {'print_fig'}
38
+         printdlg(gcbf);
39
+      case {'copy_fig'}
40
+         copy_fig;
41
+      case {'export_fig'}
42
+         export_fig;
43
+   end
44
+
45
+   return					% rri_file_menu
46
+
47
+
48
+%------------------------------------------------
49
+%
50
+%  Create (or append) File menu
51
+%
52
+function init(fig, no_close)
53
+
54
+   %  search for file menu
55
+   %
56
+   h_file = [];
57
+   menuitems = findobj(fig, 'type', 'uimenu');
58
+
59
+   for i=1:length(menuitems)
60
+      filelabel = get(menuitems(i),'label');
61
+
62
+      if strcmpi(strrep(filelabel, '&', ''), 'file')
63
+         h_file = menuitems(i);
64
+         break;
65
+      end
66
+   end
67
+
68
+   set(fig, 'menubar', 'none');
69
+
70
+   if isempty(h_file)
71
+      if isempty(menuitems)
72
+         h_file = uimenu('parent', fig, 'label', 'File');
73
+      else
74
+         h_file = uimenu('parent', fig, 'label', 'Copy Figure');
75
+      end
76
+
77
+      h1 = uimenu('parent', h_file, ...
78
+         'callback','rri_file_menu(''copy_fig'');', ...
79
+         'label','Copy to Clipboard');
80
+   else
81
+      h1 = uimenu('parent', h_file, ...
82
+         'callback','rri_file_menu(''copy_fig'');', ...
83
+         'separator','on', ...
84
+         'label','Copy to Clipboard');
85
+   end
86
+
87
+   h2 = uimenu(h_file, ...
88
+      'callback','pagesetupdlg(gcbf);', ...
89
+      'label','Page Setup...');
90
+
91
+   h2 = uimenu(h_file, ...
92
+      'callback','printpreview(gcbf);', ...
93
+      'label','Print Preview...');
94
+
95
+   h2 = uimenu('parent', h_file, ...
96
+      'callback','printdlg(gcbf);', ...
97
+      'label','Print Figure ...');
98
+
99
+   h2 = uimenu('parent', h_file, ...
100
+      'callback','rri_file_menu(''export_fig'');', ...
101
+      'label','Save Figure ...');
102
+
103
+   arch = computer;
104
+   if ~strcmpi(arch(1:2),'PC')
105
+      set(h1, 'enable', 'off');
106
+   end
107
+
108
+   if ~no_close
109
+      h1 = uimenu('parent', h_file, ...
110
+         'callback','close(gcbf);', ...
111
+         'separator','on', ...
112
+         'label','Close');
113
+   end
114
+
115
+   return;					% init
116
+
117
+
118
+%------------------------------------------------
119
+%
120
+%  Copy to clipboard
121
+%
122
+function copy_fig
123
+
124
+   arch = computer;
125
+   if(~strcmpi(arch(1:2),'PC'))
126
+      error('copy to clipboard can only be used under MS Windows');
127
+      return;
128
+   end
129
+
130
+   print -noui -dbitmap;
131
+
132
+   return					% copy_fig
133
+
134
+
135
+%------------------------------------------------
136
+%
137
+%  Save as an image file
138
+%
139
+function export_fig
140
+
141
+   curr = pwd;
142
+   if isempty(curr)
143
+      curr = filesep;
144
+   end
145
+
146
+   [selected_file, selected_path] = rri_select_file(curr,'Save As');
147
+
148
+   if isempty(selected_file) | isempty(selected_path)
149
+      return;
150
+   end
151
+
152
+   filename = [selected_path selected_file];
153
+
154
+   if(exist(filename,'file')==2)		% file exist
155
+
156
+      dlg_title = 'Confirm File Overwrite';
157
+      msg = ['File ',filename,' exist. Are you sure you want to overwrite it?'];
158
+      response = questdlg(msg,dlg_title,'Yes','No','Yes');
159
+
160
+      if(strcmp(response,'No'))
161
+         return;
162
+      end
163
+
164
+   end
165
+
166
+   old_pointer = get(gcbf,'pointer');
167
+   set(gcbf,'pointer','watch');
168
+
169
+   try
170
+      saveas(gcbf,filename);
171
+   catch
172
+      msg = 'ERROR: Cannot save file';
173
+      set(findobj(gcf,'Tag','MessageLine'),'String',msg);
174
+   end
175
+
176
+   set(gcbf,'pointer',old_pointer);
177
+
178
+   return;					% export_fig
179
+
... ...
@@ -0,0 +1,95 @@
1
+%  Convert image of different orientations to standard Analyze orientation
2
+%
3
+%  Usage: nii = rri_orient(nii);
4
+
5
+%  Jimmy Shen (jimmy@rotman-baycrest.on.ca), 26-APR-04
6
+%___________________________________________________________________
7
+
8
+function [nii, orient, pattern] = rri_orient(nii, varargin)
9
+
10
+   if nargin > 1
11
+      pattern = varargin{1};
12
+   else
13
+      pattern = [];
14
+   end
15
+
16
+   orient = [1 2 3];
17
+   dim = double(nii.hdr.dime.dim([2:4]));
18
+
19
+   if ~isempty(pattern) & ~isequal(length(pattern), prod(dim))
20
+      return;
21
+   end
22
+
23
+   %  get orient of the current image
24
+   %
25
+   orient = rri_orient_ui;
26
+   pause(.1);
27
+
28
+   %  no need for conversion
29
+   %
30
+   if isequal(orient, [1 2 3])
31
+      return;
32
+   end
33
+
34
+   if isempty(pattern)
35
+      pattern = 1:prod(dim);
36
+   end
37
+
38
+   pattern = reshape(pattern, dim);
39
+   img = nii.img;
40
+
41
+   %  calculate after flip orient
42
+   %
43
+   rot_orient = mod(orient + 2, 3) + 1;
44
+
45
+   %  do flip:
46
+   %
47
+   flip_orient = orient - rot_orient;
48
+
49
+   for i = 1:3
50
+      if flip_orient(i)
51
+         pattern = flipdim(pattern, i);
52
+         img = flipdim(img, i);
53
+      end
54
+   end
55
+
56
+   %  get index of orient (do inverse)
57
+   %
58
+   [tmp rot_orient] = sort(rot_orient);
59
+
60
+   %  do rotation:
61
+   %
62
+   pattern = permute(pattern, rot_orient);
63
+   img = permute(img, [rot_orient 4 5 6]);
64
+
65
+   %  rotate resolution, or 'dim'
66
+   %
67
+   new_dim = nii.hdr.dime.dim([2:4]);
68
+   new_dim = new_dim(rot_orient);
69
+   nii.hdr.dime.dim([2:4]) = new_dim;
70
+
71
+   %  rotate voxel_size, or 'pixdim'
72
+   %
73
+   tmp = nii.hdr.dime.pixdim([2:4]);
74
+   tmp = tmp(rot_orient);
75
+   nii.hdr.dime.pixdim([2:4]) = tmp;
76
+
77
+   %  re-calculate originator
78
+   %
79
+   tmp = nii.hdr.hist.originator([1:3]);
80
+   tmp = tmp(rot_orient);
81
+   flip_orient = flip_orient(rot_orient);
82
+
83
+   for i = 1:3
84
+      if flip_orient(i) & ~isequal(double(tmp(i)), 0)
85
+         tmp(i) = int16(double(new_dim(i)) - double(tmp(i)) + 1);
86
+      end
87
+   end
88
+
89
+   nii.hdr.hist.originator([1:3]) = tmp;
90
+
91
+   nii.img = img;
92
+   pattern = pattern(:);
93
+
94
+   return;						% rri_orient
95
+
... ...
@@ -0,0 +1,251 @@
1
+%  Return orientation of the current image:
2
+%	orient is orientation 1x3 matrix, in that:
3
+%	Three elements represent: [x y z]
4
+%	Element value:	1 - Left to Right; 2 - Posterior to Anterior;
5
+%			3 - Inferior to Superior; 4 - Right to Left;
6
+%			5 - Anterior to Posterior; 6 - Superior to Inferior;
7
+%  e.g.:
8
+%	Standard RAS Orientation:	[1 2 3]
9
+%	Standard RHOS Orientation:	[2 4 3]
10
+
11
+%  Jimmy Shen (jimmy@rotman-baycrest.on.ca), 26-APR-04
12
+%
13
+function orient = rri_orient_ui(varargin)
14
+
15
+   if nargin == 0
16
+      init;
17
+      orient_ui_fig = gcf;
18
+      uiwait;					% wait for user finish
19
+
20
+      orient = getappdata(gcf, 'orient');
21
+
22
+      if isempty(orient)
23
+         orient = [1 2 3];
24
+      end
25
+
26
+      if ishandle(orient_ui_fig)
27
+         close(gcf);
28
+      end
29
+
30
+      return;
31
+   end
32
+
33
+   action = varargin{1};
34
+
35
+   if strcmp(action, 'done')
36
+      click_done;
37
+   elseif strcmp(action, 'cancel')
38
+      uiresume;
39
+   end
40
+
41
+   return;						% rri_orient_ui
42
+
43
+
44
+%----------------------------------------------------------------------
45
+function init
46
+
47
+   save_setting_status = 'on';
48
+   rri_orient_pos = [];
49
+
50
+   try
51
+      load('pls_profile');
52
+   catch
53
+   end
54
+
55
+   try
56
+      load('rri_pos_profile');
57
+   catch
58
+   end
59
+
60
+   if ~isempty(rri_orient_pos) & strcmp(save_setting_status,'on')
61
+
62
+      pos = rri_orient_pos;
63
+
64
+   else
65
+
66
+      w = 0.35;
67
+      h = 0.4;
68
+      x = (1-w)/2;
69
+      y = (1-h)/2;
70
+
71
+      pos = [x y w h];
72
+
73
+   end
74
+
75
+   handles.figure = figure('Color',[0.8 0.8 0.8], ...
76
+        'Units','normal', ...
77
+        'Name', 'Convert to standard RAS orientation', ...
78
+        'NumberTitle','off', ...
79
+        'MenuBar','none', ...
80
+        'Position',pos, ...
81
+        'WindowStyle', 'normal', ...
82
+        'ToolBar','none');
83
+
84
+   h0 = handles.figure;
85
+   Font.FontUnits  = 'point';
86
+   Font.FontSize   = 12;
87
+
88
+   margin = .1;
89
+   line_num = 6;
90
+   line_ht = (1 - margin*2) / line_num;
91
+
92
+   x = margin;
93
+   y = 1 - margin - line_ht;
94
+   w = 1 - margin * 2;
95
+   h = line_ht * .7;
96
+
97
+   pos = [x y w h];
98
+
99
+   handles.Ttit = uicontrol('parent', h0, ...
100
+	'style','text', ...
101
+	'unit', 'normal', ...
102
+	Font, ...
103
+	'Position',pos, ...
104
+	'HorizontalAlignment','left',...
105
+	'background', [0.8 0.8 0.8], ...
106
+	'string', 'Please input orientation of the current image:');
107
+
108
+   y = y - line_ht;
109
+   w = .2;
110
+
111
+   pos = [x y w h];
112
+
113
+   handles.Tx_orient = uicontrol('parent', h0, ...
114
+	'style','text', ...
115
+	'unit', 'normal', ...
116
+	Font, ...
117
+	'Position',pos, ...
118
+	'HorizontalAlignment','left',...
119
+	'background', [0.8 0.8 0.8], ...
120
+	'string', 'X   Axes:');
121
+
122
+   y = y - line_ht;
123
+
124
+   pos = [x y w h];
125
+
126
+   handles.Ty_orient = uicontrol('parent', h0, ...
127
+	'style','text', ...
128
+	'unit', 'normal', ...
129
+	Font, ...
130
+	'Position',pos, ...
131
+	'HorizontalAlignment','left',...
132
+	'background', [0.8 0.8 0.8], ...
133
+	'string', 'Y   Axes:');
134
+
135
+   y = y - line_ht;
136
+
137
+   pos = [x y w h];
138
+
139
+   handles.Tz_orient = uicontrol('parent', h0, ...
140
+	'style','text', ...
141
+	'unit', 'normal', ...
142
+	Font, ...
143
+	'Position',pos, ...
144
+	'HorizontalAlignment','left',...
145
+	'background', [0.8 0.8 0.8], ...
146
+	'string', 'Z   Axes:');
147
+
148
+   choice = {	'From Left to Right', 'From Posterior to Anterior', ...
149
+		'From Inferior to Superior', 'From Right to Left', ...
150
+		'From Anterior to Posterior', 'From Superior to Inferior'	};
151
+
152
+   y = 1 - margin - line_ht;
153
+   y = y - line_ht;
154
+   w = 1 - margin - x - w;
155
+   x = 1 - margin - w;
156
+
157
+   pos = [x y w h];
158
+
159
+   handles.x_orient = uicontrol('parent', h0, ...
160
+	'style','popupmenu', ...
161
+	'unit', 'normal', ...
162
+	Font, ...
163
+	'Position',pos, ...
164
+	'HorizontalAlignment','left',...
165
+	'string', choice, ...
166
+	'value', 1, ...
167
+	'background', [1 1 1]);
168
+
169
+   y = y - line_ht;
170
+
171
+   pos = [x y w h];
172
+
173
+   handles.y_orient = uicontrol('parent', h0, ...
174
+	'style','popupmenu', ...
175
+	'unit', 'normal', ...
176
+	Font, ...
177
+	'Position',pos, ...
178
+	'HorizontalAlignment','left',...
179
+	'string', choice, ...
180
+	'value', 2, ...
181
+	'background', [1 1 1]);
182
+
183
+   y = y - line_ht;
184
+
185
+   pos = [x y w h];
186
+
187
+   handles.z_orient = uicontrol('parent', h0, ...
188
+	'style','popupmenu', ...
189
+	'unit', 'normal', ...
190
+	Font, ...
191
+	'Position',pos, ...
192
+	'HorizontalAlignment','left',...
193
+	'string', choice, ...
194
+	'value', 3, ...
195
+	'background', [1 1 1]);
196
+
197
+   x = margin;
198
+   y = y - line_ht * 1.5;
199
+   w = .3;
200
+
201
+   pos = [x y w h];
202
+
203
+   handles.done = uicontrol('parent', h0, ...
204
+	'unit', 'normal', ...
205
+	Font, ...
206
+	'Position',pos, ...
207
+	'HorizontalAlignment','center',...
208
+        'callback', 'rri_orient_ui(''done'');', ...
209
+	'string', 'Done');
210
+
211
+   x = 1 - margin - w;
212
+
213
+   pos = [x y w h];
214
+
215
+   handles.cancel = uicontrol('parent', h0, ...
216
+	'unit', 'normal', ...
217
+	Font, ...
218
+	'Position',pos, ...
219
+	'HorizontalAlignment','center',...
220
+        'callback', 'rri_orient_ui(''cancel'');', ...
221
+	'string', 'Cancel');
222
+
223
+   setappdata(h0, 'handles', handles);
224
+   setappdata(h0, 'orient', [1 2 3]);
225
+
226
+   return;						% init
227
+
228
+
229
+%----------------------------------------------------------------------
230
+function click_done
231
+
232
+   handles = getappdata(gcf, 'handles');
233
+
234
+   x_orient = get(handles.x_orient, 'value');
235
+   y_orient = get(handles.y_orient, 'value');
236
+   z_orient = get(handles.z_orient, 'value');
237
+
238
+   orient = [x_orient y_orient z_orient];
239
+   test_orient = [orient, orient + 3];
240
+   test_orient = mod(test_orient, 3);
241
+
242
+   if length(unique(test_orient)) ~= 3
243
+      msgbox('Please don''t choose same or opposite direction','Error','modal');
244
+      return;
245
+   end
246
+
247
+   setappdata(gcf, 'orient', [x_orient y_orient z_orient]);
248
+   uiresume;
249
+
250
+   return;						% click_done
251
+
... ...
@@ -0,0 +1,92 @@
1
+%   rri_xhair: create a pair of full_cross_hair at point [x y] in
2
+%              axes h_ax, and return xhair struct
3
+%
4
+%   Usage: xhair = rri_xhair([x y], xhair, h_ax);
5
+%
6
+%   If omit xhair, rri_xhair will create a pair of xhair; otherwise,
7
+%   rri_xhair will update the xhair. If omit h_ax, current axes will
8
+%   be used.
9
+%
10
+
11
+%   24-nov-2003 jimmy (jimmy@rotman-baycrest.on.ca)
12
+%
13
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14
+
15
+function xhair = rri_xhair(varargin)
16
+
17
+   if nargin == 0
18
+      error('Please enter a point position as first argument');
19
+      return;
20
+   end
21
+
22
+   if nargin > 0
23
+      p = varargin{1};
24
+
25
+      if ~isnumeric(p) | length(p) ~= 2
26
+         error('Invalid point position');
27
+         return;
28
+      else
29
+         xhair = [];
30
+      end
31
+   end
32
+
33
+   if nargin > 1
34
+      xhair = varargin{2};
35
+
36
+      if ~isempty(xhair)
37
+         if ~isstruct(xhair)
38
+            error('Invalid xhair struct');
39
+            return;
40
+         elseif ~isfield(xhair,'lx') | ~isfield(xhair,'ly')
41
+            error('Invalid xhair struct');
42
+            return;
43
+         elseif ~ishandle(xhair.lx) | ~ishandle(xhair.ly)
44
+            error('Invalid xhair struct');
45
+            return;
46
+         end
47
+
48
+         lx = xhair.lx;
49
+         ly = xhair.ly;
50
+      else
51
+         lx = [];
52
+         ly = [];
53
+      end
54
+   end
55
+
56
+   if nargin > 2
57
+      h_ax = varargin{3};
58
+
59
+      if ~ishandle(h_ax)
60
+         error('Invalid axes handle');
61
+         return;
62
+      elseif ~strcmp(lower(get(h_ax,'type')), 'axes')
63
+         error('Invalid axes handle');
64
+         return;
65
+      end
66
+   else
67
+      h_ax = gca;
68
+   end
69
+
70
+   x_range = get(h_ax,'xlim');
71
+   y_range = get(h_ax,'ylim');
72
+
73
+   if ~isempty(xhair)
74
+      set(lx, 'ydata', [p(2) p(2)]);
75
+      set(ly, 'xdata', [p(1) p(1)]);
76
+      set(h_ax, 'selected', 'on');
77
+      set(h_ax, 'selected', 'off');
78
+   else
79
+      figure(get(h_ax,'parent'));
80
+      axes(h_ax);
81
+
82
+      xhair.lx = line('xdata', x_range, 'ydata', [p(2) p(2)], ...
83
+	'zdata', [11 11], 'color', [1 0 0], 'hittest', 'off');
84
+      xhair.ly = line('xdata', [p(1) p(1)], 'ydata', y_range, ...
85
+	'zdata', [11 11], 'color', [1 0 0], 'hittest', 'off');
86
+   end
87
+
88
+   set(h_ax,'xlim',x_range);
89
+   set(h_ax,'ylim',y_range);
90
+
91
+   return;
92
+
... ...
@@ -0,0 +1,33 @@
1
+%  Imbed a zoom menu to any figure.
2
+%
3
+%  Usage: rri_zoom_menu(fig);
4
+%
5
+
6
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
7
+%
8
+%--------------------------------------------------------------------
9
+function menu_hdl = rri_zoom_menu(fig)
10
+
11
+   if isnumeric(fig)
12
+      menu_hdl = uimenu('Parent',fig, ...
13
+   	   'Label','Zoom on', ...
14
+	   'Userdata', 1, ...
15
+           'Callback','rri_zoom_menu(''zoom'');');
16
+
17
+      return;
18
+   end
19
+
20
+   zoom_on_state = get(gcbo,'Userdata');
21
+
22
+   if (zoom_on_state == 1)
23
+      zoom on;
24
+      set(gcbo,'Userdata',0,'Label','Zoom off');
25
+      set(gcbf,'pointer','crosshair');
26
+   else
27
+      zoom off;
28
+      set(gcbo,'Userdata',1,'Label','Zoom on');
29
+      set(gcbf,'pointer','arrow');
30
+   end
31
+
32
+   return					% rri_zoom_menu
33
+
... ...
@@ -0,0 +1,233 @@
1
+%  Save NIFTI dataset. Support both *.nii and *.hdr/*.img file extension.
2
+%  If file extension is not provided, *.hdr/*.img will be used as default.
3
+%  
4
+%  Usage: save_nii(nii, filename, [old_RGB])
5
+%  
6
+%  nii.hdr - struct with NIFTI header fields (from load_nii.m or make_nii.m)
7
+%
8
+%  nii.img - 3D (or 4D) matrix of NIFTI data.
9
+%
10
+%  filename - NIFTI file name.
11
+%
12
+%  old_RGB    - an optional boolean variable to handle special RGB data 
13
+%       sequence [R1 R2 ... G1 G2 ... B1 B2 ...] that is used only by 
14
+%       AnalyzeDirect (Analyze Software). Since both NIfTI and Analyze
15
+%       file format use RGB triple [R1 G1 B1 R2 G2 B2 ...] sequentially
16
+%       for each voxel, this variable is set to FALSE by default. If you
17
+%       would like the saved image only to be opened by AnalyzeDirect 
18
+%       Software, set old_RGB to TRUE (or 1). It will be set to 0, if it
19
+%       is default or empty.
20
+%  
21
+%  Tip: to change the data type, set nii.hdr.dime.datatype,
22
+%	and nii.hdr.dime.bitpix to:
23
+% 
24
+%     0 None                     (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN 
25
+%     1 Binary                         (ubit1, bitpix=1) % DT_BINARY 
26
+%     2 Unsigned char         (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8 
27
+%     4 Signed short                  (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16 
28
+%     8 Signed integer                (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32 
29
+%    16 Floating point    (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32 
30
+%    32 Complex, 2 float32      (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64
31
+%    64 Double precision  (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64 
32
+%   128 Red-Green-Blue            (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24 
33
+%   256 Signed char            (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8 
34
+%   512 Unsigned short               (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16 
35
+%   768 Unsigned integer             (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32 
36
+%  1024 Signed long long              (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64
37
+%  1280 Unsigned long long           (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64 
38
+%  1536 Long double, float128  (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128 
39
+%  1792 Complex128, 2 float64  (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 
40
+%  2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 
41
+%  
42
+%  Part of this file is copied and modified under GNU license from
43
+%  MRI_TOOLBOX developed by CNSP in Flinders University, Australia
44
+%
45
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
46
+%
47
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
48
+%  - "old_RGB" related codes in "save_nii.m" are added by Mike Harms (2006.06.28) 
49
+%
50
+function save_nii(nii, fileprefix, old_RGB)
51
+   
52
+   if ~exist('nii','var') | isempty(nii) | ~isfield(nii,'hdr') | ...
53
+	~isfield(nii,'img') | ~exist('fileprefix','var') | isempty(fileprefix)
54
+
55
+      error('Usage: save_nii(nii, filename, [old_RGB])');
56
+   end
57
+
58
+   if isfield(nii,'untouch') & nii.untouch == 1
59
+      error('Usage: please use ''save_untouch_nii.m'' for the untouched structure.');
60
+   end
61
+
62
+   if ~exist('old_RGB','var') | isempty(old_RGB)
63
+      old_RGB = 0;
64
+   end
65
+   
66
+   filetype = 1;
67
+
68
+   %  Note: fileprefix is actually the filename you want to save
69
+   %   
70
+   if findstr('.nii',fileprefix)
71
+      filetype = 2;
72
+      fileprefix = strrep(fileprefix,'.nii','');
73
+   end
74
+   
75
+   if findstr('.hdr',fileprefix)
76
+      fileprefix = strrep(fileprefix,'.hdr','');
77
+   end
78
+   
79
+   if findstr('.img',fileprefix)
80
+      fileprefix = strrep(fileprefix,'.img','');
81
+   end
82
+   
83
+   write_nii(nii, filetype, fileprefix, old_RGB);
84
+
85
+   if filetype == 1
86
+
87
+      %  So earlier versions of SPM can also open it with correct originator
88
+      %
89
+      M=[[diag(nii.hdr.dime.pixdim(2:4)) -[nii.hdr.hist.originator(1:3).*nii.hdr.dime.pixdim(2:4)]'];[0 0 0 1]];
90
+      save(fileprefix, 'M');
91
+   end
92
+   
93
+   return					% save_nii
94
+
95
+
96
+%-----------------------------------------------------------------------------------
97
+function write_nii(nii, filetype, fileprefix, old_RGB)
98
+
99
+   hdr = nii.hdr;
100
+
101
+   if isfield(nii,'ext') & ~isempty(nii.ext)
102
+      ext = nii.ext;
103
+      [ext, esize_total] = verify_nii_ext(ext);
104
+   else
105
+      ext = [];
106
+   end
107
+
108
+   switch double(hdr.dime.datatype),
109
+   case   1,
110
+      hdr.dime.bitpix = int16(1 ); precision = 'ubit1';
111
+   case   2,
112
+      hdr.dime.bitpix = int16(8 ); precision = 'uint8';
113
+   case   4,
114
+      hdr.dime.bitpix = int16(16); precision = 'int16';
115
+   case   8,
116
+      hdr.dime.bitpix = int16(32); precision = 'int32';
117
+   case  16,
118
+      hdr.dime.bitpix = int16(32); precision = 'float32';
119
+   case  32,
120
+      hdr.dime.bitpix = int16(64); precision = 'float32';
121
+   case  64,
122
+      hdr.dime.bitpix = int16(64); precision = 'float64';
123
+   case 128,
124
+      hdr.dime.bitpix = int16(24); precision = 'uint8';
125
+   case 256 
126
+      hdr.dime.bitpix = int16(8 ); precision = 'int8';
127
+   case 512 
128
+      hdr.dime.bitpix = int16(16); precision = 'uint16';
129
+   case 768 
130
+      hdr.dime.bitpix = int16(32); precision = 'uint32';
131
+   case 1024
132
+      hdr.dime.bitpix = int16(64); precision = 'int64';
133
+   case 1280
134
+      hdr.dime.bitpix = int16(64); precision = 'uint64';
135
+   case 1792,
136
+      hdr.dime.bitpix = int16(128); precision = 'float64';
137
+   otherwise
138
+      error('This datatype is not supported');
139
+   end
140
+   
141
+   hdr.dime.glmax = round(double(max(nii.img(:))));
142
+   hdr.dime.glmin = round(double(min(nii.img(:))));
143
+   
144
+   if filetype == 2
145
+      fid = fopen(sprintf('%s.nii',fileprefix),'w');
146
+      
147
+      if fid < 0,
148
+         msg = sprintf('Cannot open file %s.nii.',fileprefix);
149
+         error(msg);
150
+      end
151
+      
152
+      hdr.dime.vox_offset = 352;
153
+
154
+      if ~isempty(ext)
155
+         hdr.dime.vox_offset = hdr.dime.vox_offset + esize_total;
156
+      end
157
+
158
+      hdr.hist.magic = 'n+1';
159
+      save_nii_hdr(hdr, fid);
160
+
161
+      if ~isempty(ext)
162
+         save_nii_ext(ext, fid);
163
+      end
164
+   else
165
+      fid = fopen(sprintf('%s.hdr',fileprefix),'w');
166
+      
167
+      if fid < 0,
168
+         msg = sprintf('Cannot open file %s.hdr.',fileprefix);
169
+         error(msg);
170
+      end
171
+      
172
+      hdr.dime.vox_offset = 0;
173
+      hdr.hist.magic = 'ni1';
174
+      save_nii_hdr(hdr, fid);
175
+
176
+      if ~isempty(ext)
177
+         save_nii_ext(ext, fid);
178
+      end
179
+      
180
+      fclose(fid);
181
+      fid = fopen(sprintf('%s.img',fileprefix),'w');
182
+   end
183
+
184
+   ScanDim = double(hdr.dime.dim(5));		% t
185
+   SliceDim = double(hdr.dime.dim(4));		% z
186
+   RowDim   = double(hdr.dime.dim(3));		% y
187
+   PixelDim = double(hdr.dime.dim(2));		% x
188
+   SliceSz  = double(hdr.dime.pixdim(4));
189
+   RowSz    = double(hdr.dime.pixdim(3));
190
+   PixelSz  = double(hdr.dime.pixdim(2));
191
+   
192
+   x = 1:PixelDim;
193
+
194
+   if filetype == 2 & isempty(ext)
195
+      skip_bytes = double(hdr.dime.vox_offset) - 348;
196
+   else
197
+      skip_bytes = 0;
198
+   end
199
+
200
+   if double(hdr.dime.datatype) == 128
201
+
202
+      %  RGB planes are expected to be in the 4th dimension of nii.img
203
+      %
204
+      if(size(nii.img,4)~=3)
205
+         error(['The NII structure does not appear to have 3 RGB color planes in the 4th dimension']);
206
+      end
207
+
208
+      if old_RGB
209
+         nii.img = permute(nii.img, [1 2 4 3 5 6 7 8]);
210
+      else
211
+         nii.img = permute(nii.img, [4 1 2 3 5 6 7 8]);
212
+      end
213
+   end
214
+
215
+   %  For complex float32 or complex float64, voxel values
216
+   %  include [real, imag]
217
+   %
218
+   if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
219
+      real_img = real(nii.img(:))';
220
+      nii.img = imag(nii.img(:))';
221
+      nii.img = [real_img; nii.img];
222
+   end
223
+
224
+   if skip_bytes
225
+      fwrite(fid, ones(1,skip_bytes), 'uint8');
226
+   end
227
+
228
+   fwrite(fid, nii.img, precision);
229
+%   fwrite(fid, nii.img, precision, skip_bytes);        % error using skip
230
+   fclose(fid);
231
+
232
+   return;					% write_nii
233
+
... ...
@@ -0,0 +1,38 @@
1
+%  Save NIFTI header extension.
2
+%
3
+%  Usage: save_nii_ext(ext, fid)
4
+%
5
+%  ext - struct with NIFTI header extension fields.
6
+%
7
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
8
+%
9
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
10
+%
11
+function save_nii_ext(ext, fid)
12
+
13
+   if ~exist('ext','var') | ~exist('fid','var')
14
+      error('Usage: save_nii_ext(ext, fid)');
15
+   end
16
+
17
+   if ~isfield(ext,'extension') | ~isfield(ext,'section') | ~isfield(ext,'num_ext')
18
+      error('Wrong header extension');
19
+   end
20
+
21
+   write_ext(ext, fid);
22
+
23
+   return;                                      % save_nii_ext
24
+
25
+
26
+%---------------------------------------------------------------------
27
+function write_ext(ext, fid)
28
+
29
+   fwrite(fid, ext.extension, 'uchar');
30
+
31
+   for i=1:ext.num_ext
32
+      fwrite(fid, ext.section(i).esize, 'int32');
33
+      fwrite(fid, ext.section(i).ecode, 'int32');
34
+      fwrite(fid, ext.section(i).edata, 'uchar');
35
+   end
36
+
37
+   return;                                      % write_ext
38
+
... ...
@@ -0,0 +1,239 @@
1
+%  Save NIFTI dataset header. Support both *.nii and *.hdr/*.img file
2
+%  extension.
3
+%  
4
+%  Usage: save_nii_hdr(hdr, fid)
5
+%  
6
+%  hdr - struct with NIFTI header fields.
7
+%  
8
+%  fileprefix - NIFTI file name without extension.
9
+%  
10
+%  Part of this file is copied and modified under GNU license from
11
+%  MRI_TOOLBOX developed by CNSP in Flinders University, Australia
12
+%  
13
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
14
+%  
15
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
16
+%
17
+function save_nii_hdr(hdr, fid)
18
+   
19
+   if ~exist('hdr','var') | ~exist('fid','var')
20
+      error('Usage: save_nii_hdr(hdr, fid)');
21
+   end
22
+   
23
+   if ~isequal(hdr.hk.sizeof_hdr,348),
24
+      error('hdr.hk.sizeof_hdr must be 348.');
25
+   end
26
+   
27
+   if hdr.hist.qform_code == 0 & hdr.hist.sform_code == 0
28
+      hdr.hist.sform_code = 1;
29
+      hdr.hist.srow_x(1) = hdr.dime.pixdim(2);
30
+      hdr.hist.srow_x(2) = 0;
31
+      hdr.hist.srow_x(3) = 0;
32
+      hdr.hist.srow_y(1) = 0;
33
+      hdr.hist.srow_y(2) = hdr.dime.pixdim(3);
34
+      hdr.hist.srow_y(3) = 0;
35
+      hdr.hist.srow_z(1) = 0;
36
+      hdr.hist.srow_z(2) = 0;
37
+      hdr.hist.srow_z(3) = hdr.dime.pixdim(4);
38
+      hdr.hist.srow_x(4) = (1-hdr.hist.originator(1))*hdr.dime.pixdim(2);
39
+      hdr.hist.srow_y(4) = (1-hdr.hist.originator(2))*hdr.dime.pixdim(3);
40
+      hdr.hist.srow_z(4) = (1-hdr.hist.originator(3))*hdr.dime.pixdim(4);
41
+   end
42
+   
43
+   write_header(hdr, fid);
44
+
45
+   return;					% save_nii_hdr
46
+
47
+
48
+%---------------------------------------------------------------------
49
+function write_header(hdr, fid)
50
+
51
+        %  Original header structures
52
+	%  struct dsr				/* dsr = hdr */
53
+	%       { 
54
+	%       struct header_key hk;            /*   0 +  40       */
55
+	%       struct image_dimension dime;     /*  40 + 108       */
56
+	%       struct data_history hist;        /* 148 + 200       */
57
+	%       };                               /* total= 348 bytes*/
58
+   
59
+   header_key(fid, hdr.hk);
60
+   image_dimension(fid, hdr.dime);
61
+   data_history(fid, hdr.hist);
62
+   
63
+   %  check the file size is 348 bytes
64
+   %
65
+   fbytes = ftell(fid);
66
+   
67
+   if ~isequal(fbytes,348),
68
+      msg = sprintf('Header size is not 348 bytes.');
69
+      warning(msg);
70
+   end
71
+    
72
+   return;					% write_header
73
+
74
+
75
+%---------------------------------------------------------------------
76
+function header_key(fid, hk)
77
+   
78
+   fseek(fid,0,'bof');
79
+
80
+	%  Original header structures    
81
+	%  struct header_key                      /* header key      */ 
82
+	%       {                                /* off + size      */
83
+	%       int sizeof_hdr                   /*  0 +  4         */
84
+	%       char data_type[10];              /*  4 + 10         */
85
+	%       char db_name[18];                /* 14 + 18         */
86
+	%       int extents;                     /* 32 +  4         */
87
+	%       short int session_error;         /* 36 +  2         */
88
+	%       char regular;                    /* 38 +  1         */
89
+	%       char dim_info;   % char hkey_un0;        /* 39 +  1 */
90
+	%       };                               /* total=40 bytes  */
91
+        
92
+   fwrite(fid, hk.sizeof_hdr(1),    'int32');	% must be 348.
93
+    
94
+   % data_type = sprintf('%-10s',hk.data_type);	% ensure it is 10 chars from left
95
+   % fwrite(fid, data_type(1:10), 'uchar');
96
+   pad = zeros(1, 10-length(hk.data_type));
97
+   hk.data_type = [hk.data_type  char(pad)];
98
+   fwrite(fid, hk.data_type(1:10), 'uchar');
99
+    
100
+   % db_name   = sprintf('%-18s', hk.db_name);	% ensure it is 18 chars from left
101
+   % fwrite(fid, db_name(1:18), 'uchar');
102
+   pad = zeros(1, 18-length(hk.db_name));
103
+   hk.db_name = [hk.db_name  char(pad)];
104
+   fwrite(fid, hk.db_name(1:18), 'uchar');
105
+    
106
+   fwrite(fid, hk.extents(1),       'int32');
107
+   fwrite(fid, hk.session_error(1), 'int16');
108
+   fwrite(fid, hk.regular(1),       'uchar');	% might be uint8
109
+    
110
+   % fwrite(fid, hk.hkey_un0(1),    'uchar');
111
+   % fwrite(fid, hk.hkey_un0(1),    'uint8');
112
+   fwrite(fid, hk.dim_info(1),      'uchar');
113
+    
114
+   return;					% header_key
115
+
116
+
117
+%---------------------------------------------------------------------
118
+function image_dimension(fid, dime)
119
+
120
+	%  Original header structures        
121
+	%  struct image_dimension
122
+	%       {                                /* off + size      */
123
+	%       short int dim[8];                /* 0 + 16          */
124
+	%       float intent_p1;   % char vox_units[4];   /* 16 + 4       */
125
+	%       float intent_p2;   % char cal_units[8];   /* 20 + 4       */
126
+	%       float intent_p3;   % char cal_units[8];   /* 24 + 4       */
127
+	%       short int intent_code;   % short int unused1;   /* 28 + 2 */
128
+	%       short int datatype;              /* 30 + 2          */
129
+	%       short int bitpix;                /* 32 + 2          */
130
+	%       short int slice_start;   % short int dim_un0;   /* 34 + 2 */
131
+	%       float pixdim[8];                 /* 36 + 32         */
132
+	%			/*
133
+	%				pixdim[] specifies the voxel dimensions:
134
+	%				pixdim[1] - voxel width
135
+	%				pixdim[2] - voxel height
136
+	%				pixdim[3] - interslice distance
137
+	%				pixdim[4] - volume timing, in msec
138
+	%					..etc
139
+	%			*/
140
+	%       float vox_offset;                /* 68 + 4          */
141
+	%       float scl_slope;   % float roi_scale;     /* 72 + 4 */
142
+	%       float scl_inter;   % float funused1;      /* 76 + 4 */
143
+	%       short slice_end;   % float funused2;      /* 80 + 2 */
144
+	%       char slice_code;   % float funused2;      /* 82 + 1 */
145
+	%       char xyzt_units;   % float funused2;      /* 83 + 1 */
146
+	%       float cal_max;                   /* 84 + 4          */
147
+	%       float cal_min;                   /* 88 + 4          */
148
+	%       float slice_duration;   % int compressed; /* 92 + 4 */
149
+	%       float toffset;   % int verified;          /* 96 + 4 */
150
+	%       int glmax;                       /* 100 + 4         */
151
+	%       int glmin;                       /* 104 + 4         */
152
+	%       };                               /* total=108 bytes */
153
+	
154
+   fwrite(fid, dime.dim(1:8),        'int16');
155
+   fwrite(fid, dime.intent_p1(1),  'float32');
156
+   fwrite(fid, dime.intent_p2(1),  'float32');
157
+   fwrite(fid, dime.intent_p3(1),  'float32');
158
+   fwrite(fid, dime.intent_code(1),  'int16');
159
+   fwrite(fid, dime.datatype(1),     'int16');
160
+   fwrite(fid, dime.bitpix(1),       'int16');
161
+   fwrite(fid, dime.slice_start(1),  'int16');
162
+   fwrite(fid, dime.pixdim(1:8),   'float32');
163
+   fwrite(fid, dime.vox_offset(1), 'float32');
164
+   fwrite(fid, dime.scl_slope(1),  'float32');
165
+   fwrite(fid, dime.scl_inter(1),  'float32');
166
+   fwrite(fid, dime.slice_end(1),    'int16');
167
+   fwrite(fid, dime.slice_code(1),   'uchar');
168
+   fwrite(fid, dime.xyzt_units(1),   'uchar');
169
+   fwrite(fid, dime.cal_max(1),    'float32');
170
+   fwrite(fid, dime.cal_min(1),    'float32');
171
+   fwrite(fid, dime.slice_duration(1), 'float32');
172
+   fwrite(fid, dime.toffset(1),    'float32');
173
+   fwrite(fid, dime.glmax(1),        'int32');
174
+   fwrite(fid, dime.glmin(1),        'int32');
175
+   
176
+   return;					% image_dimension
177
+
178
+
179
+%---------------------------------------------------------------------
180
+function data_history(fid, hist)
181
+    
182
+	% Original header structures
183
+	%struct data_history       
184
+	%       {                                /* off + size      */
185
+	%       char descrip[80];                /* 0 + 80          */
186
+	%       char aux_file[24];               /* 80 + 24         */
187
+	%       short int qform_code;            /* 104 + 2         */
188
+	%       short int sform_code;            /* 106 + 2         */
189
+	%       float quatern_b;                 /* 108 + 4         */
190
+	%       float quatern_c;                 /* 112 + 4         */
191
+	%       float quatern_d;                 /* 116 + 4         */
192
+	%       float qoffset_x;                 /* 120 + 4         */
193
+	%       float qoffset_y;                 /* 124 + 4         */
194
+	%       float qoffset_z;                 /* 128 + 4         */
195
+	%       float srow_x[4];                 /* 132 + 16        */
196
+	%       float srow_y[4];                 /* 148 + 16        */
197
+	%       float srow_z[4];                 /* 164 + 16        */
198
+	%       char intent_name[16];            /* 180 + 16        */
199
+	%       char magic[4];   % int smin;     /* 196 + 4         */
200
+	%       };                               /* total=200 bytes */
201
+	
202
+   % descrip     = sprintf('%-80s', hist.descrip);     % 80 chars from left
203
+   % fwrite(fid, descrip(1:80),    'uchar');
204
+   pad = zeros(1, 80-length(hist.descrip));
205
+   hist.descrip = [hist.descrip  char(pad)];
206
+   fwrite(fid, hist.descrip(1:80), 'uchar');
207
+    
208
+   % aux_file    = sprintf('%-24s', hist.aux_file);    % 24 chars from left
209
+   % fwrite(fid, aux_file(1:24),   'uchar');
210
+   pad = zeros(1, 24-length(hist.aux_file));
211
+   hist.aux_file = [hist.aux_file  char(pad)];
212
+   fwrite(fid, hist.aux_file(1:24), 'uchar');
213
+    
214
+   fwrite(fid, hist.qform_code,    'int16');
215
+   fwrite(fid, hist.sform_code,    'int16');
216
+   fwrite(fid, hist.quatern_b,   'float32');
217
+   fwrite(fid, hist.quatern_c,   'float32');
218
+   fwrite(fid, hist.quatern_d,   'float32');
219
+   fwrite(fid, hist.qoffset_x,   'float32');
220
+   fwrite(fid, hist.qoffset_y,   'float32');
221
+   fwrite(fid, hist.qoffset_z,   'float32');
222
+   fwrite(fid, hist.srow_x(1:4), 'float32');
223
+   fwrite(fid, hist.srow_y(1:4), 'float32');
224
+   fwrite(fid, hist.srow_z(1:4), 'float32');
225
+
226
+   % intent_name = sprintf('%-16s', hist.intent_name);	% 16 chars from left
227
+   % fwrite(fid, intent_name(1:16),    'uchar');
228
+   pad = zeros(1, 16-length(hist.intent_name));
229
+   hist.intent_name = [hist.intent_name  char(pad)];
230
+   fwrite(fid, hist.intent_name(1:16), 'uchar');
231
+    
232
+   % magic	= sprintf('%-4s', hist.magic);		% 4 chars from left
233
+   % fwrite(fid, magic(1:4),           'uchar');
234
+   pad = zeros(1, 4-length(hist.magic));
235
+   hist.magic = [hist.magic  char(pad)];
236
+   fwrite(fid, hist.magic(1:4),        'uchar');
237
+    
238
+   return;					% data_history
239
+
... ...
@@ -0,0 +1,219 @@
1
+%  internal function
2
+
3
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
4
+
5
+function save_nii_hdr(hdr, fid)
6
+
7
+   if ~isequal(hdr.hk.sizeof_hdr,348),
8
+      error('hdr.hk.sizeof_hdr must be 348.');
9
+   end
10
+
11
+   write_header(hdr, fid);
12
+
13
+   return;					% save_nii_hdr
14
+
15
+
16
+%---------------------------------------------------------------------
17
+function write_header(hdr, fid)
18
+
19
+        %  Original header structures
20
+	%  struct dsr				/* dsr = hdr */
21
+	%       { 
22
+	%       struct header_key hk;            /*   0 +  40       */
23
+	%       struct image_dimension dime;     /*  40 + 108       */
24
+	%       struct data_history hist;        /* 148 + 200       */
25
+	%       };                               /* total= 348 bytes*/
26
+   
27
+   header_key(fid, hdr.hk);
28
+   image_dimension(fid, hdr.dime);
29
+   data_history(fid, hdr.hist);
30
+   
31
+   %  check the file size is 348 bytes
32
+   %
33
+   fbytes = ftell(fid);
34
+   
35
+   if ~isequal(fbytes,348),
36
+      msg = sprintf('Header size is not 348 bytes.');
37
+      warning(msg);
38
+   end
39
+    
40
+   return;					% write_header
41
+
42
+
43
+%---------------------------------------------------------------------
44
+function header_key(fid, hk)
45
+   
46
+   fseek(fid,0,'bof');
47
+
48
+	%  Original header structures    
49
+	%  struct header_key                      /* header key      */ 
50
+	%       {                                /* off + size      */
51
+	%       int sizeof_hdr                   /*  0 +  4         */
52
+	%       char data_type[10];              /*  4 + 10         */
53
+	%       char db_name[18];                /* 14 + 18         */
54
+	%       int extents;                     /* 32 +  4         */
55
+	%       short int session_error;         /* 36 +  2         */
56
+	%       char regular;                    /* 38 +  1         */
57
+	%       char hkey_un0;                   /* 39 +  1 */
58
+	%       };                               /* total=40 bytes  */
59
+        
60
+   fwrite(fid, hk.sizeof_hdr(1),    'int32');	% must be 348.
61
+    
62
+   % data_type = sprintf('%-10s',hk.data_type);	% ensure it is 10 chars from left
63
+   % fwrite(fid, data_type(1:10), 'uchar');
64
+   pad = zeros(1, 10-length(hk.data_type));
65
+   hk.data_type = [hk.data_type  char(pad)];
66
+   fwrite(fid, hk.data_type(1:10), 'uchar');
67
+    
68
+   % db_name   = sprintf('%-18s', hk.db_name);	% ensure it is 18 chars from left
69
+   % fwrite(fid, db_name(1:18), 'uchar');
70
+   pad = zeros(1, 18-length(hk.db_name));
71
+   hk.db_name = [hk.db_name  char(pad)];
72
+   fwrite(fid, hk.db_name(1:18), 'uchar');
73
+
74
+   fwrite(fid, hk.extents(1),       'int32');
75
+   fwrite(fid, hk.session_error(1), 'int16');
76
+   fwrite(fid, hk.regular(1),       'uchar');
77
+
78
+   fwrite(fid, hk.hkey_un0(1),    'uchar');
79
+    
80
+   return;					% header_key
81
+
82
+
83
+%---------------------------------------------------------------------
84
+function image_dimension(fid, dime)
85
+
86
+	%struct image_dimension
87
+	%       {                                /* off + size      */
88
+	%       short int dim[8];                /* 0 + 16          */
89
+	%       char vox_units[4];               /* 16 + 4          */
90
+	%       char cal_units[8];               /* 20 + 8          */
91
+	%       short int unused1;               /* 28 + 2          */
92
+	%       short int datatype;              /* 30 + 2          */
93
+	%       short int bitpix;                /* 32 + 2          */
94
+	%       short int dim_un0;               /* 34 + 2          */
95
+	%       float pixdim[8];                 /* 36 + 32         */
96
+	%			/*
97
+	%				pixdim[] specifies the voxel dimensions:
98
+	%				pixdim[1] - voxel width
99
+	%				pixdim[2] - voxel height
100
+	%				pixdim[3] - interslice distance
101
+	%					..etc
102
+	%			*/
103
+	%       float vox_offset;                /* 68 + 4          */
104
+	%       float roi_scale;                 /* 72 + 4          */
105
+	%       float funused1;                  /* 76 + 4          */
106
+	%       float funused2;                  /* 80 + 4          */
107
+	%       float cal_max;                   /* 84 + 4          */
108
+	%       float cal_min;                   /* 88 + 4          */
109
+	%       int compressed;                  /* 92 + 4          */
110
+	%       int verified;                    /* 96 + 4          */
111
+	%       int glmax;                       /* 100 + 4         */
112
+	%       int glmin;                       /* 104 + 4         */
113
+	%       };                               /* total=108 bytes */
114
+	
115
+   fwrite(fid, dime.dim(1:8),      'int16');
116
+
117
+   pad = zeros(1, 4-length(dime.vox_units));
118
+   dime.vox_units = [dime.vox_units  char(pad)];
119
+   fwrite(fid, dime.vox_units(1:4),  'uchar');
120
+
121
+   pad = zeros(1, 8-length(dime.cal_units));
122
+   dime.cal_units = [dime.cal_units  char(pad)];
123
+   fwrite(fid, dime.cal_units(1:8),  'uchar');
124
+
125
+   fwrite(fid, dime.unused1(1),    'int16');
126
+   fwrite(fid, dime.datatype(1),   'int16');
127
+   fwrite(fid, dime.bitpix(1),     'int16');
128
+   fwrite(fid, dime.dim_un0(1),    'int16');
129
+   fwrite(fid, dime.pixdim(1:8),   'float32');
130
+   fwrite(fid, dime.vox_offset(1), 'float32');
131
+   fwrite(fid, dime.roi_scale(1),  'float32');
132
+   fwrite(fid, dime.funused1(1),   'float32');
133
+   fwrite(fid, dime.funused2(1),   'float32');
134
+   fwrite(fid, dime.cal_max(1),    'float32');
135
+   fwrite(fid, dime.cal_min(1),    'float32');
136
+   fwrite(fid, dime.compressed(1), 'int32');
137
+   fwrite(fid, dime.verified(1),   'int32');
138
+   fwrite(fid, dime.glmax(1),      'int32');
139
+   fwrite(fid, dime.glmin(1),      'int32');
140
+   
141
+   return;					% image_dimension
142
+
143
+
144
+%---------------------------------------------------------------------
145
+function data_history(fid, hist)
146
+    
147
+	% Original header structures - ANALYZE 7.5
148
+	%struct data_history       
149
+	%       {                                /* off + size      */
150
+	%       char descrip[80];                /* 0 + 80          */
151
+	%       char aux_file[24];               /* 80 + 24         */
152
+	%       char orient;                     /* 104 + 1         */
153
+	%       char originator[10];             /* 105 + 10        */
154
+	%       char generated[10];              /* 115 + 10        */
155
+	%       char scannum[10];                /* 125 + 10        */
156
+	%       char patient_id[10];             /* 135 + 10        */
157
+	%       char exp_date[10];               /* 145 + 10        */
158
+	%       char exp_time[10];               /* 155 + 10        */
159
+	%       char hist_un0[3];                /* 165 + 3         */
160
+	%       int views                        /* 168 + 4         */
161
+	%       int vols_added;                  /* 172 + 4         */
162
+	%       int start_field;                 /* 176 + 4         */
163
+	%       int field_skip;                  /* 180 + 4         */
164
+	%       int omax;                        /* 184 + 4         */
165
+	%       int omin;                        /* 188 + 4         */
166
+	%       int smax;                        /* 192 + 4         */
167
+	%       int smin;                        /* 196 + 4         */
168
+	%       };                               /* total=200 bytes */
169
+	
170
+   % descrip     = sprintf('%-80s', hist.descrip);     % 80 chars from left
171
+   % fwrite(fid, descrip(1:80),    'uchar');
172
+   pad = zeros(1, 80-length(hist.descrip));
173
+   hist.descrip = [hist.descrip  char(pad)];
174
+   fwrite(fid, hist.descrip(1:80), 'uchar');
175
+    
176
+   % aux_file    = sprintf('%-24s', hist.aux_file);    % 24 chars from left
177
+   % fwrite(fid, aux_file(1:24),   'uchar');
178
+   pad = zeros(1, 24-length(hist.aux_file));
179
+   hist.aux_file = [hist.aux_file  char(pad)];
180
+   fwrite(fid, hist.aux_file(1:24), 'uchar');
181
+
182
+   fwrite(fid, hist.orient(1),      'uchar');
183
+   fwrite(fid, hist.originator(1:5), 'int16');
184
+
185
+   pad = zeros(1, 10-length(hist.generated));
186
+   hist.generated = [hist.generated  char(pad)];
187
+   fwrite(fid, hist.generated(1:10),  'uchar');
188
+
189
+   pad = zeros(1, 10-length(hist.scannum));
190
+   hist.scannum = [hist.scannum  char(pad)];
191
+   fwrite(fid, hist.scannum(1:10),  'uchar');
192
+
193
+   pad = zeros(1, 10-length(hist.patient_id));
194
+   hist.patient_id = [hist.patient_id  char(pad)];
195
+   fwrite(fid, hist.patient_id(1:10),  'uchar');
196
+
197
+   pad = zeros(1, 10-length(hist.exp_date));
198
+   hist.exp_date = [hist.exp_date  char(pad)];
199
+   fwrite(fid, hist.exp_date(1:10),  'uchar');
200
+
201
+   pad = zeros(1, 10-length(hist.exp_time));
202
+   hist.exp_time = [hist.exp_time  char(pad)];
203
+   fwrite(fid, hist.exp_time(1:10),  'uchar');
204
+
205
+   pad = zeros(1, 3-length(hist.hist_un0));
206
+   hist.hist_un0 = [hist.hist_un0  char(pad)];
207
+   fwrite(fid, hist.hist_un0(1:3),  'uchar');
208
+
209
+   fwrite(fid, hist.views(1),      'int32');
210
+   fwrite(fid, hist.vols_added(1), 'int32');
211
+   fwrite(fid, hist.start_field(1),'int32');
212
+   fwrite(fid, hist.field_skip(1), 'int32');
213
+   fwrite(fid, hist.omax(1),       'int32');
214
+   fwrite(fid, hist.omin(1),       'int32');
215
+   fwrite(fid, hist.smax(1),       'int32');
216
+   fwrite(fid, hist.smin(1),       'int32');
217
+    
218
+   return;					% data_history
219
+
... ...
@@ -0,0 +1,197 @@
1
+%  Save NIFTI or ANALYZE dataset that is loaded by "load_untouch_nii.m".
2
+%  The output image format and file extension will be the same as the
3
+%  input one (NIFTI.nii, NIFTI.img or ANALYZE.img). Therefore, any file
4
+%  extension that you specified will be ignored.
5
+%
6
+%  Usage: save_untouch_nii(nii, filename)
7
+%  
8
+%  nii - nii structure that is loaded by "load_untouch_nii.m"
9
+%
10
+%  filename  - 	NIFTI or ANALYZE file name.
11
+%
12
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
13
+%
14
+function save_untouch_nii(nii, filename)
15
+   
16
+   if ~exist('nii','var') | isempty(nii) | ~isfield(nii,'hdr') | ...
17
+	~isfield(nii,'img') | ~exist('filename','var') | isempty(filename)
18
+
19
+      error('Usage: save_untouch_nii(nii, filename)');
20
+   end
21
+
22
+   if ~isfield(nii,'untouch') | nii.untouch == 0
23
+      error('Usage: please use ''save_nii.m'' for the modified structure.');
24
+   end
25
+
26
+   if isfield(nii.hdr.hist,'magic') & strcmp(nii.hdr.hist.magic(1:3),'ni1')
27
+      filetype = 1;
28
+   elseif isfield(nii.hdr.hist,'magic') & strcmp(nii.hdr.hist.magic(1:3),'n+1')
29
+      filetype = 2;
30
+   else
31
+      filetype = 0;
32
+   end
33
+
34
+   [p,f] = fileparts(filename);
35
+   fileprefix = fullfile(p, f);
36
+
37
+   write_nii(nii, filetype, fileprefix);
38
+
39
+%   %  So earlier versions of SPM can also open it with correct originator
40
+ %  %
41
+  % if filetype == 0
42
+   %   M=[[diag(nii.hdr.dime.pixdim(2:4)) -[nii.hdr.hist.originator(1:3).*nii.hdr.dime.pixdim(2:4)]'];[0 0 0 1]];
43
+    %  save(fileprefix, 'M');
44
+%   elseif filetype == 1
45
+ %     M=[];
46
+  %    save(fileprefix, 'M');
47
+   %end
48
+   
49
+   return					% save_untouch_nii
50
+
51
+
52
+%-----------------------------------------------------------------------------------
53
+function write_nii(nii, filetype, fileprefix)
54
+
55
+   hdr = nii.hdr;
56
+
57
+   if isfield(nii,'ext') & ~isempty(nii.ext)
58
+      ext = nii.ext;
59
+      [ext, esize_total] = verify_nii_ext(ext);
60
+   else
61
+      ext = [];
62
+   end
63
+
64
+   switch double(hdr.dime.datatype),
65
+   case   1,
66
+      hdr.dime.bitpix = int16(1 ); precision = 'ubit1';
67
+   case   2,
68
+      hdr.dime.bitpix = int16(8 ); precision = 'uint8';
69
+   case   4,
70
+      hdr.dime.bitpix = int16(16); precision = 'int16';
71
+   case   8,
72
+      hdr.dime.bitpix = int16(32); precision = 'int32';
73
+   case  16,
74
+      hdr.dime.bitpix = int16(32); precision = 'float32';
75
+   case  32,
76
+      hdr.dime.bitpix = int16(64); precision = 'float32';
77
+   case  64,
78
+      hdr.dime.bitpix = int16(64); precision = 'float64';
79
+   case 128,
80
+      hdr.dime.bitpix = int16(24); precision = 'uint8';
81
+   case 256 
82
+      hdr.dime.bitpix = int16(8 ); precision = 'int8';
83
+   case 512 
84
+      hdr.dime.bitpix = int16(16); precision = 'uint16';
85
+   case 768 
86
+      hdr.dime.bitpix = int16(32); precision = 'uint32';
87
+   case 1024
88
+      hdr.dime.bitpix = int16(64); precision = 'int64';
89
+   case 1280
90
+      hdr.dime.bitpix = int16(64); precision = 'uint64';
91
+   case 1792,
92
+      hdr.dime.bitpix = int16(128); precision = 'float64';
93
+   otherwise
94
+      error('This datatype is not supported');
95
+   end
96
+   
97
+%   hdr.dime.glmax = round(double(max(nii.img(:))));
98
+ %  hdr.dime.glmin = round(double(min(nii.img(:))));
99
+   
100
+   if filetype == 2
101
+      fid = fopen(sprintf('%s.nii',fileprefix),'w');
102
+      
103
+      if fid < 0,
104
+         msg = sprintf('Cannot open file %s.nii.',fileprefix);
105
+         error(msg);
106
+      end
107
+      
108
+      hdr.dime.vox_offset = 352;
109
+
110
+      if ~isempty(ext)
111
+         hdr.dime.vox_offset = hdr.dime.vox_offset + esize_total;
112
+      end
113
+
114
+      hdr.hist.magic = 'n+1';
115
+      save_untouch_nii_hdr(hdr, fid);
116
+
117
+      if ~isempty(ext)
118
+         save_nii_ext(ext, fid);
119
+      end
120
+   elseif filetype == 1
121
+      fid = fopen(sprintf('%s.hdr',fileprefix),'w');
122
+      
123
+      if fid < 0,
124
+         msg = sprintf('Cannot open file %s.hdr.',fileprefix);
125
+         error(msg);
126
+      end
127
+      
128
+      hdr.dime.vox_offset = 0;
129
+      hdr.hist.magic = 'ni1';
130
+      save_untouch_nii_hdr(hdr, fid);
131
+
132
+      if ~isempty(ext)
133
+         save_nii_ext(ext, fid);
134
+      end
135
+      
136
+      fclose(fid);
137
+      fid = fopen(sprintf('%s.img',fileprefix),'w');
138
+   else
139
+      fid = fopen(sprintf('%s.hdr',fileprefix),'w');
140
+      
141
+      if fid < 0,
142
+         msg = sprintf('Cannot open file %s.hdr.',fileprefix);
143
+         error(msg);
144
+      end
145
+      
146
+      save_untouch0_nii_hdr(hdr, fid);
147
+      
148
+      fclose(fid);
149
+      fid = fopen(sprintf('%s.img',fileprefix),'w');
150
+   end
151
+
152
+   ScanDim = double(hdr.dime.dim(5));		% t
153
+   SliceDim = double(hdr.dime.dim(4));		% z
154
+   RowDim   = double(hdr.dime.dim(3));		% y
155
+   PixelDim = double(hdr.dime.dim(2));		% x
156
+   SliceSz  = double(hdr.dime.pixdim(4));
157
+   RowSz    = double(hdr.dime.pixdim(3));
158
+   PixelSz  = double(hdr.dime.pixdim(2));
159
+   
160
+   x = 1:PixelDim;
161
+   
162
+   if filetype == 2 & isempty(ext)
163
+      skip_bytes = double(hdr.dime.vox_offset) - 348;
164
+   else
165
+      skip_bytes = 0;
166
+   end
167
+
168
+   if double(hdr.dime.datatype) == 128
169
+
170
+      %  RGB planes are expected to be in the 4th dimension of nii.img
171
+      %
172
+      if(size(nii.img,4)~=3)
173
+         error(['The NII structure does not appear to have 3 RGB color planes in the 4th dimension']);
174
+      end
175
+
176
+      nii.img = permute(nii.img, [4 1 2 3 5]);
177
+   end
178
+
179
+   %  For complex float32 or complex float64, voxel values
180
+   %  include [real, imag]
181
+   %
182
+   if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
183
+      real_img = real(nii.img(:))';
184
+      nii.img = imag(nii.img(:))';
185
+      nii.img = [real_img; nii.img];
186
+   end
187
+
188
+   if skip_bytes
189
+      fwrite(fid, ones(1,skip_bytes), 'uint8');
190
+   end
191
+
192
+   fwrite(fid, nii.img, precision);
193
+%   fwrite(fid, nii.img, precision, skip_bytes);        % error using skip
194
+   fclose(fid);
195
+
196
+   return;					% write_nii
197
+
... ...
@@ -0,0 +1,207 @@
1
+%  internal function
2
+
3
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
4
+
5
+function save_nii_hdr(hdr, fid)
6
+
7
+   if ~isequal(hdr.hk.sizeof_hdr,348),
8
+      error('hdr.hk.sizeof_hdr must be 348.');
9
+   end
10
+
11
+   write_header(hdr, fid);
12
+
13
+   return;					% save_nii_hdr
14
+
15
+
16
+%---------------------------------------------------------------------
17
+function write_header(hdr, fid)
18
+
19
+        %  Original header structures
20
+	%  struct dsr				/* dsr = hdr */
21
+	%       { 
22
+	%       struct header_key hk;            /*   0 +  40       */
23
+	%       struct image_dimension dime;     /*  40 + 108       */
24
+	%       struct data_history hist;        /* 148 + 200       */
25
+	%       };                               /* total= 348 bytes*/
26
+   
27
+   header_key(fid, hdr.hk);
28
+   image_dimension(fid, hdr.dime);
29
+   data_history(fid, hdr.hist);
30
+   
31
+   %  check the file size is 348 bytes
32
+   %
33
+   fbytes = ftell(fid);
34
+   
35
+   if ~isequal(fbytes,348),
36
+      msg = sprintf('Header size is not 348 bytes.');
37
+      warning(msg);
38
+   end
39
+    
40
+   return;					% write_header
41
+
42
+
43
+%---------------------------------------------------------------------
44
+function header_key(fid, hk)
45
+   
46
+   fseek(fid,0,'bof');
47
+
48
+	%  Original header structures    
49
+	%  struct header_key                      /* header key      */ 
50
+	%       {                                /* off + size      */
51
+	%       int sizeof_hdr                   /*  0 +  4         */
52
+	%       char data_type[10];              /*  4 + 10         */
53
+	%       char db_name[18];                /* 14 + 18         */
54
+	%       int extents;                     /* 32 +  4         */
55
+	%       short int session_error;         /* 36 +  2         */
56
+	%       char regular;                    /* 38 +  1         */
57
+	%       char dim_info;   % char hkey_un0;        /* 39 +  1 */
58
+	%       };                               /* total=40 bytes  */
59
+        
60
+   fwrite(fid, hk.sizeof_hdr(1),    'int32');	% must be 348.
61
+    
62
+   % data_type = sprintf('%-10s',hk.data_type);	% ensure it is 10 chars from left
63
+   % fwrite(fid, data_type(1:10), 'uchar');
64
+   pad = zeros(1, 10-length(hk.data_type));
65
+   hk.data_type = [hk.data_type  char(pad)];
66
+   fwrite(fid, hk.data_type(1:10), 'uchar');
67
+    
68
+   % db_name   = sprintf('%-18s', hk.db_name);	% ensure it is 18 chars from left
69
+   % fwrite(fid, db_name(1:18), 'uchar');
70
+   pad = zeros(1, 18-length(hk.db_name));
71
+   hk.db_name = [hk.db_name  char(pad)];
72
+   fwrite(fid, hk.db_name(1:18), 'uchar');
73
+    
74
+   fwrite(fid, hk.extents(1),       'int32');
75
+   fwrite(fid, hk.session_error(1), 'int16');
76
+   fwrite(fid, hk.regular(1),       'uchar');	% might be uint8
77
+    
78
+   % fwrite(fid, hk.hkey_un0(1),    'uchar');
79
+   % fwrite(fid, hk.hkey_un0(1),    'uint8');
80
+   fwrite(fid, hk.dim_info(1),      'uchar');
81
+    
82
+   return;					% header_key
83
+
84
+
85
+%---------------------------------------------------------------------
86
+function image_dimension(fid, dime)
87
+
88
+	%  Original header structures        
89
+	%  struct image_dimension
90
+	%       {                                /* off + size      */
91
+	%       short int dim[8];                /* 0 + 16          */
92
+	%       float intent_p1;   % char vox_units[4];   /* 16 + 4       */
93
+	%       float intent_p2;   % char cal_units[8];   /* 20 + 4       */
94
+	%       float intent_p3;   % char cal_units[8];   /* 24 + 4       */
95
+	%       short int intent_code;   % short int unused1;   /* 28 + 2 */
96
+	%       short int datatype;              /* 30 + 2          */
97
+	%       short int bitpix;                /* 32 + 2          */
98
+	%       short int slice_start;   % short int dim_un0;   /* 34 + 2 */
99
+	%       float pixdim[8];                 /* 36 + 32         */
100
+	%			/*
101
+	%				pixdim[] specifies the voxel dimensions:
102
+	%				pixdim[1] - voxel width
103
+	%				pixdim[2] - voxel height
104
+	%				pixdim[3] - interslice distance
105
+	%				pixdim[4] - volume timing, in msec
106
+	%					..etc
107
+	%			*/
108
+	%       float vox_offset;                /* 68 + 4          */
109
+	%       float scl_slope;   % float roi_scale;     /* 72 + 4 */
110
+	%       float scl_inter;   % float funused1;      /* 76 + 4 */
111
+	%       short slice_end;   % float funused2;      /* 80 + 2 */
112
+	%       char slice_code;   % float funused2;      /* 82 + 1 */
113
+	%       char xyzt_units;   % float funused2;      /* 83 + 1 */
114
+	%       float cal_max;                   /* 84 + 4          */
115
+	%       float cal_min;                   /* 88 + 4          */
116
+	%       float slice_duration;   % int compressed; /* 92 + 4 */
117
+	%       float toffset;   % int verified;          /* 96 + 4 */
118
+	%       int glmax;                       /* 100 + 4         */
119
+	%       int glmin;                       /* 104 + 4         */
120
+	%       };                               /* total=108 bytes */
121
+	
122
+   fwrite(fid, dime.dim(1:8),        'int16');
123
+   fwrite(fid, dime.intent_p1(1),  'float32');
124
+   fwrite(fid, dime.intent_p2(1),  'float32');
125
+   fwrite(fid, dime.intent_p3(1),  'float32');
126
+   fwrite(fid, dime.intent_code(1),  'int16');
127
+   fwrite(fid, dime.datatype(1),     'int16');
128
+   fwrite(fid, dime.bitpix(1),       'int16');
129
+   fwrite(fid, dime.slice_start(1),  'int16');
130
+   fwrite(fid, dime.pixdim(1:8),   'float32');
131
+   fwrite(fid, dime.vox_offset(1), 'float32');
132
+   fwrite(fid, dime.scl_slope(1),  'float32');
133
+   fwrite(fid, dime.scl_inter(1),  'float32');
134
+   fwrite(fid, dime.slice_end(1),    'int16');
135
+   fwrite(fid, dime.slice_code(1),   'uchar');
136
+   fwrite(fid, dime.xyzt_units(1),   'uchar');
137
+   fwrite(fid, dime.cal_max(1),    'float32');
138
+   fwrite(fid, dime.cal_min(1),    'float32');
139
+   fwrite(fid, dime.slice_duration(1), 'float32');
140
+   fwrite(fid, dime.toffset(1),    'float32');
141
+   fwrite(fid, dime.glmax(1),        'int32');
142
+   fwrite(fid, dime.glmin(1),        'int32');
143
+   
144
+   return;					% image_dimension
145
+
146
+
147
+%---------------------------------------------------------------------
148
+function data_history(fid, hist)
149
+    
150
+	% Original header structures
151
+	%struct data_history       
152
+	%       {                                /* off + size      */
153
+	%       char descrip[80];                /* 0 + 80          */
154
+	%       char aux_file[24];               /* 80 + 24         */
155
+	%       short int qform_code;            /* 104 + 2         */
156
+	%       short int sform_code;            /* 106 + 2         */
157
+	%       float quatern_b;                 /* 108 + 4         */
158
+	%       float quatern_c;                 /* 112 + 4         */
159
+	%       float quatern_d;                 /* 116 + 4         */
160
+	%       float qoffset_x;                 /* 120 + 4         */
161
+	%       float qoffset_y;                 /* 124 + 4         */
162
+	%       float qoffset_z;                 /* 128 + 4         */
163
+	%       float srow_x[4];                 /* 132 + 16        */
164
+	%       float srow_y[4];                 /* 148 + 16        */
165
+	%       float srow_z[4];                 /* 164 + 16        */
166
+	%       char intent_name[16];            /* 180 + 16        */
167
+	%       char magic[4];   % int smin;     /* 196 + 4         */
168
+	%       };                               /* total=200 bytes */
169
+	
170
+   % descrip     = sprintf('%-80s', hist.descrip);     % 80 chars from left
171
+   % fwrite(fid, descrip(1:80),    'uchar');
172
+   pad = zeros(1, 80-length(hist.descrip));
173
+   hist.descrip = [hist.descrip  char(pad)];
174
+   fwrite(fid, hist.descrip(1:80), 'uchar');
175
+    
176
+   % aux_file    = sprintf('%-24s', hist.aux_file);    % 24 chars from left
177
+   % fwrite(fid, aux_file(1:24),   'uchar');
178
+   pad = zeros(1, 24-length(hist.aux_file));
179
+   hist.aux_file = [hist.aux_file  char(pad)];
180
+   fwrite(fid, hist.aux_file(1:24), 'uchar');
181
+    
182
+   fwrite(fid, hist.qform_code,    'int16');
183
+   fwrite(fid, hist.sform_code,    'int16');
184
+   fwrite(fid, hist.quatern_b,   'float32');
185
+   fwrite(fid, hist.quatern_c,   'float32');
186
+   fwrite(fid, hist.quatern_d,   'float32');
187
+   fwrite(fid, hist.qoffset_x,   'float32');
188
+   fwrite(fid, hist.qoffset_y,   'float32');
189
+   fwrite(fid, hist.qoffset_z,   'float32');
190
+   fwrite(fid, hist.srow_x(1:4), 'float32');
191
+   fwrite(fid, hist.srow_y(1:4), 'float32');
192
+   fwrite(fid, hist.srow_z(1:4), 'float32');
193
+
194
+   % intent_name = sprintf('%-16s', hist.intent_name);	% 16 chars from left
195
+   % fwrite(fid, intent_name(1:16),    'uchar');
196
+   pad = zeros(1, 16-length(hist.intent_name));
197
+   hist.intent_name = [hist.intent_name  char(pad)];
198
+   fwrite(fid, hist.intent_name(1:16), 'uchar');
199
+    
200
+   % magic	= sprintf('%-4s', hist.magic);		% 4 chars from left
201
+   % fwrite(fid, magic(1:4),           'uchar');
202
+   pad = zeros(1, 4-length(hist.magic));
203
+   hist.magic = [hist.magic  char(pad)];
204
+   fwrite(fid, hist.magic(1:4),        'uchar');
205
+    
206
+   return;					% data_history
207
+
... ...
@@ -0,0 +1,40 @@
1
+%  Undo the flipping and rotations performed by xform_nii; spit back only
2
+%  the raw img data block. Initial cut will only deal with 3D volumes
3
+%  strongly assume we have called xform_nii to write down the steps used 
4
+%  in xform_nii.
5
+%
6
+%  Usage:  a = load_nii('original_name');
7
+%          manipulate a.img to make array b;
8
+%
9
+%          if you use unxform_nii to un-tranform the image (img) data
10
+%          block, then nii.original.hdr is the corresponding header.
11
+%
12
+%          nii.original.img = unxform_nii(a, b);
13
+%          save_nii(nii.original,'newname');
14
+%
15
+%  Where, 'newname' is created with data in the same space as the
16
+%         original_name data    
17
+%
18
+%  - Jeff Gunter, 26-JUN-06
19
+%
20
+function outblock = unxform_nii(nii, inblock)
21
+  
22
+   if isempty(nii.hdr.hist.rot_orient)     
23
+      outblock=inblock;
24
+   else
25
+      [dummy unrotate_orient] = sort(nii.hdr.hist.rot_orient);
26
+      outblock = permute(inblock, unrotate_orient);
27
+   end
28
+
29
+   if ~isempty(nii.hdr.hist.flip_orient)
30
+      flip_orient = nii.hdr.hist.flip_orient(unrotate_orient);
31
+
32
+      for i = 1:3
33
+         if flip_orient(i)
34
+            outblock = flipdim(outblock, i);
35
+         end
36
+      end
37
+   end;
38
+
39
+   return;
40
+
... ...
@@ -0,0 +1,45 @@
1
+%  Verify NIFTI header extension to make sure that each extension section
2
+%  must be an integer multiple of 16 byte long that includes the first 8
3
+%  bytes of esize and ecode. If the length of extension section is not the
4
+%  above mentioned case, edata should be padded with all 0.
5
+%
6
+%  Usage: [ext, esize_total] = verify_nii_ext(ext)
7
+%
8
+%  ext - Structure of NIFTI header extension, which includes num_ext,
9
+%       and all the extended header sections in the header extension.
10
+%       Each extended header section will have its esize, ecode, and
11
+%       edata, where edata can be plain text, xml, or any raw data
12
+%       that was saved in the extended header section.
13
+%
14
+%  esize_total - Sum of all esize variable in all header sections.
15
+%
16
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
17
+%
18
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
19
+%
20
+function [ext, esize_total] = verify_nii_ext(ext)
21
+
22
+   if ~isfield(ext, 'section')
23
+      error('Incorrect NIFTI header extension structure.');
24
+   elseif ~isfield(ext, 'num_ext')
25
+      ext.num_ext = length(ext.section);
26
+   elseif ~isfield(ext, 'extension')
27
+      ext.extension = [1 0 0 0];
28
+   end
29
+
30
+   esize_total = 0;
31
+
32
+   for i=1:ext.num_ext
33
+      if ~isfield(ext.section(i), 'ecode') | ~isfield(ext.section(i), 'edata')
34
+         error('Incorrect NIFTI header extension structure.');
35
+      end
36
+
37
+      ext.section(i).esize = ceil((length(ext.section(i).edata)+8)/16)*16;
38
+      ext.section(i).edata = ...
39
+	[ext.section(i).edata ...
40
+	 zeros(1,ext.section(i).esize-length(ext.section(i).edata)-8)];
41
+      esize_total = esize_total + ext.section(i).esize;
42
+   end
43
+
44
+   return                                       % verify_nii_ext
45
+
... ...
@@ -0,0 +1,4847 @@
1
+%  VIEW_NII: Create or update a 3-View (Front, Top, Side) of the 
2
+%	brain data that is specified by nii structure
3
+%
4
+%  Usage:  	status = view_nii([h], nii, [option])	or
5
+%		status = view_nii(h, [option])
6
+%
7
+%  Where, h is the figure on which the 3-View will be plotted;
8
+%	nii is the brain data in NIFTI format;
9
+%	option is a struct that configures the view plotted, can be:
10
+%
11
+%		option.command = 'init'
12
+%		option.command = 'update'
13
+%		option.command = 'clearnii'
14
+%		option.command = 'updatenii'
15
+%		option.command = 'updateimg' (nii is nii.img here)
16
+%
17
+%		option.usecolorbar = 0 | [1]
18
+%		option.usepanel = 0 | [1]
19
+%		option.usecrosshair = 0 | [1]
20
+%		option.usestretch = 0 | [1]
21
+%		option.useimagesc = 0 | [1]
22
+%		option.useinterp = [0] | 1
23
+%
24
+%		option.setarea = [x y w h] | [0.05 0.05 0.9 0.9]
25
+%		option.setunit = ['vox'] | 'mm'
26
+%		option.setviewpoint = [x y z] | [origin]
27
+%		option.setscanid = [t] | [1]
28
+%		option.setcrosshaircolor = [r g b] | [1 0 0]
29
+%		option.setcolorindex = From 1 to 9 (default is 2 or 3)
30
+%		option.setcolormap = (Mx3 matrix, 0 <= val <= 1)
31
+%		option.setcolorlevel = No more than 256 (default 256)
32
+%		option.sethighcolor = []
33
+%		option.setcbarminmax = []
34
+%		option.setvalue = []
35
+%		option.glblocminmax = []
36
+%		option.setbuttondown = ''
37
+%		option.setcomplex = [0] | 1 | 2
38
+%
39
+%	Options description in detail:
40
+%	==============================
41
+%
42
+%	1. command: A char string that can control program.
43
+%
44
+%		init: If option.command='init', the program will display
45
+%			a 3-View plot on the figure specified by figure h
46
+%			or on a new figure. If there is already a 3-View
47
+%			plot on the figure, please use option.command = 
48
+%			'updatenii' (see detail below); otherwise, the
49
+%			new 3-View plot will superimpose on the old one.
50
+%			If there is no option provided, the program will
51
+%			assume that this is an initial plot. If the figure
52
+%			handle is omitted, the program knows that it is
53
+%			an initial plot.
54
+%
55
+%		update: If there is no command specified, and a figure
56
+%			handle of the existing 3-View plot is provided,
57
+%			the program will choose option.command='update'
58
+%			to update the 3-View plot with some new option 
59
+%			items.
60
+%
61
+%		clearnii: Clear 3-View plot on specific figure
62
+%
63
+%		updatenii: If a new nii is going to be loaded on a fig
64
+%			that has already 3-View plot on it, use this
65
+%			command to clear existing 3-View plot, and then
66
+%			display with new nii. So, the new nii will not
67
+%			superimpose on the existing one. All options
68
+%			for 'init' can be used for 'updatenii'.
69
+%
70
+%		updateimg: If a new 3D matrix with the same dimension
71
+%			is going to be loaded, option.command='updateimg'
72
+%			can be used as a light-weighted 'updatenii, since
73
+%			it only updates the 3 slices with new values.
74
+%			inputing argument nii should be a 3D matrix
75
+%			(nii.img) instead of nii struct. No other option
76
+%			should be used together with 'updateimg' to keep
77
+%			this command as simple as possible.
78
+%
79
+%
80
+%	2. usecolorbar: If specified and usecolorbar=0, the program
81
+%		will not include the colorbar in plot area; otherwise,
82
+%		a colorbar will be included in plot area.
83
+%
84
+%	3. usepanel: If specified and usepanel=0, the control panel
85
+%		at lower right cornor will be invisible; otherwise,
86
+%		it will be visible.
87
+%
88
+%	4. usecrosshair: If specified and usecrosshair=0, the crosshair
89
+%		will be invisible; otherwise, it will be visible.
90
+%
91
+%	5. usestretch: If specified and usestretch=0, the 3 slices will
92
+%		not be stretched, and will be displayed according to
93
+%		the actual voxel size; otherwise, the 3 slices will be 
94
+%		stretched to the edge.
95
+%
96
+%	6. useimagesc: If specified and useimagesc=0, images data will
97
+%		be used directly to match the colormap (like 'image'
98
+%		command); otherwise, image data will be scaled to full
99
+%		colormap with 'imagesc' command in Matlab.
100
+%
101
+%	7. useinterp: If specified and useinterp=1, the image will be
102
+%		displayed using interpolation. Otherwise, it will be
103
+%		displayed like mosaic, and each tile stands for a
104
+%		pixel. This option does not apply to 'setvalue' option
105
+%		is set.
106
+%
107
+%
108
+%	8. setarea: 3-View plot will be displayed on this specific 
109
+%		region. If it is not specified, program will set the
110
+%		plot area to [0.05 0.05 0.9 0.9].
111
+%
112
+%	9. setunit: It can be specified to setunit='voxel' or 'mm'
113
+%		and the view will change the axes unit of [X Y Z]
114
+%		accordingly.
115
+%
116
+%	10. setviewpoint: If specified, [X Y Z] values will be used
117
+%		to set the viewpoint of 3-View plot.
118
+%
119
+%	11. setscanid: If specified, [t] value will be used to display
120
+%		the specified image scan in NIFTI data.
121
+%
122
+%	12. setcrosshaircolor: If specified, [r g b] value will be used
123
+%		for Crosshair Color. Otherwise, red will be the default.
124
+%
125
+%	13. setcolorindex: If specified, the 3-View will choose the
126
+%		following colormap:  2 - Bipolar; 3 - Gray; 4 - Jet;
127
+%		5 - Cool; 6 - Bone; 7 - Hot; 8 - Copper; 9 - Pink;
128
+%		If not specified, it will choose 3 - Gray if all data
129
+%		values are not less than 0; otherwise, it will choose
130
+%		2 - Bipolar if there is value less than 0. (Contrast
131
+%		control can only apply to 3 - Gray colormap.
132
+%
133
+%	14. setcolormap: 3-View plot will use it as a customized colormap.
134
+%		It is a 3-column matrix with value between 0 and 1. If
135
+%		using MS-Windows version of Matlab, the number of rows
136
+%		can not be more than 256, because of Matlab limitation.
137
+%		When colormap is used, setcolorlevel option will be
138
+%		disabled automatically.
139
+%
140
+%	15. setcolorlevel: If specified (must be no more than 256, and
141
+%		cannot be used for customized colormap), row number of
142
+%		colormap will be squeezed down to this level; otherwise,
143
+%		it will assume that setcolorlevel=256.
144
+%
145
+%	16. sethighcolor: If specified, program will squeeze down the
146
+%		colormap, and allocate sethighcolor (an Mx3 matrix)
147
+%		to high-end portion of the colormap. The sum of M and
148
+%		setcolorlevel should be less than 256. If setcolormap
149
+%		option is used, sethighcolor will be inserted on top 
150
+%		of the setcolormap, and the setcolorlevel option will
151
+%		be disabled automatically.
152
+%
153
+%	17. setcbarminmax: if specified, the [min max] will be used to
154
+%		set the min and max of the colorbar, which does not
155
+%		include any data for highcolor.
156
+%
157
+%	18. setvalue: If specified, setvalue.val (with the same size as
158
+%		the source data on solution points) in the source area
159
+%		setvalue.idx will be superimposed on the current nii 
160
+%		image. So, the size of setvalue.val should be equal to
161
+%		the size of setvalue.idx. To use this feature, it needs
162
+%		single or double nii structure for background image.
163
+%
164
+%	19. glblocminmax: If specified, pgm will use glblocminmax to
165
+%		calculate the colormap, instead of minmax of image.
166
+%
167
+%	20. setbuttondown: If specified, pgm will evaluate the command
168
+%		after a click or slide action is invoked to the new
169
+%		view point.
170
+%
171
+%	21. setcomplex: This option will decide how complex data to be
172
+%		displayed:  0 - Real part of complex data; 1 - Imaginary
173
+%		part of complex data; 2 - Modulus (magnitude) of complex
174
+%		data;  If not specified, it will be set to 0 (Real part
175
+%		of complex data as default option. This option only apply
176
+%		when option.command is set to 'init or 'updatenii'.
177
+%
178
+%
179
+%	Additional Options for 'update' command:
180
+%	=======================================
181
+%
182
+%		option.enablecursormove = [1] | 0
183
+%		option.enableviewpoint = 0 | [1]
184
+%		option.enableorigin = 0 | [1]
185
+%		option.enableunit = 0 | [1]
186
+%		option.enablecrosshair = 0 | [1]
187
+%		option.enablehistogram = 0 | [1]
188
+%		option.enablecolormap = 0 | [1]
189
+%		option.enablecontrast = 0 | [1]
190
+%		option.enablebrightness = 0 | [1]
191
+%		option.enableslider = 0 | [1]
192
+%		option.enabledirlabel = 0 | [1]
193
+%
194
+%
195
+%  e.g.:
196
+%	nii = load_nii('T1');		% T1.img/hdr
197
+%	view_nii(nii);
198
+%
199
+%	or
200
+%
201
+%	h = figure('unit','normal','pos', [0.18 0.08 0.64 0.85]);
202
+%	opt.setarea = [0.05 0.05 0.9 0.9];
203
+%	view_nii(h, nii, opt);
204
+%
205
+%
206
+%  Part of this file is copied and modified under GNU license from
207
+%  MRI_TOOLBOX developed by CNSP in Flinders University, Australia
208
+%
209
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
210
+%
211
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
212
+%
213
+function status = view_nii(varargin)
214
+
215
+   if nargin < 1
216
+      error('Please check inputs using ''help view_nii''');
217
+   end;
218
+
219
+   nii = '';
220
+   opt = '';
221
+   command = '';
222
+
223
+   usecolorbar = [];
224
+   usepanel = [];
225
+   usecrosshair = '';
226
+   usestretch = [];
227
+   useimagesc = [];
228
+   useinterp = [];
229
+
230
+   setarea = [];
231
+   setunit = '';
232
+   setviewpoint = [];
233
+   setscanid = [];
234
+   setcrosshaircolor = [];
235
+   setcolorindex = '';
236
+   setcolormap = 'NA';
237
+   setcolorlevel = [];
238
+   sethighcolor = 'NA';
239
+   setcbarminmax = [];
240
+   setvalue = [];
241
+   glblocminmax = [];
242
+   setbuttondown = '';
243
+   setcomplex = 0;
244
+
245
+   status = [];
246
+
247
+   if ishandle(varargin{1})		% plot on top of this figure
248
+
249
+      fig = varargin{1};
250
+
251
+      if nargin < 2
252
+         command = 'update';		% just to get 3-View status
253
+      end
254
+
255
+      if nargin == 2
256
+         if ~isstruct(varargin{2})
257
+            error('2nd parameter should be either nii struct or option struct');
258
+         end
259
+
260
+         opt = varargin{2};
261
+
262
+         if isfield(opt,'hdr') & isfield(opt,'img')
263
+            nii = opt;
264
+         elseif isfield(opt, 'command') & (strcmpi(opt.command,'init') ...
265
+		| strcmpi(opt.command,'updatenii') ...
266
+		| strcmpi(opt.command,'updateimg') )
267
+
268
+            error('Option here cannot contain "init", "updatenii", or "updateimg" comand');
269
+         end
270
+      end
271
+
272
+      if nargin == 3
273
+         nii = varargin{2};
274
+         opt = varargin{3};
275
+
276
+         if ~isstruct(opt)
277
+            error('3rd parameter should be option struct');
278
+         end
279
+
280
+         if ~isfield(opt,'command') | ~strcmpi(opt.command,'updateimg')
281
+            if ~isstruct(nii) | ~isfield(nii,'hdr') | ~isfield(nii,'img')
282
+               error('2nd parameter should be nii struct');
283
+            end
284
+
285
+            if isfield(nii,'untouch') & nii.untouch == 1
286
+               error('Usage: please use ''load_nii.m'' to load the structure.');
287
+            end
288
+         end
289
+      end
290
+
291
+      set(fig, 'menubar', 'none');
292
+
293
+   elseif ischar(varargin{1})		% call back by event
294
+
295
+      command = lower(varargin{1});
296
+      fig = gcbf;
297
+
298
+   else					% start nii with a new figure
299
+
300
+      nii = varargin{1};
301
+
302
+      if ~isstruct(nii) | ~isfield(nii,'hdr') | ~isfield(nii,'img')
303
+         error('1st parameter should be either a figure handle or nii struct');
304
+      end
305
+
306
+      if isfield(nii,'untouch') & nii.untouch == 1
307
+         error('Usage: please use ''load_nii.m'' to load the structure.');
308
+      end
309
+
310
+      if nargin > 1
311
+         opt = varargin{2};
312
+
313
+         if isfield(opt, 'command') & ~strcmpi(opt.command,'init')
314
+            error('Option here must use "init" comand');
315
+         end
316
+      end
317
+
318
+      command = 'init';
319
+      fig = figure('unit','normal','position',[0.15 0.08 0.70 0.85]);
320
+      view_nii_menu(fig);
321
+      rri_file_menu(fig);
322
+
323
+   end
324
+
325
+   if ~isempty(opt)
326
+
327
+      if isfield(opt,'command')
328
+         command = lower(opt.command);
329
+      end
330
+
331
+      if isempty(command)
332
+         command = 'update';
333
+      end
334
+
335
+      if isfield(opt,'usecolorbar')
336
+         usecolorbar = opt.usecolorbar;
337
+      end
338
+
339
+      if isfield(opt,'usepanel')
340
+         usepanel = opt.usepanel;
341
+      end
342
+
343
+      if isfield(opt,'usecrosshair')
344
+         usecrosshair = opt.usecrosshair;
345
+      end
346
+
347
+      if isfield(opt,'usestretch')
348
+         usestretch = opt.usestretch;
349
+      end
350
+
351
+      if isfield(opt,'useimagesc')
352
+         useimagesc = opt.useimagesc;
353
+      end
354
+
355
+      if isfield(opt,'useinterp')
356
+         useinterp = opt.useinterp;
357
+      end
358
+
359
+      if isfield(opt,'setarea')
360
+         setarea = opt.setarea;
361
+      end
362
+
363
+      if isfield(opt,'setunit')
364
+         setunit = opt.setunit;
365
+      end
366
+
367
+      if isfield(opt,'setviewpoint')
368
+         setviewpoint = opt.setviewpoint;
369
+      end
370
+
371
+      if isfield(opt,'setscanid')
372
+         setscanid = opt.setscanid;
373
+      end
374
+
375
+      if isfield(opt,'setcrosshaircolor')
376
+         setcrosshaircolor = opt.setcrosshaircolor;
377
+
378
+         if ~isempty(setcrosshaircolor) & (~isnumeric(setcrosshaircolor) | ~isequal(size(setcrosshaircolor),[1 3]) | min(setcrosshaircolor(:))<0 | max(setcrosshaircolor(:))>1)
379
+            error('Crosshair Color should be a 1x3 matrix with value between 0 and 1');
380
+         end
381
+      end
382
+
383
+      if isfield(opt,'setcolorindex')
384
+         setcolorindex = round(opt.setcolorindex);
385
+
386
+         if ~isnumeric(setcolorindex) | setcolorindex < 1 | setcolorindex > 9
387
+            error('Colorindex should be a number between 1 and 9');
388
+         end
389
+      end
390
+
391
+      if isfield(opt,'setcolormap')
392
+         setcolormap = opt.setcolormap;
393
+
394
+         if ~isempty(setcolormap) & (~isnumeric(setcolormap) | size(setcolormap,2) ~= 3 | min(setcolormap(:))<0 | max(setcolormap(:))>1)
395
+            error('Colormap should be a Mx3 matrix with value between 0 and 1');
396
+         end
397
+      end
398
+
399
+      if isfield(opt,'setcolorlevel')
400
+         setcolorlevel = round(opt.setcolorlevel);
401
+
402
+         if ~isnumeric(setcolorlevel) | setcolorlevel > 256 | setcolorlevel < 1
403
+            error('Colorlevel should be a number between 1 and 256');
404
+         end
405
+      end
406
+
407
+      if isfield(opt,'sethighcolor')
408
+         sethighcolor = opt.sethighcolor;
409
+
410
+         if ~isempty(sethighcolor) & (~isnumeric(sethighcolor) | size(sethighcolor,2) ~= 3 | min(sethighcolor(:))<0 | max(sethighcolor(:))>1)
411
+            error('Highcolor should be a Mx3 matrix with value between 0 and 1');
412
+         end
413
+      end
414
+
415
+      if isfield(opt,'setcbarminmax')
416
+         setcbarminmax = opt.setcbarminmax;
417
+
418
+         if isempty(setcbarminmax) | ~isnumeric(setcbarminmax) | length(setcbarminmax) ~= 2
419
+            error('Colorbar MinMax should contain 2 values: [min max]');
420
+         end
421
+      end
422
+
423
+      if isfield(opt,'setvalue')
424
+         setvalue = opt.setvalue;
425
+
426
+         if isempty(setvalue) | ~isstruct(setvalue) | ...
427
+		~isfield(opt.setvalue,'idx') | ~isfield(opt.setvalue,'val')
428
+            error('setvalue should be a struct contains idx and val');
429
+         end
430
+
431
+         if length(opt.setvalue.idx(:)) ~= length(opt.setvalue.val(:))
432
+            error('length of idx and val fields should be the same');
433
+         end
434
+
435
+         if ~strcmpi(class(opt.setvalue.idx),'single')
436
+            opt.setvalue.idx = single(opt.setvalue.idx);
437
+         end
438
+
439
+         if ~strcmpi(class(opt.setvalue.val),'single')
440
+            opt.setvalue.val = single(opt.setvalue.val);
441
+         end
442
+      end
443
+
444
+      if isfield(opt,'glblocminmax')
445
+         glblocminmax = opt.glblocminmax;
446
+      end
447
+
448
+      if isfield(opt,'setbuttondown')
449
+         setbuttondown = opt.setbuttondown;
450
+      end
451
+
452
+      if isfield(opt,'setcomplex')
453
+         setcomplex = opt.setcomplex;
454
+      end
455
+
456
+   end
457
+
458
+   switch command
459
+
460
+   case {'init'}
461
+
462
+      set(fig, 'InvertHardcopy','off');
463
+      set(fig, 'PaperPositionMode','auto');
464
+
465
+      fig = init(nii, fig, setarea, setunit, setviewpoint, setscanid, setbuttondown, ...
466
+         setcolorindex, setcolormap, setcolorlevel, sethighcolor, setcbarminmax, ...
467
+         usecolorbar, usepanel, usecrosshair, usestretch, useimagesc, useinterp, ...
468
+         setvalue, glblocminmax, setcrosshaircolor, setcomplex);
469
+
470
+      %  get status
471
+      %
472
+      status = get_status(fig);
473
+
474
+   case {'update'}
475
+
476
+      nii_view = getappdata(fig,'nii_view');
477
+      h = fig;
478
+
479
+      if isempty(nii_view)
480
+         error('The figure should already contain a 3-View plot.');
481
+      end
482
+
483
+      if ~isempty(opt)
484
+
485
+         %  Order of the following update matters.
486
+         %
487
+         update_shape(h, setarea, usecolorbar, usestretch, useimagesc);
488
+         update_useinterp(h, useinterp);
489
+         update_useimagesc(h, useimagesc);
490
+         update_usepanel(h, usepanel);
491
+         update_colorindex(h, setcolorindex);
492
+         update_colormap(h, setcolormap);
493
+         update_highcolor(h, sethighcolor, setcolorlevel);
494
+         update_cbarminmax(h, setcbarminmax);
495
+         update_unit(h, setunit);
496
+         update_viewpoint(h, setviewpoint);
497
+         update_scanid(h, setscanid);
498
+         update_buttondown(h, setbuttondown);
499
+         update_crosshaircolor(h, setcrosshaircolor);
500
+         update_usecrosshair(h, usecrosshair);
501
+
502
+         %  Enable/Disable object
503
+         %
504
+         update_enable(h, opt);
505
+
506
+      end
507
+
508
+      %  get status
509
+      %
510
+      status = get_status(h);
511
+
512
+   case {'updateimg'}
513
+
514
+      if ~exist('nii','var')
515
+         msg = sprintf('Please input a 3D matrix brain data');
516
+         error(msg);
517
+      end
518
+
519
+      %  Note: nii is not nii, nii should be a 3D matrix here
520
+      %
521
+      if ~isnumeric(nii)
522
+         msg = sprintf('2nd parameter should be a 3D matrix, not nii struct');
523
+         error(msg);
524
+      end
525
+
526
+      nii_view = getappdata(fig,'nii_view');
527
+
528
+      if isempty(nii_view)
529
+         error('The figure should already contain a 3-View plot.');
530
+      end
531
+
532
+      img = nii;
533
+      update_img(img, fig, opt);
534
+
535
+      %  get status
536
+      %
537
+      status = get_status(fig);
538
+
539
+   case {'updatenii'}
540
+
541
+      nii_view = getappdata(fig,'nii_view');
542
+
543
+      if isempty(nii_view)
544
+         error('The figure should already contain a 3-View plot.');
545
+      end
546
+
547
+      if ~isstruct(nii) | ~isfield(nii,'hdr') | ~isfield(nii,'img')
548
+         error('2nd parameter should be nii struct');
549
+      end
550
+
551
+      if isfield(nii,'untouch') & nii.untouch == 1
552
+         error('Usage: please use ''load_nii.m'' to load the structure.');
553
+      end
554
+
555
+      opt.command = 'clearnii';
556
+      view_nii(fig, opt);
557
+
558
+      opt.command = 'init';
559
+      view_nii(fig, nii, opt);
560
+
561
+      %  get status
562
+      %
563
+      status = get_status(fig);
564
+
565
+   case {'clearnii'}
566
+
567
+      nii_view = getappdata(fig,'nii_view');
568
+
569
+      handles = struct2cell(nii_view.handles);
570
+
571
+      for i=1:length(handles)
572
+         if ishandle(handles{i})	% in case already del by parent
573
+            delete(handles{i});
574
+         end
575
+      end
576
+
577
+      rmappdata(fig,'nii_view');
578
+      buttonmotion = get(fig,'windowbuttonmotion');
579
+      mymotion = '; view_nii(''move_cursor'');';
580
+      buttonmotion = strrep(buttonmotion, mymotion, '');
581
+      set(fig, 'windowbuttonmotion', buttonmotion);
582
+
583
+   case {'axial_image','coronal_image','sagittal_image'}    
584
+
585
+      switch command
586
+         case 'axial_image',    view = 'axi'; axi = 0; cor = 1; sag = 1;
587
+         case 'coronal_image',  view = 'cor'; axi = 1; cor = 0; sag = 1;
588
+         case 'sagittal_image', view = 'sag'; axi = 1; cor = 1; sag = 0;
589
+      end
590
+
591
+      nii_view = getappdata(fig,'nii_view');
592
+      nii_view = get_slice_position(nii_view,view);
593
+
594
+      if isfield(nii_view, 'disp')
595
+         img = nii_view.disp;
596
+      else
597
+         img = nii_view.nii.img;
598
+      end
599
+
600
+      %  CData must be double() for Matlab 6.5 for Windows
601
+      %
602
+      if axi,
603
+         if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg) & nii_view.useinterp
604
+            Saxi = squeeze(nii_view.bgimg(:,:,nii_view.slices.axi));
605
+            set(nii_view.handles.axial_bg,'CData',Saxi');
606
+         end
607
+
608
+         if isfield(nii_view.handles,'axial_image'),
609
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
610
+               Saxi = squeeze(img(:,:,nii_view.slices.axi,:,nii_view.scanid));
611
+               Saxi = permute(Saxi, [2 1 3]);
612
+            else
613
+               Saxi = squeeze(img(:,:,nii_view.slices.axi,nii_view.scanid));
614
+               Saxi = Saxi';
615
+            end
616
+
617
+            set(nii_view.handles.axial_image,'CData',Saxi);
618
+         end
619
+
620
+         if isfield(nii_view.handles,'axial_slider'),
621
+            set(nii_view.handles.axial_slider,'Value',nii_view.slices.axi);
622
+         end;
623
+       end
624
+
625
+       if cor,
626
+         if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg) & nii_view.useinterp
627
+            Scor = squeeze(nii_view.bgimg(:,nii_view.slices.cor,:));
628
+            set(nii_view.handles.coronal_bg,'CData',Scor');
629
+         end
630
+
631
+         if isfield(nii_view.handles,'coronal_image'),
632
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
633
+               Scor = squeeze(img(:,nii_view.slices.cor,:,:,nii_view.scanid));
634
+               Scor = permute(Scor, [2 1 3]);
635
+            else
636
+               Scor = squeeze(img(:,nii_view.slices.cor,:,nii_view.scanid));
637
+               Scor = Scor';
638
+            end
639
+
640
+            set(nii_view.handles.coronal_image,'CData',Scor);
641
+         end
642
+
643
+         if isfield(nii_view.handles,'coronal_slider'),
644
+            slider_val = nii_view.dims(2) - nii_view.slices.cor + 1;
645
+            set(nii_view.handles.coronal_slider,'Value',slider_val);
646
+         end;
647
+      end;
648
+
649
+      if sag,
650
+         if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg) & nii_view.useinterp
651
+            Ssag = squeeze(nii_view.bgimg(nii_view.slices.sag,:,:));
652
+            set(nii_view.handles.sagittal_bg,'CData',Ssag');
653
+         end
654
+
655
+         if isfield(nii_view.handles,'sagittal_image'),
656
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
657
+               Ssag = squeeze(img(nii_view.slices.sag,:,:,:,nii_view.scanid));
658
+               Ssag = permute(Ssag, [2 1 3]);
659
+            else
660
+               Ssag = squeeze(img(nii_view.slices.sag,:,:,nii_view.scanid));
661
+               Ssag = Ssag';
662
+            end
663
+
664
+            set(nii_view.handles.sagittal_image,'CData',Ssag);
665
+         end
666
+
667
+         if isfield(nii_view.handles,'sagittal_slider'),
668
+            set(nii_view.handles.sagittal_slider,'Value',nii_view.slices.sag);
669
+         end;
670
+      end;
671
+
672
+      update_nii_view(nii_view);
673
+
674
+      if ~isempty(nii_view.buttondown)
675
+         eval(nii_view.buttondown);
676
+      end
677
+    
678
+   case {'axial_slider','coronal_slider','sagittal_slider'},
679
+    
680
+      switch command
681
+         case 'axial_slider',    view = 'axi'; axi = 1; cor = 0; sag = 0;
682
+         case 'coronal_slider',  view = 'cor'; axi = 0; cor = 1; sag = 0;
683
+         case 'sagittal_slider', view = 'sag'; axi = 0; cor = 0; sag = 1;
684
+      end
685
+
686
+      nii_view = getappdata(fig,'nii_view');
687
+      nii_view = get_slider_position(nii_view);
688
+
689
+      if isfield(nii_view, 'disp')
690
+         img = nii_view.disp;
691
+      else
692
+         img = nii_view.nii.img;
693
+      end
694
+
695
+      if axi,
696
+         if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg) & nii_view.useinterp
697
+            Saxi = squeeze(nii_view.bgimg(:,:,nii_view.slices.axi));
698
+            set(nii_view.handles.axial_bg,'CData',Saxi');
699
+         end
700
+
701
+         if isfield(nii_view.handles,'axial_image'),
702
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
703
+               Saxi = squeeze(img(:,:,nii_view.slices.axi,:,nii_view.scanid));
704
+               Saxi = permute(Saxi, [2 1 3]);
705
+            else
706
+               Saxi = squeeze(img(:,:,nii_view.slices.axi,nii_view.scanid));
707
+               Saxi = Saxi';
708
+            end
709
+
710
+            set(nii_view.handles.axial_image,'CData',Saxi);
711
+         end
712
+
713
+         if isfield(nii_view.handles,'axial_slider'),
714
+            set(nii_view.handles.axial_slider,'Value',nii_view.slices.axi);
715
+         end
716
+      end
717
+
718
+      if cor,
719
+         if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg) & nii_view.useinterp
720
+            Scor = squeeze(nii_view.bgimg(:,nii_view.slices.cor,:));
721
+            set(nii_view.handles.coronal_bg,'CData',Scor');
722
+         end
723
+
724
+         if isfield(nii_view.handles,'coronal_image'),
725
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
726
+               Scor = squeeze(img(:,nii_view.slices.cor,:,:,nii_view.scanid));
727
+               Scor = permute(Scor, [2 1 3]);
728
+            else
729
+               Scor = squeeze(img(:,nii_view.slices.cor,:,nii_view.scanid));
730
+               Scor = Scor';
731
+            end
732
+
733
+            set(nii_view.handles.coronal_image,'CData',Scor);
734
+         end
735
+
736
+         if isfield(nii_view.handles,'coronal_slider'),
737
+            slider_val = nii_view.dims(2) - nii_view.slices.cor + 1;
738
+            set(nii_view.handles.coronal_slider,'Value',slider_val);
739
+         end
740
+      end    
741
+
742
+      if sag,
743
+         if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg) & nii_view.useinterp
744
+            Ssag = squeeze(nii_view.bgimg(nii_view.slices.sag,:,:));
745
+            set(nii_view.handles.sagittal_bg,'CData',Ssag');
746
+         end
747
+
748
+         if isfield(nii_view.handles,'sagittal_image'),
749
+            if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
750
+               Ssag = squeeze(img(nii_view.slices.sag,:,:,:,nii_view.scanid));
751
+               Ssag = permute(Ssag, [2 1 3]);
752
+            else
753
+               Ssag = squeeze(img(nii_view.slices.sag,:,:,nii_view.scanid));
754
+               Ssag = Ssag';
755
+            end
756
+
757
+            set(nii_view.handles.sagittal_image,'CData',Ssag);
758
+         end
759
+
760
+         if isfield(nii_view.handles,'sagittal_slider'),
761
+            set(nii_view.handles.sagittal_slider,'Value',nii_view.slices.sag);
762
+         end
763
+      end
764
+
765
+      update_nii_view(nii_view);
766
+
767
+      if ~isempty(nii_view.buttondown)
768
+         eval(nii_view.buttondown);
769
+      end
770
+
771
+   case {'impos_edit'}
772
+
773
+      nii_view = getappdata(fig,'nii_view');
774
+      impos = str2num(get(nii_view.handles.impos,'string'));
775
+
776
+      if isfield(nii_view, 'disp')
777
+         img = nii_view.disp;
778
+      else
779
+         img = nii_view.nii.img;
780
+      end
781
+
782
+      if isempty(impos) | ~all(size(impos) ==  [1 3])
783
+         msg = 'Please use 3 numbers to represent X,Y and Z';
784
+         msgbox(msg,'Error');
785
+         return;
786
+      end
787
+
788
+      slices.sag = round(impos(1));
789
+      slices.cor = round(impos(2));
790
+      slices.axi = round(impos(3));
791
+
792
+      nii_view = convert2voxel(nii_view,slices);
793
+      nii_view = check_slices(nii_view);
794
+
795
+      impos(1) = nii_view.slices.sag;
796
+      impos(2) = nii_view.dims(2) - nii_view.slices.cor + 1;
797
+      impos(3) = nii_view.slices.axi;
798
+
799
+      if isfield(nii_view.handles,'sagittal_slider'),
800
+         set(nii_view.handles.sagittal_slider,'Value',impos(1));
801
+      end
802
+
803
+      if isfield(nii_view.handles,'coronal_slider'),
804
+         set(nii_view.handles.coronal_slider,'Value',impos(2));
805
+      end
806
+
807
+      if isfield(nii_view.handles,'axial_slider'),
808
+         set(nii_view.handles.axial_slider,'Value',impos(3));
809
+      end
810
+
811
+      nii_view = get_slider_position(nii_view);
812
+      update_nii_view(nii_view);
813
+
814
+      if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg) & nii_view.useinterp
815
+         Saxi = squeeze(nii_view.bgimg(:,:,nii_view.slices.axi));
816
+         set(nii_view.handles.axial_bg,'CData',Saxi');
817
+      end
818
+
819
+      if isfield(nii_view.handles,'axial_image'),
820
+         if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
821
+            Saxi = squeeze(img(:,:,nii_view.slices.axi,:,nii_view.scanid));
822
+            Saxi = permute(Saxi, [2 1 3]);
823
+         else
824
+            Saxi = squeeze(img(:,:,nii_view.slices.axi,nii_view.scanid));
825
+            Saxi = Saxi';
826
+         end
827
+
828
+         set(nii_view.handles.axial_image,'CData',Saxi);
829
+      end
830
+
831
+      if isfield(nii_view.handles,'axial_slider'),
832
+         set(nii_view.handles.axial_slider,'Value',nii_view.slices.axi);
833
+      end
834
+
835
+      if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg) & nii_view.useinterp
836
+         Scor = squeeze(nii_view.bgimg(:,nii_view.slices.cor,:));
837
+         set(nii_view.handles.coronal_bg,'CData',Scor');
838
+      end
839
+
840
+      if isfield(nii_view.handles,'coronal_image'),
841
+         if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
842
+            Scor = squeeze(img(:,nii_view.slices.cor,:,:,nii_view.scanid));
843
+            Scor = permute(Scor, [2 1 3]);
844
+         else
845
+            Scor = squeeze(img(:,nii_view.slices.cor,:,nii_view.scanid));
846
+            Scor = Scor';
847
+         end
848
+
849
+         set(nii_view.handles.coronal_image,'CData',Scor);
850
+      end
851
+
852
+      if isfield(nii_view.handles,'coronal_slider'),
853
+         slider_val = nii_view.dims(2) - nii_view.slices.cor + 1;
854
+         set(nii_view.handles.coronal_slider,'Value',slider_val);
855
+      end
856
+
857
+      if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg) & nii_view.useinterp
858
+         Ssag = squeeze(nii_view.bgimg(nii_view.slices.sag,:,:));
859
+         set(nii_view.handles.sagittal_bg,'CData',Ssag');
860
+      end
861
+
862
+      if isfield(nii_view.handles,'sagittal_image'),
863
+         if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
864
+            Ssag = squeeze(img(nii_view.slices.sag,:,:,:,nii_view.scanid));
865
+            Ssag = permute(Ssag, [2 1 3]);
866
+         else
867
+            Ssag = squeeze(img(nii_view.slices.sag,:,:,nii_view.scanid));
868
+            Ssag = Ssag';
869
+         end
870
+
871
+         set(nii_view.handles.sagittal_image,'CData',Ssag);
872
+      end
873
+
874
+      if isfield(nii_view.handles,'sagittal_slider'),
875
+         set(nii_view.handles.sagittal_slider,'Value',nii_view.slices.sag);
876
+      end
877
+
878
+      axes(nii_view.handles.axial_axes);
879
+      axes(nii_view.handles.coronal_axes);
880
+      axes(nii_view.handles.sagittal_axes);
881
+
882
+      if ~isempty(nii_view.buttondown)
883
+         eval(nii_view.buttondown);
884
+      end
885
+
886
+   case 'coordinates',
887
+
888
+      nii_view = getappdata(fig,'nii_view');
889
+      set_image_value(nii_view);
890
+
891
+   case 'crosshair',
892
+
893
+      nii_view = getappdata(fig,'nii_view');
894
+
895
+      if get(nii_view.handles.xhair,'value') == 2		% off
896
+         set(nii_view.axi_xhair.lx,'visible','off');
897
+         set(nii_view.axi_xhair.ly,'visible','off');
898
+         set(nii_view.cor_xhair.lx,'visible','off');
899
+         set(nii_view.cor_xhair.ly,'visible','off');
900
+         set(nii_view.sag_xhair.lx,'visible','off');
901
+         set(nii_view.sag_xhair.ly,'visible','off');
902
+      else
903
+         set(nii_view.axi_xhair.lx,'visible','on');
904
+         set(nii_view.axi_xhair.ly,'visible','on');
905
+         set(nii_view.cor_xhair.lx,'visible','on');
906
+         set(nii_view.cor_xhair.ly,'visible','on');
907
+         set(nii_view.sag_xhair.lx,'visible','on');
908
+         set(nii_view.sag_xhair.ly,'visible','on');
909
+
910
+         set(nii_view.handles.axial_axes,'selected','on');
911
+         set(nii_view.handles.axial_axes,'selected','off');
912
+         set(nii_view.handles.coronal_axes,'selected','on');
913
+         set(nii_view.handles.coronal_axes,'selected','off');
914
+         set(nii_view.handles.sagittal_axes,'selected','on');
915
+         set(nii_view.handles.sagittal_axes,'selected','off');
916
+      end
917
+
918
+   case 'xhair_color',
919
+
920
+      old_color = get(gcbo,'user');
921
+      new_color = uisetcolor(old_color);
922
+      update_crosshaircolor(fig, new_color);
923
+
924
+   case {'color','contrast_def'}
925
+
926
+      nii_view = getappdata(fig,'nii_view');
927
+
928
+      if nii_view.numscan == 1
929
+         if get(nii_view.handles.colorindex,'value') == 2
930
+            set(nii_view.handles.contrast,'value',128);
931
+         elseif get(nii_view.handles.colorindex,'value') == 3
932
+            set(nii_view.handles.contrast,'value',1);
933
+         end
934
+      end
935
+
936
+      [custom_color_map, custom_colorindex] = change_colormap(fig);
937
+
938
+      if strcmpi(command, 'color')
939
+
940
+         setcolorlevel = nii_view.colorlevel;
941
+
942
+         if ~isempty(custom_color_map)		% isfield(nii_view, 'color_map')
943
+            setcolormap = custom_color_map;	% nii_view.color_map;
944
+         else
945
+            setcolormap = [];
946
+         end
947
+
948
+         if isfield(nii_view, 'highcolor')
949
+            sethighcolor = nii_view.highcolor;
950
+         else
951
+            sethighcolor = [];
952
+         end
953
+
954
+         redraw_cbar(fig, setcolorlevel, setcolormap, sethighcolor);
955
+
956
+         if nii_view.numscan == 1 & ...
957
+		(custom_colorindex < 2 | custom_colorindex > 3)
958
+            contrastopt.enablecontrast = 0;
959
+         else
960
+            contrastopt.enablecontrast = 1;
961
+         end
962
+
963
+         update_enable(fig, contrastopt);
964
+
965
+      end
966
+
967
+   case {'neg_color','brightness','contrast'}
968
+
969
+      change_colormap(fig);
970
+
971
+   case {'brightness_def'}
972
+
973
+      nii_view = getappdata(fig,'nii_view');
974
+      set(nii_view.handles.brightness,'value',0);
975
+      change_colormap(fig);
976
+
977
+   case 'hist_plot'
978
+
979
+      hist_plot(fig);
980
+
981
+   case 'hist_eq'
982
+
983
+      hist_eq(fig);
984
+
985
+   case 'move_cursor'
986
+
987
+      move_cursor(fig);
988
+
989
+   case 'edit_change_scan'
990
+
991
+      change_scan('edit_change_scan');
992
+
993
+   case 'slider_change_scan'
994
+
995
+      change_scan('slider_change_scan');
996
+
997
+   end
998
+
999
+   return;						% view_nii
1000
+
1001
+
1002
+%----------------------------------------------------------------
1003
+function fig = init(nii, fig, area, setunit, setviewpoint, setscanid, buttondown, ...
1004
+         colorindex, color_map, colorlevel, highcolor, cbarminmax, ...
1005
+         usecolorbar, usepanel, usecrosshair, usestretch, useimagesc, ...
1006
+         useinterp, setvalue, glblocminmax, setcrosshaircolor, ...
1007
+         setcomplex)
1008
+
1009
+   %  Support data type COMPLEX64 & COMPLEX128
1010
+   %
1011
+   if nii.hdr.dime.datatype == 32 | nii.hdr.dime.datatype == 1792
1012
+      switch setcomplex,
1013
+      case 0,
1014
+         nii.img = real(nii.img);
1015
+      case 1,
1016
+         nii.img = imag(nii.img);
1017
+      case 2,
1018
+         if isa(nii.img, 'double')
1019
+            nii.img = abs(double(nii.img));
1020
+         else
1021
+            nii.img = single(abs(double(nii.img)));
1022
+         end
1023
+      end
1024
+   end
1025
+
1026
+   if isempty(area)
1027
+      area = [0.05 0.05 0.9 0.9];
1028
+   end
1029
+
1030
+   if isempty(setscanid)
1031
+      setscanid = 1;
1032
+   else
1033
+      setscanid = round(setscanid);
1034
+
1035
+      if setscanid < 1
1036
+         setscanid = 1;
1037
+      end
1038
+
1039
+      if setscanid > nii.hdr.dime.dim(5)
1040
+         setscanid = nii.hdr.dime.dim(5);
1041
+      end
1042
+   end
1043
+
1044
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
1045
+      usecolorbar = 0;
1046
+   elseif isempty(usecolorbar)
1047
+      usecolorbar = 1;
1048
+   end
1049
+
1050
+   if isempty(usepanel)
1051
+      usepanel = 1;
1052
+   end
1053
+
1054
+   if isempty(usestretch)
1055
+      usestretch = 1;
1056
+   end
1057
+
1058
+   if isempty(useimagesc)
1059
+      useimagesc = 1;
1060
+   end
1061
+
1062
+   if isempty(useinterp)
1063
+      useinterp = 0;
1064
+   end
1065
+
1066
+   if isempty(colorindex)
1067
+      tmp = min(nii.img(:,:,:,setscanid));
1068
+
1069
+      if  min(tmp(:)) < 0
1070
+         colorindex = 2;
1071
+         setcrosshaircolor = [1 1 0];
1072
+      else
1073
+         colorindex = 3;
1074
+      end
1075
+   end
1076
+
1077
+   if isempty(color_map) | ischar(color_map)
1078
+      color_map = [];
1079
+   else
1080
+      colorindex = 1;
1081
+   end
1082
+
1083
+   bgimg = [];
1084
+
1085
+   if ~isempty(glblocminmax)
1086
+      minvalue = glblocminmax(1);
1087
+      maxvalue = glblocminmax(2);
1088
+   else
1089
+      minvalue = double(min(nii.img(:,:,:,setscanid)));
1090
+      minvalue = min(minvalue(:));
1091
+      maxvalue = double(max(nii.img(:,:,:,setscanid)));
1092
+      maxvalue = max(maxvalue(:));
1093
+   end
1094
+
1095
+   if ~isempty(setvalue)
1096
+      if ~isempty(glblocminmax)
1097
+         minvalue = glblocminmax(1);
1098
+         maxvalue = glblocminmax(2);
1099
+      else
1100
+         minvalue = double(min(setvalue.val));
1101
+         maxvalue = double(max(setvalue.val));
1102
+      end
1103
+
1104
+      bgimg = double(nii.img);
1105
+      minbg = double(min(bgimg(:)));
1106
+      maxbg = double(max(bgimg(:)));
1107
+
1108
+      bgimg = scale_in(bgimg, minbg, maxbg, 54) + 200;	% scale to 202~256 (level 201 is used for highcolor part tolerance)
1109
+
1110
+      %  55 level for brain structure (paded 0 for highcolor level 1, i.e. normal level 201, to make 56 highcolor)
1111
+      %
1112
+      highcolor = [zeros(1,3);gray(55)];
1113
+      cbarminmax = [minvalue maxvalue];
1114
+
1115
+      if useinterp
1116
+
1117
+         %  scale signal data to 1~200
1118
+         %
1119
+         nii.img = repmat(nan, size(nii.img));
1120
+         nii.img(setvalue.idx) = setvalue.val;
1121
+
1122
+         %  199 level for source image (map highest color to 199 instead of 200, give 1 level of tolerance)
1123
+         %
1124
+         bgimg = single(scale_out(bgimg, cbarminmax(1), cbarminmax(2), 198));
1125
+      else
1126
+
1127
+         bgimg(setvalue.idx) = 0;
1128
+
1129
+         %  scale signal data to 1~200
1130
+         %
1131
+         nii.img = zeros(size(nii.img));
1132
+         nii.img(setvalue.idx) = scale_in(setvalue.val, minvalue, maxvalue, 198);
1133
+         nii.img = nii.img + bgimg;
1134
+         bgimg = [];
1135
+         nii.img = scale_out(nii.img, cbarminmax(1), cbarminmax(2), 198);
1136
+
1137
+         minvalue = double(min(nii.img(:)));
1138
+         maxvalue = double(max(nii.img(:)));
1139
+
1140
+         if ~isempty(glblocminmax)		% maxvalue is gray
1141
+            minvalue = glblocminmax(1);
1142
+         end
1143
+
1144
+      end
1145
+
1146
+      colorindex = 2;
1147
+      setcrosshaircolor = [1 1 0];
1148
+
1149
+   end
1150
+
1151
+   if isempty(highcolor) | ischar(highcolor)
1152
+      highcolor = [];
1153
+      num_highcolor = 0;
1154
+   else
1155
+      num_highcolor = size(highcolor,1);
1156
+   end
1157
+
1158
+   if isempty(colorlevel)
1159
+      colorlevel = 256 - num_highcolor;
1160
+   end
1161
+
1162
+   if usecolorbar
1163
+      cbar_area = area;
1164
+      cbar_area(1) = area(1) + area(3)*0.93;
1165
+      cbar_area(3) = area(3)*0.04;
1166
+      area(3) = area(3)*0.9;		% 90% used for main axes
1167
+   else
1168
+      cbar_area = [];
1169
+   end
1170
+
1171
+   %  init color (gray) scaling to make sure the slice clim take the
1172
+   %  global clim [min(nii.img(:)) max(nii.img(:))]
1173
+   %
1174
+   if isempty(bgimg)
1175
+      clim = [minvalue maxvalue];
1176
+   else
1177
+      clim = [minvalue double(max(bgimg(:)))];
1178
+   end
1179
+
1180
+   if clim(1) == clim(2)
1181
+      clim(2) = clim(1) + 0.000001;
1182
+   end
1183
+
1184
+   if isempty(cbarminmax)
1185
+      cbarminmax = [minvalue maxvalue];
1186
+   end
1187
+
1188
+   xdim = size(nii.img, 1);
1189
+   ydim = size(nii.img, 2);
1190
+   zdim = size(nii.img, 3);
1191
+
1192
+   dims = [xdim ydim zdim];
1193
+   voxel_size = abs(nii.hdr.dime.pixdim(2:4));		% vol in mm
1194
+
1195
+   if any(voxel_size <= 0)
1196
+      voxel_size(find(voxel_size <= 0)) = 1;
1197
+   end
1198
+
1199
+   origin = abs(nii.hdr.hist.originator(1:3));
1200
+
1201
+   if isempty(origin) | all(origin == 0)		% according to SPM
1202
+      origin = (dims+1)/2;   
1203
+   end;
1204
+
1205
+   origin = round(origin);
1206
+
1207
+   if any(origin > dims)				% simulate fMRI
1208
+      origin(find(origin > dims)) = dims(find(origin > dims));
1209
+   end
1210
+
1211
+   if any(origin <= 0)
1212
+      origin(find(origin <= 0)) = 1;
1213
+   end
1214
+
1215
+   nii_view.dims = dims;
1216
+   nii_view.voxel_size = voxel_size;
1217
+   nii_view.origin = origin;
1218
+
1219
+   nii_view.slices.sag = 1;
1220
+   nii_view.slices.cor = 1;
1221
+   nii_view.slices.axi = 1;
1222
+   if xdim > 1, nii_view.slices.sag = origin(1); end
1223
+   if ydim > 1, nii_view.slices.cor = origin(2); end
1224
+   if zdim > 1, nii_view.slices.axi = origin(3); end
1225
+
1226
+   nii_view.area = area;
1227
+   nii_view.fig = fig;
1228
+   nii_view.nii = nii;					% image data
1229
+   nii_view.bgimg = bgimg;				% background
1230
+   nii_view.setvalue = setvalue;
1231
+   nii_view.minvalue = minvalue;
1232
+   nii_view.maxvalue = maxvalue;
1233
+   nii_view.numscan = nii.hdr.dime.dim(5);
1234
+   nii_view.scanid = setscanid;
1235
+
1236
+   Font.FontUnits  = 'point';
1237
+   Font.FontSize   = 12;
1238
+
1239
+   %  create axes for colorbar
1240
+   %
1241
+   [cbar_axes cbarminmax_axes] = create_cbar_axes(fig, cbar_area);
1242
+
1243
+   if isempty(cbar_area)
1244
+      nii_view.cbar_area = [];
1245
+   else
1246
+      nii_view.cbar_area = cbar_area;
1247
+   end
1248
+
1249
+   %  create axes for top/front/side view
1250
+   %
1251
+   vol_size = voxel_size .* dims;
1252
+   [top_ax, front_ax, side_ax] ...
1253
+	= create_ax(fig, area, vol_size, usestretch);
1254
+
1255
+   top_pos = get(top_ax,'position');
1256
+   front_pos = get(front_ax,'position');
1257
+   side_pos = get(side_ax,'position');
1258
+
1259
+   %  Sagittal Slider
1260
+   %
1261
+   x = side_pos(1);
1262
+   y = top_pos(2) + top_pos(4);
1263
+   w = side_pos(3);
1264
+   h = (front_pos(2) - y) / 2;
1265
+   y = y + h;
1266
+
1267
+   pos = [x y w h];
1268
+
1269
+   if xdim > 1,
1270
+      slider_step(1) = 1/(xdim);
1271
+      slider_step(2) = 1.00001/(xdim);
1272
+
1273
+      handles.sagittal_slider = uicontrol('Parent',fig, ...
1274
+                'Style','slider','Units','Normalized', Font, ...
1275
+                'Position',pos, 'HorizontalAlignment','center',...
1276
+                'BackgroundColor',[0.5 0.5 0.5],'ForegroundColor',[0 0 0],...
1277
+                'BusyAction','queue',...
1278
+                'TooltipString','Sagittal slice navigation',...
1279
+                'Min',1,'Max',xdim,'SliderStep',slider_step, ...
1280
+                'Value',nii_view.slices.sag,...
1281
+                'Callback','view_nii(''sagittal_slider'');');
1282
+
1283
+      set(handles.sagittal_slider,'position',pos);	% linux66
1284
+   end
1285
+
1286
+   %  Coronal Slider
1287
+   %
1288
+   x = top_pos(1);
1289
+   y = top_pos(2) + top_pos(4);
1290
+   w = top_pos(3);
1291
+   h = (front_pos(2) - y) / 2;
1292
+   y = y + h;
1293
+
1294
+   pos = [x y w h];
1295
+
1296
+   if ydim > 1,
1297
+      slider_step(1) = 1/(ydim);
1298
+      slider_step(2) = 1.00001/(ydim);
1299
+
1300
+      slider_val = nii_view.dims(2) - nii_view.slices.cor + 1;
1301
+
1302
+      handles.coronal_slider = uicontrol('Parent',fig, ...
1303
+                'Style','slider','Units','Normalized', Font, ...
1304
+                'Position',pos, 'HorizontalAlignment','center',...
1305
+                'BackgroundColor',[0.5 0.5 0.5],'ForegroundColor',[0 0 0],...
1306
+                'BusyAction','queue',...
1307
+                'TooltipString','Coronal slice navigation',...
1308
+                'Min',1,'Max',ydim,'SliderStep',slider_step, ...
1309
+                'Value',slider_val,...
1310
+                'Callback','view_nii(''coronal_slider'');');
1311
+
1312
+      set(handles.coronal_slider,'position',pos);	% linux66
1313
+   end
1314
+
1315
+   %  Axial Slider
1316
+   %
1317
+%   x = front_pos(1) + front_pos(3);
1318
+%   y = front_pos(2);
1319
+%   w = side_pos(1) - x;
1320
+%   h = front_pos(4);
1321
+
1322
+   x = top_pos(1);
1323
+   y = area(2);
1324
+   w = top_pos(3);
1325
+   h = top_pos(2) - y;
1326
+
1327
+   pos = [x y w h];
1328
+
1329
+   if zdim > 1,
1330
+      slider_step(1) = 1/(zdim);
1331
+      slider_step(2) = 1.00001/(zdim);
1332
+
1333
+      handles.axial_slider = uicontrol('Parent',fig, ...
1334
+                'Style','slider','Units','Normalized', Font, ...
1335
+                'Position',pos, 'HorizontalAlignment','center',...
1336
+                'BackgroundColor',[0.5 0.5 0.5],'ForegroundColor',[0 0 0],...
1337
+                'BusyAction','queue',...
1338
+                'TooltipString','Axial slice navigation',...
1339
+                'Min',1,'Max',zdim,'SliderStep',slider_step, ...
1340
+                'Value',nii_view.slices.axi,...
1341
+                'Callback','view_nii(''axial_slider'');');
1342
+
1343
+      set(handles.axial_slider,'position',pos);	% linux66
1344
+   end
1345
+
1346
+   %  plot info view
1347
+   %
1348
+%   info_pos = [side_pos([1,3]); top_pos([2,4])];
1349
+%   info_pos = info_pos(:);
1350
+   gap = side_pos(1)-(top_pos(1)+top_pos(3));
1351
+   info_pos(1) = side_pos(1) + gap;
1352
+   info_pos(2) = area(2);
1353
+   info_pos(3) = side_pos(3) - gap;
1354
+   info_pos(4) = top_pos(2) + top_pos(4) - area(2) - gap;
1355
+
1356
+   num_inputline = 10;
1357
+   inputline_space =info_pos(4) / num_inputline;
1358
+
1359
+
1360
+   %  for any info_area change, update_usestretch should also be changed
1361
+
1362
+
1363
+   %  Image Intensity Value at Cursor
1364
+   %
1365
+   x = info_pos(1);
1366
+   y = info_pos(2);
1367
+   w = info_pos(3)*0.5;
1368
+   h = inputline_space*0.6;
1369
+
1370
+   pos = [x y w h];
1371
+
1372
+   handles.Timvalcur = uicontrol('Parent',fig,'Style','text', ...
1373
+      'Units','Normalized', Font, ...
1374
+      'Position',pos, 'HorizontalAlignment', 'left',...
1375
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1376
+      'BusyAction','queue',...
1377
+      'visible','off', ...
1378
+      'String','Value at cursor:');
1379
+
1380
+   if usepanel
1381
+      set(handles.Timvalcur, 'visible', 'on');
1382
+   end
1383
+
1384
+   x = x + w;
1385
+   w = info_pos(3)*0.5;
1386
+
1387
+   pos = [x y w h];
1388
+
1389
+   handles.imvalcur = uicontrol('Parent',fig,'Style','text', ...
1390
+      'Units','Normalized', Font, ...
1391
+      'Position',pos, 'HorizontalAlignment', 'right',...
1392
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1393
+      'BusyAction','queue',...
1394
+      'visible','off', ...
1395
+      'String',' ');
1396
+
1397
+   if usepanel
1398
+      set(handles.imvalcur, 'visible', 'on');
1399
+   end
1400
+
1401
+   %  Position at Cursor
1402
+   %
1403
+   x = info_pos(1);
1404
+   y = y + inputline_space;
1405
+   w = info_pos(3)*0.5;
1406
+
1407
+   pos = [x y w h];
1408
+
1409
+   handles.Timposcur = uicontrol('Parent',fig,'Style','text', ...
1410
+        'Units','Normalized', Font, ...
1411
+        'Position',pos, 'HorizontalAlignment', 'left',...
1412
+        'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1413
+        'BusyAction','queue',...
1414
+        'visible','off', ...
1415
+        'String','[X Y Z] at cursor:');
1416
+
1417
+   if usepanel
1418
+      set(handles.Timposcur, 'visible', 'on');
1419
+   end
1420
+
1421
+   x = x + w;
1422
+   w = info_pos(3)*0.5;
1423
+
1424
+   pos = [x y w h];
1425
+
1426
+   handles.imposcur = uicontrol('Parent',fig,'Style','text', ...
1427
+        'Units','Normalized', Font, ...
1428
+        'Position',pos, 'HorizontalAlignment', 'right',...
1429
+        'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1430
+        'BusyAction','queue',...
1431
+        'visible','off', ...
1432
+        'String',' ','Value',[0 0 0]);
1433
+
1434
+   if usepanel
1435
+      set(handles.imposcur, 'visible', 'on');
1436
+   end
1437
+
1438
+   %  Image Intensity Value at Mouse Click
1439
+   %
1440
+   x = info_pos(1);
1441
+   y = y + inputline_space;
1442
+   w = info_pos(3)*0.5;
1443
+
1444
+   pos = [x y w h];
1445
+
1446
+   handles.Timval = uicontrol('Parent',fig,'Style','text', ...
1447
+      'Units','Normalized', Font, ...
1448
+      'Position',pos, 'HorizontalAlignment', 'left',...
1449
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1450
+      'BusyAction','queue',...
1451
+      'visible','off', ...
1452
+      'String','Value at crosshair:');
1453
+
1454
+   if usepanel
1455
+      set(handles.Timval, 'visible', 'on');
1456
+   end
1457
+
1458
+   x = x + w;
1459
+   w = info_pos(3)*0.5;
1460
+
1461
+   pos = [x y w h];
1462
+
1463
+   handles.imval = uicontrol('Parent',fig,'Style','text', ...
1464
+      'Units','Normalized', Font, ...
1465
+      'Position',pos, 'HorizontalAlignment', 'right',...
1466
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1467
+      'BusyAction','queue',...
1468
+      'visible','off', ...
1469
+      'String',' ');
1470
+
1471
+   if usepanel
1472
+      set(handles.imval, 'visible', 'on');
1473
+   end
1474
+
1475
+   %  Viewpoint Position at Mouse Click
1476
+   %
1477
+   x = info_pos(1);
1478
+   y = y + inputline_space;
1479
+   w = info_pos(3)*0.5;
1480
+
1481
+   pos = [x y w h];
1482
+
1483
+   handles.Timpos = uicontrol('Parent',fig,'Style','text', ...
1484
+        'Units','Normalized', Font, ...
1485
+        'Position',pos, 'HorizontalAlignment', 'left',...
1486
+        'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1487
+        'BusyAction','queue',...
1488
+        'visible','off', ...
1489
+        'String','[X Y Z] at crosshair:');
1490
+
1491
+   if usepanel
1492
+      set(handles.Timpos, 'visible', 'on');
1493
+   end
1494
+
1495
+   x = x + w + 0.005;
1496
+   y = y - 0.008;
1497
+   w = info_pos(3)*0.5;
1498
+   h = inputline_space*0.9;
1499
+
1500
+   pos = [x y w h];
1501
+
1502
+   handles.impos = uicontrol('Parent',fig,'Style','edit', ...
1503
+        'Units','Normalized', Font, ...
1504
+        'Position',pos, 'HorizontalAlignment', 'right',...
1505
+        'BackgroundColor', [1 1 1], 'ForegroundColor', [0 0 0],...
1506
+        'BusyAction','queue',...
1507
+        'Callback','view_nii(''impos_edit'');', ...
1508
+        'TooltipString','Viewpoint Location in Axes Unit', ...
1509
+        'visible','off', ...
1510
+        'String',' ','Value',[0 0 0]);
1511
+
1512
+   if usepanel
1513
+      set(handles.impos, 'visible', 'on');
1514
+   end
1515
+
1516
+   %  Origin Position
1517
+   %
1518
+   x = info_pos(1);
1519
+   y = y + inputline_space*1.2;
1520
+   w = info_pos(3)*0.5;
1521
+   h = inputline_space*0.6;
1522
+
1523
+   pos = [x y w h];
1524
+
1525
+   handles.Torigin = uicontrol('Parent',fig,'Style','text', ...
1526
+        'Units','Normalized', Font, ...
1527
+        'Position',pos, 'HorizontalAlignment', 'left',...
1528
+        'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1529
+        'BusyAction','queue',...
1530
+        'visible','off', ...
1531
+        'String','[X Y Z] at origin:');
1532
+
1533
+   if usepanel
1534
+      set(handles.Torigin, 'visible', 'on');
1535
+   end
1536
+
1537
+   x = x + w;
1538
+   w = info_pos(3)*0.5;
1539
+
1540
+   pos = [x y w h];
1541
+
1542
+   handles.origin = uicontrol('Parent',fig,'Style','text', ...
1543
+        'Units','Normalized', Font, ...
1544
+        'Position',pos, 'HorizontalAlignment', 'right',...
1545
+        'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1546
+        'BusyAction','queue',...
1547
+        'visible','off', ...
1548
+        'String',' ','Value',[0 0 0]);
1549
+
1550
+   if usepanel
1551
+      set(handles.origin, 'visible', 'on');
1552
+   end
1553
+
1554
+if 0
1555
+   %  Voxel Unit
1556
+   %
1557
+   x = info_pos(1);
1558
+   y = y + inputline_space;
1559
+   w = info_pos(3)*0.5;
1560
+
1561
+   pos = [x y w h];
1562
+
1563
+   handles.Tcoord = uicontrol('Parent',fig,'Style','text', ...
1564
+      'Units','Normalized', Font, ...
1565
+      'Position',pos, 'HorizontalAlignment', 'left',...
1566
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1567
+      'BusyAction','queue',...
1568
+      'visible','off', ...
1569
+      'String','Axes Unit:');
1570
+
1571
+   if usepanel
1572
+      set(handles.Tcoord, 'visible', 'on');
1573
+   end
1574
+
1575
+   x = x + w + 0.005;
1576
+   w = info_pos(3)*0.5 - 0.005;
1577
+
1578
+   pos = [x y w h];
1579
+
1580
+   Font.FontSize   = 8;
1581
+
1582
+   handles.coord = uicontrol('Parent',fig,'Style','popupmenu', ...
1583
+      'Units','Normalized', Font, ...
1584
+      'Position',pos, ...
1585
+      'BackgroundColor', [1 1 1], 'ForegroundColor', [0 0 0],...
1586
+      'BusyAction','queue',...
1587
+      'TooltipString','Choose Voxel or Millimeter',...
1588
+      'String',{'Voxel','Millimeter'},...
1589
+      'visible','off', ...
1590
+      'Callback','view_nii(''coordinates'');');
1591
+
1592
+%      'TooltipString','Choose Voxel, MNI or Talairach Coordinates',...
1593
+%      'String',{'Voxel','MNI (mm)','Talairach (mm)'},...
1594
+
1595
+   Font.FontSize   = 12;
1596
+
1597
+   if usepanel
1598
+      set(handles.coord, 'visible', 'on');
1599
+   end
1600
+end
1601
+
1602
+   %  Crosshair
1603
+   %
1604
+   x = info_pos(1);
1605
+   y = y + inputline_space;
1606
+   w = info_pos(3)*0.4;
1607
+
1608
+   pos = [x y w h];
1609
+
1610
+   handles.Txhair = uicontrol('Parent',fig,'Style','text', ...
1611
+      'Units','Normalized', Font, ...
1612
+      'Position',pos, 'HorizontalAlignment', 'left',...
1613
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1614
+      'BusyAction','queue',...
1615
+      'visible','off', ...
1616
+      'String','Crosshair:');
1617
+
1618
+   if usepanel
1619
+      set(handles.Txhair, 'visible', 'on');
1620
+   end
1621
+
1622
+   x = info_pos(1) + info_pos(3)*0.5;
1623
+   w = info_pos(3)*0.2;
1624
+   h = inputline_space*0.7;
1625
+
1626
+   pos = [x y w h];
1627
+
1628
+   Font.FontSize   = 8;
1629
+
1630
+   handles.xhair_color = uicontrol('Parent',fig,'Style','push', ...
1631
+      'Units','Normalized', Font, ...
1632
+      'Position',pos, 'HorizontalAlignment', 'center',...
1633
+      'TooltipString','Crosshair Color',...
1634
+      'User',[1 0 0],...
1635
+      'String','Color',...
1636
+      'visible','off', ...
1637
+      'Callback','view_nii(''xhair_color'');');
1638
+
1639
+   if usepanel
1640
+      set(handles.xhair_color, 'visible', 'on');
1641
+   end
1642
+
1643
+   x = info_pos(1) + info_pos(3)*0.7;
1644
+   w = info_pos(3)*0.3;
1645
+
1646
+   pos = [x y w h];
1647
+
1648
+   handles.xhair = uicontrol('Parent',fig,'Style','popupmenu', ...
1649
+      'Units','Normalized', Font, ...
1650
+      'Position',pos, ...
1651
+      'BackgroundColor', [1 1 1], 'ForegroundColor', [0 0 0],...
1652
+      'BusyAction','queue',...
1653
+      'TooltipString','Display or Hide Crosshair',...
1654
+      'String',{'On','Off'},...
1655
+      'visible','off', ...
1656
+      'Callback','view_nii(''crosshair'');');
1657
+
1658
+   if usepanel
1659
+      set(handles.xhair, 'visible', 'on');
1660
+   end
1661
+
1662
+   %  Histogram & Color
1663
+   %
1664
+   x = info_pos(1);
1665
+   w = info_pos(3)*0.45;
1666
+   h = inputline_space * 1.5;
1667
+
1668
+   pos = [x,  y+inputline_space*0.9,  w,  h];
1669
+
1670
+   handles.hist_frame = uicontrol('Parent',fig, ...	
1671
+   	'Units','normal', ...
1672
+   	'BackgroundColor',[0.8 0.8 0.8], ...
1673
+   	'Position',pos, ...
1674
+        'visible','off', ...
1675
+   	'Style','frame');
1676
+
1677
+   if usepanel
1678
+%      set(handles.hist_frame, 'visible', 'on');
1679
+   end
1680
+
1681
+   handles.coord_frame = uicontrol('Parent',fig, ...	
1682
+   	'Units','normal', ...
1683
+   	'BackgroundColor',[0.8 0.8 0.8], ...
1684
+   	'Position',pos, ...
1685
+        'visible','off', ...
1686
+   	'Style','frame');
1687
+
1688
+   if usepanel
1689
+      set(handles.coord_frame, 'visible', 'on');
1690
+   end
1691
+
1692
+   x = info_pos(1) + info_pos(3)*0.475;
1693
+   w = info_pos(3)*0.525;
1694
+   h = inputline_space * 1.5;
1695
+
1696
+   pos = [x,  y+inputline_space*0.9,  w,  h];
1697
+
1698
+   handles.color_frame = uicontrol('Parent',fig, ...	
1699
+   	'Units','normal', ...
1700
+   	'BackgroundColor',[0.8 0.8 0.8], ...
1701
+   	'Position',pos, ...
1702
+        'visible','off', ...
1703
+   	'Style','frame');
1704
+
1705
+   if usepanel
1706
+      set(handles.color_frame, 'visible', 'on');
1707
+   end
1708
+
1709
+   x = info_pos(1) + info_pos(3)*0.025;
1710
+   y = y + inputline_space*1.2;
1711
+   w = info_pos(3)*0.2;
1712
+   h = inputline_space*0.7;
1713
+
1714
+   pos = [x y w h];
1715
+
1716
+   Font.FontSize   = 8;
1717
+
1718
+   handles.hist_eq = uicontrol('Parent',fig,'Style','toggle', ...
1719
+      'Units','Normalized', Font, ...
1720
+      'Position',pos, 'HorizontalAlignment', 'center',...
1721
+      'TooltipString','Histogram Equalization',...
1722
+      'String','Hist EQ',...
1723
+      'visible','off', ...
1724
+      'Callback','view_nii(''hist_eq'');');
1725
+
1726
+   if usepanel
1727
+%      set(handles.hist_eq, 'visible', 'on');
1728
+   end
1729
+
1730
+   x = x + w;
1731
+   w = info_pos(3)*0.2;
1732
+
1733
+   pos = [x y w h];
1734
+
1735
+   handles.hist_plot = uicontrol('Parent',fig,'Style','push', ...
1736
+      'Units','Normalized', Font, ...
1737
+      'Position',pos, 'HorizontalAlignment', 'center',...
1738
+      'TooltipString','Histogram Plot',...
1739
+      'String','Hist Plot',...
1740
+      'visible','off', ...
1741
+      'Callback','view_nii(''hist_plot'');');
1742
+
1743
+   if usepanel
1744
+%      set(handles.hist_plot, 'visible', 'on');
1745
+   end
1746
+
1747
+   x = info_pos(1) + info_pos(3)*0.025;
1748
+   w = info_pos(3)*0.4;
1749
+
1750
+   pos = [x y w h];
1751
+
1752
+   handles.coord = uicontrol('Parent',fig,'Style','popupmenu', ...
1753
+      'Units','Normalized', Font, ...
1754
+      'Position',pos, ...
1755
+      'BackgroundColor', [1 1 1], 'ForegroundColor', [0 0 0],...
1756
+      'BusyAction','queue',...
1757
+      'TooltipString','Choose Voxel or Millimeter',...
1758
+      'String',{'Voxel','Millimeter'},...
1759
+      'visible','off', ...
1760
+      'Callback','view_nii(''coordinates'');');
1761
+
1762
+%      'TooltipString','Choose Voxel, MNI or Talairach Coordinates',...
1763
+%      'String',{'Voxel','MNI (mm)','Talairach (mm)'},...
1764
+
1765
+   if usepanel
1766
+      set(handles.coord, 'visible', 'on');
1767
+   end
1768
+
1769
+   x = info_pos(1) + info_pos(3)*0.5;
1770
+   w = info_pos(3)*0.2;
1771
+
1772
+   pos = [x y w h];
1773
+
1774
+   handles.neg_color = uicontrol('Parent',fig,'Style','toggle', ...
1775
+      'Units','Normalized', Font, ...
1776
+      'Position',pos, 'HorizontalAlignment', 'center',...
1777
+      'TooltipString','Negative Colormap',...
1778
+      'String','Negative',...
1779
+      'visible','off', ...
1780
+      'Callback','view_nii(''neg_color'');');
1781
+
1782
+   if usepanel
1783
+      set(handles.neg_color, 'visible', 'on');
1784
+   end
1785
+
1786
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
1787
+      set(handles.neg_color, 'enable', 'off');
1788
+   end
1789
+
1790
+   x = info_pos(1) + info_pos(3)*0.7;
1791
+   w = info_pos(3)*0.275;
1792
+
1793
+   pos = [x y w h];
1794
+
1795
+   handles.colorindex = uicontrol('Parent',fig,'Style','popupmenu', ...
1796
+      'Units','Normalized', Font, ...
1797
+      'Position',pos, ...
1798
+      'BackgroundColor', [1 1 1], 'ForegroundColor', [0 0 0],...
1799
+      'BusyAction','queue',...
1800
+      'TooltipString','Change Colormap',...
1801
+      'String',{'Custom','Bipolar','Gray','Jet','Cool','Bone','Hot','Copper','Pink'},...
1802
+      'value', colorindex, ...
1803
+      'visible','off', ...
1804
+      'Callback','view_nii(''color'');');
1805
+
1806
+   if usepanel
1807
+      set(handles.colorindex, 'visible', 'on');
1808
+   end
1809
+
1810
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
1811
+      set(handles.colorindex, 'enable', 'off');
1812
+   end
1813
+
1814
+   x = info_pos(1) + info_pos(3)*0.1;
1815
+   y = y + inputline_space;
1816
+   w = info_pos(3)*0.28;
1817
+   h = inputline_space*0.6;
1818
+
1819
+   pos = [x y w h];
1820
+
1821
+   Font.FontSize   = 8;
1822
+
1823
+   handles.Thist = uicontrol('Parent',fig,'Style','text', ...
1824
+      'Units','Normalized', Font, ...
1825
+      'Position',pos, 'HorizontalAlignment', 'center',...
1826
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1827
+      'BusyAction','queue',...
1828
+      'visible','off', ...
1829
+      'String','Histogram');
1830
+
1831
+   handles.Tcoord = uicontrol('Parent',fig,'Style','text', ...
1832
+      'Units','Normalized', Font, ...
1833
+      'Position',pos, 'HorizontalAlignment', 'center',...
1834
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1835
+      'BusyAction','queue',...
1836
+      'visible','off', ...
1837
+      'String','Axes Unit');
1838
+
1839
+   if usepanel
1840
+%      set(handles.Thist, 'visible', 'on');
1841
+      set(handles.Tcoord, 'visible', 'on');
1842
+   end
1843
+
1844
+   x = info_pos(1) + info_pos(3)*0.60;
1845
+   w = info_pos(3)*0.28;
1846
+
1847
+   pos = [x y w h];
1848
+
1849
+   handles.Tcolor = uicontrol('Parent',fig,'Style','text', ...
1850
+      'Units','Normalized', Font, ...
1851
+      'Position',pos, 'HorizontalAlignment', 'center',...
1852
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1853
+      'BusyAction','queue',...
1854
+      'visible','off', ...
1855
+      'String','Colormap');
1856
+
1857
+   if usepanel
1858
+      set(handles.Tcolor, 'visible', 'on');
1859
+   end
1860
+
1861
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
1862
+      set(handles.Tcolor, 'enable', 'off');
1863
+   end
1864
+
1865
+   %  Contrast Frame
1866
+   %
1867
+   x = info_pos(1);
1868
+   w = info_pos(3)*0.45;
1869
+   h = inputline_space * 2;
1870
+
1871
+   pos = [x,  y+inputline_space*0.8,  w,  h];
1872
+
1873
+   handles.contrast_frame = uicontrol('Parent',fig, ...	
1874
+   	'Units','normal', ...
1875
+   	'BackgroundColor',[0.8 0.8 0.8], ...
1876
+   	'Position',pos, ...
1877
+        'visible','off', ...
1878
+   	'Style','frame');
1879
+
1880
+   if usepanel
1881
+      set(handles.contrast_frame, 'visible', 'on');
1882
+   end
1883
+
1884
+   if colorindex < 2 | colorindex > 3
1885
+      set(handles.contrast_frame, 'visible', 'off');
1886
+   end
1887
+
1888
+   %  Brightness Frame
1889
+   %
1890
+   x = info_pos(1) + info_pos(3)*0.475;
1891
+   w = info_pos(3)*0.525;
1892
+
1893
+   pos = [x,  y+inputline_space*0.8,  w,  h];
1894
+
1895
+   handles.brightness_frame = uicontrol('Parent',fig, ...	
1896
+   	'Units','normal', ...
1897
+   	'BackgroundColor',[0.8 0.8 0.8], ...
1898
+   	'Position',pos, ...
1899
+        'visible','off', ...
1900
+   	'Style','frame');
1901
+
1902
+   if usepanel
1903
+      set(handles.brightness_frame, 'visible', 'on');
1904
+   end
1905
+
1906
+   %  Contrast
1907
+   %
1908
+   x = info_pos(1) + info_pos(3)*0.025;
1909
+   y = y + inputline_space;
1910
+   w = info_pos(3)*0.4;
1911
+   h = inputline_space*0.6;
1912
+
1913
+   pos = [x y w h];
1914
+
1915
+   Font.FontSize   = 12;
1916
+
1917
+   slider_step(1) = 5/255;
1918
+   slider_step(2) = 5.00001/255;
1919
+
1920
+   handles.contrast = uicontrol('Parent',fig, ...
1921
+      'Style','slider','Units','Normalized', Font, ...
1922
+      'Position',pos, 'HorizontalAlignment', 'left',...
1923
+      'BackgroundColor',[0.5 0.5 0.5],'ForegroundColor',[0 0 0],...
1924
+      'BusyAction','queue',...
1925
+      'TooltipString','Change contrast',...
1926
+      'Min',1,'Max',256,'SliderStep',slider_step, ...
1927
+      'Value',1, ...
1928
+      'visible','off', ...
1929
+      'Callback','view_nii(''contrast'');');
1930
+
1931
+   if usepanel
1932
+      set(handles.contrast, 'visible', 'on');
1933
+   end
1934
+
1935
+   if (nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511) & nii_view.numscan <= 1
1936
+      set(handles.contrast, 'enable', 'off');
1937
+   end
1938
+
1939
+   if nii_view.numscan > 1
1940
+      set(handles.contrast, 'min', 1, 'max', nii_view.numscan, ...
1941
+         'sliderstep',[1/(nii_view.numscan-1) 1.00001/(nii_view.numscan-1)], ...
1942
+         'Callback', 'view_nii(''slider_change_scan'');');
1943
+   elseif colorindex < 2 | colorindex > 3
1944
+      set(handles.contrast, 'visible', 'off');
1945
+   elseif colorindex == 2
1946
+      set(handles.contrast,'value',128);
1947
+   end
1948
+
1949
+   set(handles.contrast,'position',pos);	% linux66
1950
+
1951
+   %  Brightness
1952
+   %
1953
+   x = info_pos(1) + info_pos(3)*0.5;
1954
+   w = info_pos(3)*0.475;
1955
+
1956
+   pos = [x y w h];
1957
+
1958
+   Font.FontSize   = 12;
1959
+
1960
+   slider_step(1) = 1/50;
1961
+   slider_step(2) = 1.00001/50;
1962
+
1963
+   handles.brightness = uicontrol('Parent',fig, ...
1964
+      'Style','slider','Units','Normalized', Font, ...
1965
+      'Position',pos, 'HorizontalAlignment', 'left',...
1966
+      'BackgroundColor',[0.5 0.5 0.5],'ForegroundColor',[0 0 0],...
1967
+      'BusyAction','queue',...
1968
+      'TooltipString','Change brightness',...
1969
+      'Min',-1,'Max',1,'SliderStep',slider_step, ...
1970
+      'Value',0, ...
1971
+      'visible','off', ...
1972
+      'Callback','view_nii(''brightness'');');
1973
+
1974
+   if usepanel
1975
+      set(handles.brightness, 'visible', 'on');
1976
+   end
1977
+
1978
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
1979
+      set(handles.brightness, 'enable', 'off');
1980
+   end
1981
+
1982
+   set(handles.brightness,'position',pos);	% linux66
1983
+
1984
+   %  Contrast text/def
1985
+   %
1986
+   x = info_pos(1) + info_pos(3)*0.025;
1987
+   y = y + inputline_space;
1988
+   w = info_pos(3)*0.22;
1989
+
1990
+   pos = [x y w h];
1991
+
1992
+   handles.Tcontrast = uicontrol('Parent',fig,'Style','text', ...
1993
+      'Units','Normalized', Font, ...
1994
+      'Position',pos, 'HorizontalAlignment', 'left',...
1995
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
1996
+      'BusyAction','queue',...
1997
+      'visible','off', ...
1998
+      'String','Contrast:');
1999
+
2000
+   if usepanel
2001
+      set(handles.Tcontrast, 'visible', 'on');
2002
+   end
2003
+
2004
+   if (nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511) & nii_view.numscan <= 1
2005
+      set(handles.Tcontrast, 'enable', 'off');
2006
+   end
2007
+
2008
+   if nii_view.numscan > 1
2009
+      set(handles.Tcontrast, 'string', 'Scan ID:');
2010
+   elseif colorindex < 2 | colorindex > 3
2011
+      set(handles.Tcontrast, 'visible', 'off');
2012
+   end
2013
+
2014
+   x = x + w;
2015
+   w = info_pos(3)*0.18;
2016
+
2017
+   pos = [x y w h];
2018
+
2019
+   Font.FontSize   = 8;
2020
+
2021
+   handles.contrast_def = uicontrol('Parent',fig,'Style','push', ...
2022
+      'Units','Normalized', Font, ...
2023
+      'Position',pos, 'HorizontalAlignment', 'center',...
2024
+      'TooltipString','Restore initial contrast',...
2025
+      'String','Reset',...
2026
+      'visible','off', ...
2027
+      'Callback','view_nii(''contrast_def'');');
2028
+
2029
+   if usepanel
2030
+      set(handles.contrast_def, 'visible', 'on');
2031
+   end
2032
+
2033
+   if (nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511) & nii_view.numscan <= 1
2034
+      set(handles.contrast_def, 'enable', 'off');
2035
+   end
2036
+
2037
+   if nii_view.numscan > 1
2038
+      set(handles.contrast_def, 'style', 'edit', 'background', 'w', ...
2039
+         'TooltipString','Scan (or volume) index in the time series',...
2040
+         'string', '1', 'Callback', 'view_nii(''edit_change_scan'');');
2041
+   elseif colorindex < 2 | colorindex > 3
2042
+      set(handles.contrast_def, 'visible', 'off');
2043
+   end
2044
+
2045
+   %  Brightness text/def
2046
+   %
2047
+   x = info_pos(1) + info_pos(3)*0.5;
2048
+   w = info_pos(3)*0.295;
2049
+
2050
+   pos = [x y w h];
2051
+
2052
+   Font.FontSize   = 12;
2053
+
2054
+   handles.Tbrightness = uicontrol('Parent',fig,'Style','text', ...
2055
+      'Units','Normalized', Font, ...
2056
+      'Position',pos, 'HorizontalAlignment', 'left',...
2057
+      'BackgroundColor', [0.8 0.8 0.8], 'ForegroundColor', [0 0 0],...
2058
+      'BusyAction','queue',...
2059
+      'visible','off', ...
2060
+      'String','Brightness:');
2061
+
2062
+   if usepanel
2063
+      set(handles.Tbrightness, 'visible', 'on');
2064
+   end
2065
+
2066
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2067
+      set(handles.Tbrightness, 'enable', 'off');
2068
+   end
2069
+
2070
+   x = x + w;
2071
+   w = info_pos(3)*0.18;
2072
+
2073
+   pos = [x y w h];
2074
+
2075
+   Font.FontSize   = 8;
2076
+
2077
+   handles.brightness_def = uicontrol('Parent',fig,'Style','push', ...
2078
+      'Units','Normalized', Font, ...
2079
+      'Position',pos, 'HorizontalAlignment', 'center',...
2080
+      'TooltipString','Restore initial brightness',...
2081
+      'String','Reset',...
2082
+      'visible','off', ...
2083
+      'Callback','view_nii(''brightness_def'');');
2084
+
2085
+   if usepanel
2086
+      set(handles.brightness_def, 'visible', 'on');
2087
+   end
2088
+
2089
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2090
+      set(handles.brightness_def, 'enable', 'off');
2091
+   end
2092
+
2093
+   %  init image handles
2094
+   %
2095
+   handles.axial_image = [];
2096
+   handles.coronal_image = [];
2097
+   handles.sagittal_image = [];
2098
+
2099
+   %  plot axial view
2100
+   %
2101
+   if ~isempty(nii_view.bgimg)
2102
+      bg_slice = squeeze(bgimg(:,:,nii_view.slices.axi));
2103
+      h1 = plot_view(fig, xdim, ydim, top_ax, bg_slice', clim, cbarminmax, ...
2104
+		handles, useimagesc, colorindex, color_map, ...
2105
+		colorlevel, highcolor, useinterp, nii_view.numscan);
2106
+      handles.axial_bg = h1;
2107
+   else
2108
+      handles.axial_bg = [];
2109
+   end
2110
+
2111
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2112
+      img_slice = squeeze(nii.img(:,:,nii_view.slices.axi,:,setscanid));
2113
+      img_slice = permute(img_slice, [2 1 3]);
2114
+   else
2115
+      img_slice = squeeze(nii.img(:,:,nii_view.slices.axi,setscanid));
2116
+      img_slice = img_slice';
2117
+   end
2118
+   h1 = plot_view(fig, xdim, ydim, top_ax, img_slice, clim, cbarminmax, ...
2119
+	handles, useimagesc, colorindex, color_map, ...
2120
+	colorlevel, highcolor, useinterp, nii_view.numscan);
2121
+   set(h1,'buttondown','view_nii(''axial_image'');');
2122
+   handles.axial_image = h1;
2123
+   handles.axial_axes = top_ax;
2124
+
2125
+   if size(img_slice,1) == 1 | size(img_slice,2) == 1
2126
+      set(top_ax,'visible','off');
2127
+
2128
+      if isfield(handles,'sagittal_slider') & ishandle(handles.sagittal_slider)
2129
+         set(handles.sagittal_slider, 'visible', 'off');
2130
+      end
2131
+
2132
+      if isfield(handles,'coronal_slider') & ishandle(handles.coronal_slider)
2133
+         set(handles.coronal_slider, 'visible', 'off');
2134
+      end
2135
+
2136
+      if isfield(handles,'axial_slider') & ishandle(handles.axial_slider)
2137
+         set(handles.axial_slider, 'visible', 'off');
2138
+      end
2139
+   end
2140
+
2141
+   %  plot coronal view
2142
+   %
2143
+   if ~isempty(nii_view.bgimg)
2144
+      bg_slice = squeeze(bgimg(:,nii_view.slices.cor,:));
2145
+      h1 = plot_view(fig, xdim, zdim, front_ax, bg_slice', clim, cbarminmax, ...
2146
+		handles, useimagesc, colorindex, color_map, ...
2147
+		colorlevel, highcolor, useinterp, nii_view.numscan);
2148
+      handles.coronal_bg = h1;
2149
+   else
2150
+      handles.coronal_bg = [];
2151
+   end
2152
+
2153
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2154
+      img_slice = squeeze(nii.img(:,nii_view.slices.cor,:,:,setscanid));
2155
+      img_slice = permute(img_slice, [2 1 3]);
2156
+   else
2157
+      img_slice = squeeze(nii.img(:,nii_view.slices.cor,:,setscanid));
2158
+      img_slice = img_slice';
2159
+   end
2160
+   h1 = plot_view(fig, xdim, zdim, front_ax, img_slice, clim, cbarminmax, ...
2161
+	handles, useimagesc, colorindex, color_map, ...
2162
+	colorlevel, highcolor, useinterp, nii_view.numscan);
2163
+   set(h1,'buttondown','view_nii(''coronal_image'');');
2164
+   handles.coronal_image = h1;
2165
+   handles.coronal_axes = front_ax;
2166
+
2167
+   if size(img_slice,1) == 1 | size(img_slice,2) == 1
2168
+      set(front_ax,'visible','off');
2169
+
2170
+      if isfield(handles,'sagittal_slider') & ishandle(handles.sagittal_slider)
2171
+         set(handles.sagittal_slider, 'visible', 'off');
2172
+      end
2173
+
2174
+      if isfield(handles,'coronal_slider') & ishandle(handles.coronal_slider)
2175
+         set(handles.coronal_slider, 'visible', 'off');
2176
+      end
2177
+
2178
+      if isfield(handles,'axial_slider') & ishandle(handles.axial_slider)
2179
+         set(handles.axial_slider, 'visible', 'off');
2180
+      end
2181
+   end
2182
+
2183
+   %  plot sagittal view
2184
+   %
2185
+   if ~isempty(nii_view.bgimg)
2186
+      bg_slice = squeeze(bgimg(nii_view.slices.sag,:,:));
2187
+
2188
+      h1 = plot_view(fig, ydim, zdim, side_ax, bg_slice', clim, cbarminmax, ...
2189
+		handles, useimagesc, colorindex, color_map, ...
2190
+		colorlevel, highcolor, useinterp, nii_view.numscan);
2191
+      handles.sagittal_bg = h1;
2192
+   else
2193
+      handles.sagittal_bg = [];
2194
+   end
2195
+
2196
+   if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2197
+      img_slice = squeeze(nii.img(nii_view.slices.sag,:,:,:,setscanid));
2198
+      img_slice = permute(img_slice, [2 1 3]);
2199
+   else
2200
+      img_slice = squeeze(nii.img(nii_view.slices.sag,:,:,setscanid));
2201
+      img_slice = img_slice';
2202
+   end
2203
+
2204
+   h1 = plot_view(fig, ydim, zdim, side_ax, img_slice, clim, cbarminmax, ...
2205
+	handles, useimagesc, colorindex, color_map, ...
2206
+	colorlevel, highcolor, useinterp, nii_view.numscan);
2207
+   set(h1,'buttondown','view_nii(''sagittal_image'');');
2208
+   set(side_ax,'Xdir', 'reverse');
2209
+   handles.sagittal_image = h1;
2210
+   handles.sagittal_axes = side_ax;
2211
+
2212
+   if size(img_slice,1) == 1 | size(img_slice,2) == 1
2213
+      set(side_ax,'visible','off');
2214
+
2215
+      if isfield(handles,'sagittal_slider') & ishandle(handles.sagittal_slider)
2216
+         set(handles.sagittal_slider, 'visible', 'off');
2217
+      end
2218
+
2219
+      if isfield(handles,'coronal_slider') & ishandle(handles.coronal_slider)
2220
+         set(handles.coronal_slider, 'visible', 'off');
2221
+      end
2222
+
2223
+      if isfield(handles,'axial_slider') & ishandle(handles.axial_slider)
2224
+         set(handles.axial_slider, 'visible', 'off');
2225
+      end
2226
+   end
2227
+
2228
+   [top1_label, top2_label, side1_label, side2_label] = ...
2229
+	dir_label(fig, top_ax, front_ax, side_ax);
2230
+
2231
+   %  store label handles
2232
+   %
2233
+   handles.top1_label = top1_label;
2234
+   handles.top2_label = top2_label;
2235
+   handles.side1_label = side1_label;
2236
+   handles.side2_label = side2_label;
2237
+
2238
+   %  plot colorbar
2239
+   %
2240
+   if ~isempty(cbar_axes) & ~isempty(cbarminmax_axes)
2241
+
2242
+if 0
2243
+      if isempty(color_map)
2244
+         level = colorlevel + num_highcolor;
2245
+      else
2246
+         level = size([color_map; highcolor], 1);
2247
+      end
2248
+end
2249
+
2250
+      if isempty(color_map)
2251
+         level = colorlevel;
2252
+      else
2253
+         level = size([color_map], 1);
2254
+      end
2255
+
2256
+      niiclass = class(nii.img);
2257
+
2258
+      h1 = plot_cbar(fig, cbar_axes, cbarminmax_axes, cbarminmax, ...
2259
+		level, handles, useimagesc, colorindex, color_map, ...
2260
+		colorlevel, highcolor, niiclass, nii_view.numscan);
2261
+      handles.cbar_image = h1;
2262
+      handles.cbar_axes = cbar_axes;
2263
+      handles.cbarminmax_axes = cbarminmax_axes;
2264
+
2265
+   end
2266
+
2267
+   nii_view.handles = handles;		% store handles
2268
+
2269
+   nii_view.usepanel = usepanel;		% whole panel at low right cornor
2270
+   nii_view.usestretch = usestretch;	% stretch display of voxel_size
2271
+   nii_view.useinterp = useinterp;	% use interpolation
2272
+   nii_view.colorindex = colorindex;	% store colorindex variable
2273
+   nii_view.buttondown = buttondown;	% command after button down click
2274
+   nii_view.cbarminmax = cbarminmax;	% store min max value for colorbar
2275
+
2276
+   set_coordinates(nii_view,useinterp);	% coord unit
2277
+
2278
+   if ~isfield(nii_view, 'axi_xhair') |  ...
2279
+      ~isfield(nii_view, 'cor_xhair') |  ...
2280
+      ~isfield(nii_view, 'sag_xhair')
2281
+
2282
+      nii_view.axi_xhair = [];			% top cross hair
2283
+      nii_view.cor_xhair = [];			% front cross hair
2284
+      nii_view.sag_xhair = [];			% side cross hair
2285
+
2286
+   end
2287
+
2288
+   if ~isempty(color_map)
2289
+      nii_view.color_map = color_map;
2290
+   end
2291
+
2292
+   if ~isempty(colorlevel)
2293
+      nii_view.colorlevel = colorlevel;
2294
+   end
2295
+
2296
+   if ~isempty(highcolor)
2297
+      nii_view.highcolor = highcolor;
2298
+   end
2299
+
2300
+   update_nii_view(nii_view);
2301
+
2302
+   if ~isempty(setunit)
2303
+      update_unit(fig, setunit);
2304
+   end
2305
+
2306
+   if ~isempty(setviewpoint)
2307
+      update_viewpoint(fig, setviewpoint);
2308
+   end
2309
+
2310
+   if ~isempty(setcrosshaircolor)
2311
+      update_crosshaircolor(fig, setcrosshaircolor);
2312
+   end
2313
+
2314
+   if ~isempty(usecrosshair)
2315
+      update_usecrosshair(fig, usecrosshair);
2316
+   end
2317
+
2318
+   nii_menu = getappdata(fig, 'nii_menu');
2319
+
2320
+   if ~isempty(nii_menu)
2321
+      if nii.hdr.dime.datatype == 128 | nii.hdr.dime.datatype == 511
2322
+         set(nii_menu.Minterp,'Userdata',1,'Label','Interp on','enable','off');
2323
+      elseif useinterp
2324
+         set(nii_menu.Minterp,'Userdata',0,'Label','Interp off');
2325
+      else
2326
+         set(nii_menu.Minterp,'Userdata',1,'Label','Interp on');
2327
+      end
2328
+   end
2329
+
2330
+   windowbuttonmotion = get(fig, 'windowbuttonmotion');
2331
+   windowbuttonmotion = [windowbuttonmotion '; view_nii(''move_cursor'');'];
2332
+   set(fig, 'windowbuttonmotion', windowbuttonmotion);
2333
+
2334
+   return;						% init
2335
+
2336
+
2337
+%----------------------------------------------------------------
2338
+function fig = update_img(img, fig, opt)
2339
+
2340
+   nii_menu = getappdata(fig,'nii_menu');
2341
+
2342
+   if ~isempty(nii_menu)
2343
+      set(nii_menu.Mzoom,'Userdata',1,'Label','Zoom on');   
2344
+      set(fig,'pointer','arrow');
2345
+      zoom off;
2346
+   end
2347
+
2348
+   nii_view = getappdata(fig,'nii_view');
2349
+   change_interp = 0;
2350
+
2351
+   if isfield(opt, 'useinterp') & opt.useinterp ~= nii_view.useinterp
2352
+      nii_view.useinterp = opt.useinterp;
2353
+      change_interp = 1;
2354
+   end
2355
+
2356
+   setscanid = 1;
2357
+
2358
+   if isfield(opt, 'setscanid')
2359
+      setscanid = round(opt.setscanid);
2360
+
2361
+      if setscanid < 1
2362
+         setscanid = 1;
2363
+      end
2364
+
2365
+      if setscanid > nii_view.numscan
2366
+         setscanid = nii_view.numscan;
2367
+      end
2368
+   end
2369
+
2370
+   if isfield(opt, 'glblocminmax') & ~isempty(opt.glblocminmax)
2371
+      minvalue = opt.glblocminmax(1);
2372
+      maxvalue = opt.glblocminmax(2);
2373
+   else
2374
+      minvalue = double(min(img(:,:,:,setscanid)));
2375
+      minvalue = min(minvalue(:));
2376
+      maxvalue = double(max(img(:,:,:,setscanid)));
2377
+      maxvalue = max(maxvalue(:));
2378
+   end
2379
+
2380
+   if isfield(opt, 'setvalue')
2381
+      setvalue = opt.setvalue;
2382
+
2383
+      if isfield(opt, 'glblocminmax') & ~isempty(opt.glblocminmax)
2384
+         minvalue = opt.glblocminmax(1);
2385
+         maxvalue = opt.glblocminmax(2);
2386
+      else
2387
+         minvalue = double(min(setvalue.val));
2388
+         maxvalue = double(max(setvalue.val));
2389
+      end
2390
+
2391
+      bgimg = img;
2392
+      minbg = min(bgimg(:));
2393
+      maxbg = max(bgimg(:));
2394
+      bgimg = scale_in(bgimg, minbg, maxbg, 54) + 200;	% scale to 202~256 (201 is used for highcolor part tolerance)
2395
+
2396
+      cbarminmax = [minvalue maxvalue];
2397
+
2398
+      if nii_view.useinterp
2399
+
2400
+         %  scale signal data to 1~200
2401
+         %
2402
+         img = repmat(nan, size(img));
2403
+         img(setvalue.idx) = setvalue.val;
2404
+
2405
+         %  199 level for source image (map highest color to 199 instead of 200, give 1 level of tolerance)
2406
+         %
2407
+         bgimg = single(scale_out(bgimg, cbarminmax(1), cbarminmax(2), 198));
2408
+
2409
+      else
2410
+
2411
+         bgimg(setvalue.idx) = 0;
2412
+
2413
+         %  scale signal data to 1~200
2414
+         %
2415
+         img = zeros(size(img));
2416
+         img(setvalue.idx) = scale_in(setvalue.val, minvalue, maxvalue, 198);
2417
+         img = img + bgimg;
2418
+         bgimg = [];
2419
+         img = scale_out(img, cbarminmax(1), cbarminmax(2), 198);
2420
+
2421
+         minvalue = double(min(img(:)));
2422
+         maxvalue = double(max(img(:)));
2423
+
2424
+         if isfield(opt,'glblocminmax') & ~isempty(opt.glblocminmax)
2425
+            minvalue = opt.glblocminmax(1);
2426
+         end
2427
+
2428
+      end
2429
+
2430
+      nii_view.bgimg = bgimg;
2431
+      nii_view.setvalue = setvalue;
2432
+   else
2433
+      cbarminmax = [minvalue maxvalue];
2434
+   end
2435
+
2436
+   update_cbarminmax(fig, cbarminmax);
2437
+   nii_view.cbarminmax = cbarminmax;
2438
+   nii_view.nii.img = img;
2439
+   nii_view.minvalue = minvalue;
2440
+   nii_view.maxvalue = maxvalue;
2441
+   nii_view.scanid = setscanid;
2442
+   change_colormap(fig);
2443
+
2444
+   %  init color (gray) scaling to make sure the slice clim take the
2445
+   %  global clim [min(nii.img(:)) max(nii.img(:))]
2446
+   %
2447
+   if isempty(nii_view.bgimg)
2448
+      clim = [minvalue maxvalue];
2449
+   else
2450
+      clim = [minvalue double(max(nii_view.bgimg(:)))];
2451
+   end
2452
+
2453
+   if clim(1) == clim(2)
2454
+      clim(2) = clim(1) + 0.000001;
2455
+   end
2456
+
2457
+   if strcmpi(get(nii_view.handles.axial_image,'cdatamapping'), 'direct')
2458
+      useimagesc = 0;
2459
+   else
2460
+      useimagesc = 1;
2461
+   end
2462
+
2463
+   if ~isempty(nii_view.bgimg)			% with interpolation
2464
+
2465
+      Saxi = squeeze(nii_view.bgimg(:,:,nii_view.slices.axi));
2466
+
2467
+      if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg)
2468
+         set(nii_view.handles.axial_bg,'CData',Saxi');
2469
+      else
2470
+         axes(nii_view.handles.axial_axes);
2471
+
2472
+         if useimagesc
2473
+            nii_view.handles.axial_bg = surface(zeros(size(Saxi')),double(Saxi'),'edgecolor','none','facecolor','interp');
2474
+         else
2475
+            nii_view.handles.axial_bg = surface(zeros(size(Saxi')),double(Saxi'),'cdatamapping','direct','edgecolor','none','facecolor','interp');
2476
+         end
2477
+
2478
+         order = get(gca,'child');
2479
+         order(find(order == nii_view.handles.axial_bg)) = [];
2480
+         order = [order; nii_view.handles.axial_bg];
2481
+         set(gca, 'child', order);
2482
+      end
2483
+
2484
+   end
2485
+
2486
+   if isfield(nii_view.handles,'axial_image'),
2487
+      if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
2488
+         Saxi = squeeze(nii_view.nii.img(:,:,nii_view.slices.axi,:,setscanid));
2489
+         Saxi = permute(Saxi, [2 1 3]);
2490
+      else
2491
+         Saxi = squeeze(nii_view.nii.img(:,:,nii_view.slices.axi,setscanid));
2492
+         Saxi = Saxi';
2493
+      end
2494
+
2495
+      set(nii_view.handles.axial_image,'CData',Saxi);
2496
+   end
2497
+
2498
+   set(nii_view.handles.axial_axes,'CLim',clim);
2499
+
2500
+   if ~isempty(nii_view.bgimg)
2501
+      Scor = squeeze(nii_view.bgimg(:,nii_view.slices.cor,:));
2502
+
2503
+      if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg)
2504
+         set(nii_view.handles.coronal_bg,'CData',Scor');
2505
+      else
2506
+         axes(nii_view.handles.coronal_axes);
2507
+
2508
+         if useimagesc
2509
+            nii_view.handles.coronal_bg = surface(zeros(size(Scor')),double(Scor'),'edgecolor','none','facecolor','interp');
2510
+         else
2511
+            nii_view.handles.coronal_bg = surface(zeros(size(Scor')),double(Scor'),'cdatamapping','direct','edgecolor','none','facecolor','interp');
2512
+         end
2513
+
2514
+         order = get(gca,'child');
2515
+         order(find(order == nii_view.handles.coronal_bg)) = [];
2516
+         order = [order; nii_view.handles.coronal_bg];
2517
+         set(gca, 'child', order);
2518
+      end
2519
+   end
2520
+
2521
+   if isfield(nii_view.handles,'coronal_image'),
2522
+      if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
2523
+         Scor = squeeze(nii_view.nii.img(:,nii_view.slices.cor,:,:,setscanid));
2524
+         Scor = permute(Scor, [2 1 3]);
2525
+      else
2526
+         Scor = squeeze(nii_view.nii.img(:,nii_view.slices.cor,:,setscanid));
2527
+         Scor = Scor';
2528
+      end
2529
+
2530
+      set(nii_view.handles.coronal_image,'CData',Scor);
2531
+   end
2532
+
2533
+   set(nii_view.handles.coronal_axes,'CLim',clim);
2534
+
2535
+   if ~isempty(nii_view.bgimg)
2536
+      Ssag = squeeze(nii_view.bgimg(nii_view.slices.sag,:,:));
2537
+
2538
+      if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg)
2539
+         set(nii_view.handles.sagittal_bg,'CData',Ssag');
2540
+      else
2541
+         axes(nii_view.handles.sagittal_axes);
2542
+
2543
+         if useimagesc
2544
+            nii_view.handles.sagittal_bg = surface(zeros(size(Ssag')),double(Ssag'),'edgecolor','none','facecolor','interp');
2545
+         else
2546
+            nii_view.handles.sagittal_bg = surface(zeros(size(Ssag')),double(Ssag'),'cdatamapping','direct','edgecolor','none','facecolor','interp');
2547
+         end
2548
+
2549
+         order = get(gca,'child');
2550
+         order(find(order == nii_view.handles.sagittal_bg)) = [];
2551
+         order = [order; nii_view.handles.sagittal_bg];
2552
+         set(gca, 'child', order);
2553
+      end
2554
+   end
2555
+
2556
+   if isfield(nii_view.handles,'sagittal_image'),
2557
+      if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
2558
+         Ssag = squeeze(nii_view.nii.img(nii_view.slices.sag,:,:,:,setscanid));
2559
+         Ssag = permute(Ssag, [2 1 3]);
2560
+      else
2561
+         Ssag = squeeze(nii_view.nii.img(nii_view.slices.sag,:,:,setscanid));
2562
+         Ssag = Ssag';
2563
+      end
2564
+
2565
+      set(nii_view.handles.sagittal_image,'CData',Ssag);
2566
+   end
2567
+
2568
+   set(nii_view.handles.sagittal_axes,'CLim',clim);
2569
+
2570
+   update_nii_view(nii_view);
2571
+
2572
+   if isfield(opt, 'setvalue')
2573
+
2574
+      if ~isfield(nii_view,'highcolor') | ~isequal(size(nii_view.highcolor),[56 3])
2575
+
2576
+         %  55 level for brain structure (paded 0 for highcolor level 1, i.e. normal level 201, to make 56 highcolor)
2577
+         %
2578
+         update_highcolor(fig, [zeros(1,3);gray(55)], []);
2579
+
2580
+      end
2581
+
2582
+      if nii_view.colorindex ~= 2
2583
+         update_colorindex(fig, 2);
2584
+      end
2585
+
2586
+      old_color = get(nii_view.handles.xhair_color,'user');
2587
+
2588
+      if isequal(old_color, [1 0 0])
2589
+         update_crosshaircolor(fig, [1 1 0]);
2590
+      end
2591
+
2592
+%      if change_interp
2593
+ %        update_useinterp(fig, nii_view.useinterp);
2594
+  %    end
2595
+
2596
+   end
2597
+
2598
+   if change_interp
2599
+      update_useinterp(fig, nii_view.useinterp);
2600
+   end
2601
+
2602
+   return;						% update_img
2603
+
2604
+
2605
+%----------------------------------------------------------------
2606
+function [top_pos, front_pos, side_pos] = ...
2607
+			axes_pos(fig,area,vol_size,usestretch)
2608
+
2609
+   set(fig,'unit','pixel');
2610
+
2611
+   fig_pos = get(fig,'position');
2612
+
2613
+   gap_x = 15/fig_pos(3);		% width of vertical scrollbar
2614
+   gap_y = 15/fig_pos(4);		% width of horizontal scrollbar
2615
+
2616
+   a = (area(3) - gap_x * 1.3) * fig_pos(3) / (vol_size(1) + vol_size(2));	% no crosshair lost in zoom
2617
+   b = (area(4) - gap_y * 3) * fig_pos(4) / (vol_size(2) + vol_size(3));
2618
+   c = min([a b]);			% make sure 'ax' is inside 'area'
2619
+
2620
+   top_w = vol_size(1) * c / fig_pos(3);
2621
+   side_w = vol_size(2) * c / fig_pos(3);
2622
+   top_h = vol_size(2) * c / fig_pos(4);
2623
+   side_h = vol_size(3) * c / fig_pos(4);
2624
+   side_x = area(1) + top_w + gap_x * 1.3;	% no crosshair lost in zoom
2625
+   side_y = area(2) + top_h + gap_y * 3;
2626
+
2627
+   if usestretch
2628
+      if a > b				% top touched ceiling, use b
2629
+         d = (area(3) - gap_x * 1.3) / (top_w + side_w);	% no crosshair lost in zoom
2630
+         top_w = top_w * d;
2631
+         side_w = side_w * d;
2632
+         side_x = area(1) + top_w + gap_x * 1.3;	% no crosshair lost in zoom
2633
+      else
2634
+         d = (area(4) - gap_y * 3) / (top_h + side_h);
2635
+         top_h = top_h * d;
2636
+         side_h = side_h * d;
2637
+         side_y = area(2) + top_h + gap_y * 3;
2638
+      end
2639
+   end
2640
+
2641
+   top_pos = [area(1) area(2)+gap_y top_w top_h];
2642
+   front_pos = [area(1) side_y top_w side_h];
2643
+   side_pos = [side_x side_y side_w side_h];
2644
+
2645
+   set(fig,'unit','normal');
2646
+
2647
+   return;						% axes_pos
2648
+
2649
+
2650
+%----------------------------------------------------------------
2651
+function [top_ax, front_ax, side_ax] ...
2652
+		= create_ax(fig, area, vol_size, usestretch)
2653
+
2654
+   cur_fig = gcf;			% save h_wait fig
2655
+   figure(fig);
2656
+
2657
+   [top_pos, front_pos, side_pos] = ...
2658
+			axes_pos(fig,area,vol_size,usestretch);
2659
+
2660
+   nii_view = getappdata(fig, 'nii_view');
2661
+
2662
+   if isempty(nii_view)
2663
+      top_ax = axes('position', top_pos);
2664
+      front_ax = axes('position', front_pos);
2665
+      side_ax = axes('position', side_pos);
2666
+   else
2667
+      top_ax = nii_view.handles.axial_axes;
2668
+      front_ax = nii_view.handles.coronal_axes;
2669
+      side_ax = nii_view.handles.sagittal_axes;
2670
+
2671
+      set(top_ax, 'position', top_pos);
2672
+      set(front_ax, 'position', front_pos);
2673
+      set(side_ax, 'position', side_pos);
2674
+   end
2675
+
2676
+   figure(cur_fig);
2677
+
2678
+   return;						% create_ax
2679
+
2680
+
2681
+%----------------------------------------------------------------
2682
+function [cbar_axes, cbarminmax_axes] = create_cbar_axes(fig, cbar_area, nii_view)
2683
+
2684
+   if isempty(cbar_area)		% without_cbar
2685
+      cbar_axes = [];
2686
+      cbarminmax_axes = [];
2687
+      return;
2688
+   end
2689
+
2690
+   cur_fig = gcf;			% save h_wait fig
2691
+   figure(fig);
2692
+
2693
+   if ~exist('nii_view', 'var')
2694
+      nii_view = getappdata(fig, 'nii_view');
2695
+   end
2696
+
2697
+   if isempty(nii_view) | ~isfield(nii_view.handles,'cbar_axes') | isempty(nii_view.handles.cbar_axes)
2698
+      cbarminmax_axes = axes('position', cbar_area);
2699
+      cbar_axes = axes('position', cbar_area);
2700
+   else
2701
+      cbarminmax_axes = nii_view.handles.cbarminmax_axes;
2702
+      cbar_axes = nii_view.handles.cbar_axes;
2703
+      set(cbarminmax_axes, 'position', cbar_area);
2704
+      set(cbar_axes, 'position', cbar_area);
2705
+   end
2706
+
2707
+   figure(cur_fig);
2708
+
2709
+   return;					% create_cbar_axes
2710
+
2711
+
2712
+%----------------------------------------------------------------
2713
+function h1 = plot_view(fig, x, y, img_ax, img_slice, clim, ...
2714
+	cbarminmax, handles, useimagesc, colorindex, color_map, ...
2715
+	colorlevel, highcolor, useinterp, numscan)
2716
+
2717
+   h1 = [];
2718
+
2719
+   if x > 1 & y > 1,
2720
+
2721
+      axes(img_ax);
2722
+
2723
+      nii_view = getappdata(fig, 'nii_view');
2724
+
2725
+      if isempty(nii_view)
2726
+
2727
+         %  set colormap first
2728
+         %
2729
+         nii.handles = handles;
2730
+         nii.handles.axial_axes = img_ax;
2731
+         nii.colorindex = colorindex;
2732
+         nii.color_map = color_map;
2733
+         nii.colorlevel = colorlevel;
2734
+         nii.highcolor = highcolor;
2735
+         nii.numscan = numscan;
2736
+
2737
+         change_colormap(fig, nii, colorindex, cbarminmax);
2738
+
2739
+         if useinterp
2740
+            if useimagesc
2741
+               h1 = surface(zeros(size(img_slice)),double(img_slice),'edgecolor','none','facecolor','interp');
2742
+            else
2743
+               h1 = surface(zeros(size(img_slice)),double(img_slice),'cdatamapping','direct','edgecolor','none','facecolor','interp');
2744
+            end
2745
+
2746
+            set(gca,'clim',clim);
2747
+         else
2748
+            if useimagesc
2749
+               h1 = imagesc(img_slice,clim);
2750
+            else
2751
+               h1 = image(img_slice);
2752
+            end
2753
+
2754
+            set(gca,'clim',clim);
2755
+         end
2756
+
2757
+      else
2758
+
2759
+         h1 = nii_view.handles.axial_image;
2760
+
2761
+         if ~isequal(get(h1,'parent'), img_ax)
2762
+            h1 = nii_view.handles.coronal_image;
2763
+         end
2764
+
2765
+         if ~isequal(get(h1,'parent'), img_ax)
2766
+            h1 = nii_view.handles.sagittal_image;
2767
+         end
2768
+
2769
+         set(h1, 'cdata', img_slice);
2770
+         set(h1, 'xdata', 1:size(img_slice,2));
2771
+         set(h1, 'ydata', 1:size(img_slice,1));
2772
+
2773
+      end
2774
+
2775
+      set(img_ax,'YDir','normal','XLimMode','manual','YLimMode','manual',...
2776
+         'ClimMode','manual','visible','off', ...
2777
+         'xtick',[],'ytick',[], 'clim', clim);
2778
+
2779
+   end
2780
+
2781
+   return;						% plot_view
2782
+
2783
+
2784
+%----------------------------------------------------------------
2785
+function h1 = plot_cbar(fig, cbar_axes, cbarminmax_axes, cbarminmax, ...
2786
+	level, handles, useimagesc, colorindex, color_map, ...
2787
+	colorlevel, highcolor, niiclass, numscan, nii_view)
2788
+
2789
+   cbar_image = [1:level]';
2790
+
2791
+   %  In a uint8 or uint16 indexed image, 0 points to the first row 
2792
+   %  in the colormap
2793
+   %
2794
+   if 0 % strcmpi(niiclass,'uint8') | strcmpi(niiclass,'uint16')
2795
+      % we use single for display anyway
2796
+      ylim = [0, level-1];
2797
+   else
2798
+      ylim = [1, level];
2799
+   end
2800
+
2801
+   axes(cbarminmax_axes);
2802
+
2803
+   plot([0 0], cbarminmax, 'w');
2804
+   axis tight;
2805
+
2806
+   set(cbarminmax_axes,'YDir','normal', ...
2807
+      'XLimMode','manual','YLimMode','manual','YColor',[0 0 0], ...
2808
+      'XColor',[0 0 0],'xtick',[],'YAxisLocation','right');
2809
+
2810
+   ylimb = get(cbarminmax_axes,'ylim');
2811
+   ytickb = get(cbarminmax_axes,'ytick');
2812
+   ytick=(ylim(2)-ylim(1))*(ytickb-ylimb(1))/(ylimb(2)-ylimb(1))+ylim(1);
2813
+
2814
+   axes(cbar_axes);
2815
+
2816
+   if ~exist('nii_view', 'var')
2817
+      nii_view = getappdata(fig, 'nii_view');
2818
+   end
2819
+
2820
+   if isempty(nii_view) | ~isfield(nii_view.handles,'cbar_image') | isempty(nii_view.handles.cbar_image)
2821
+
2822
+      %  set colormap first
2823
+      %
2824
+      nii.handles = handles;
2825
+      nii.colorindex = colorindex;
2826
+      nii.color_map = color_map;
2827
+      nii.colorlevel = colorlevel;
2828
+      nii.highcolor = highcolor;
2829
+      nii.numscan = numscan;
2830
+
2831
+      change_colormap(fig, nii, colorindex, cbarminmax);
2832
+      h1 = image([0,1], [ylim(1),ylim(2)], cbar_image);
2833
+
2834
+   else
2835
+      h1 = nii_view.handles.cbar_image;
2836
+      set(h1, 'cdata', cbar_image);
2837
+   end
2838
+
2839
+   set(cbar_axes,'YDir','normal','XLimMode','manual', ...
2840
+	'YLimMode','manual','YColor',[0 0 0],'XColor',[0 0 0],'xtick',[], ...
2841
+	'YAxisLocation','right','ylim',ylim,'ytick',ytick,'yticklabel','');
2842
+
2843
+   return;						% plot_cbar
2844
+
2845
+
2846
+%----------------------------------------------------------------
2847
+function set_coordinates(nii_view,useinterp)
2848
+
2849
+    imgPlim.vox = nii_view.dims;
2850
+    imgNlim.vox = [1 1 1];
2851
+
2852
+    if useinterp    
2853
+       xdata_ax = [imgNlim.vox(1) imgPlim.vox(1)];
2854
+       ydata_ax = [imgNlim.vox(2) imgPlim.vox(2)];
2855
+       zdata_ax = [imgNlim.vox(3) imgPlim.vox(3)];
2856
+    else
2857
+       xdata_ax = [imgNlim.vox(1)-0.5 imgPlim.vox(1)+0.5];
2858
+       ydata_ax = [imgNlim.vox(2)-0.5 imgPlim.vox(2)+0.5];
2859
+       zdata_ax = [imgNlim.vox(3)-0.5 imgPlim.vox(3)+0.5];
2860
+    end
2861
+
2862
+    if isfield(nii_view.handles,'axial_image') & ~isempty(nii_view.handles.axial_image)
2863
+        set(nii_view.handles.axial_axes,'Xlim',xdata_ax);
2864
+        set(nii_view.handles.axial_axes,'Ylim',ydata_ax);
2865
+    end;
2866
+    if isfield(nii_view.handles,'coronal_image') & ~isempty(nii_view.handles.coronal_image)
2867
+        set(nii_view.handles.coronal_axes,'Xlim',xdata_ax);
2868
+        set(nii_view.handles.coronal_axes,'Ylim',zdata_ax);
2869
+    end;
2870
+    if isfield(nii_view.handles,'sagittal_image') & ~isempty(nii_view.handles.sagittal_image)
2871
+        set(nii_view.handles.sagittal_axes,'Xlim',ydata_ax);
2872
+        set(nii_view.handles.sagittal_axes,'Ylim',zdata_ax);
2873
+    end;
2874
+
2875
+    return						% set_coordinates
2876
+
2877
+
2878
+%----------------------------------------------------------------
2879
+function set_image_value(nii_view),
2880
+
2881
+    %  get coordinates of selected voxel and the image intensity there
2882
+    %
2883
+    sag = round(nii_view.slices.sag);
2884
+    cor = round(nii_view.slices.cor);
2885
+    axi = round(nii_view.slices.axi);
2886
+
2887
+    if 0 % isfield(nii_view, 'disp')
2888
+       img = nii_view.disp;    
2889
+    else
2890
+       img = nii_view.nii.img;
2891
+    end
2892
+
2893
+    if nii_view.nii.hdr.dime.datatype == 128
2894
+       imgvalue = [double(img(sag,cor,axi,1,nii_view.scanid)) double(img(sag,cor,axi,2,nii_view.scanid)) double(img(sag,cor,axi,3,nii_view.scanid))];
2895
+       set(nii_view.handles.imval,'Value',imgvalue);
2896
+       set(nii_view.handles.imval,'String',sprintf('%7.4g %7.4g %7.4g',imgvalue));
2897
+    elseif nii_view.nii.hdr.dime.datatype == 511
2898
+       R = double(img(sag,cor,axi,1,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
2899
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
2900
+       G = double(img(sag,cor,axi,2,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
2901
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
2902
+       B = double(img(sag,cor,axi,3,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
2903
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
2904
+       imgvalue = [double(img(sag,cor,axi,1,nii_view.scanid)) double(img(sag,cor,axi,2,nii_view.scanid)) double(img(sag,cor,axi,3,nii_view.scanid))];
2905
+       set(nii_view.handles.imval,'Value',imgvalue);
2906
+       imgvalue = [R G B];
2907
+       set(nii_view.handles.imval,'String',sprintf('%7.4g %7.4g %7.4g',imgvalue));
2908
+    else
2909
+       imgvalue = double(img(sag,cor,axi,nii_view.scanid));
2910
+       set(nii_view.handles.imval,'Value',imgvalue);
2911
+
2912
+       if isnan(imgvalue) | imgvalue > nii_view.cbarminmax(2)
2913
+          imgvalue = 0;
2914
+       end
2915
+
2916
+       set(nii_view.handles.imval,'String',sprintf('%.6g',imgvalue));
2917
+    end
2918
+
2919
+    % Now update the coordinates of the selected voxel
2920
+
2921
+    nii_view = update_imgXYZ(nii_view);
2922
+
2923
+    if get(nii_view.handles.coord,'value') == 1,
2924
+       sag = nii_view.imgXYZ.vox(1);
2925
+       cor = nii_view.imgXYZ.vox(2);
2926
+       axi = nii_view.imgXYZ.vox(3);
2927
+       org = nii_view.origin;
2928
+    elseif get(nii_view.handles.coord,'value') == 2,
2929
+       sag = nii_view.imgXYZ.mm(1);
2930
+       cor = nii_view.imgXYZ.mm(2);
2931
+       axi = nii_view.imgXYZ.mm(3);
2932
+       org = [0 0 0];
2933
+    elseif get(nii_view.handles.coord,'value') == 3,
2934
+       sag = nii_view.imgXYZ.tal(1);
2935
+       cor = nii_view.imgXYZ.tal(2);
2936
+       axi = nii_view.imgXYZ.tal(3);
2937
+       org = [0 0 0];
2938
+    end
2939
+
2940
+    set(nii_view.handles.impos,'Value',[sag,cor,axi]);
2941
+
2942
+    if get(nii_view.handles.coord,'value') == 1,
2943
+        string = sprintf('%7.0f %7.0f %7.0f',sag,cor,axi);
2944
+        org_str = sprintf('%7.0f %7.0f %7.0f', org(1), org(2), org(3));
2945
+    else
2946
+        string = sprintf('%7.1f %7.1f %7.1f',sag,cor,axi);
2947
+        org_str = sprintf('%7.1f %7.1f %7.1f', org(1), org(2), org(3));
2948
+    end;
2949
+    
2950
+    set(nii_view.handles.impos,'String',string);
2951
+    set(nii_view.handles.origin, 'string', org_str);
2952
+
2953
+    return						% set_image_value
2954
+
2955
+
2956
+%----------------------------------------------------------------
2957
+function nii_view = get_slice_position(nii_view,view),
2958
+
2959
+    %  obtain slices that is in correct unit, then update slices
2960
+    %
2961
+    slices = nii_view.slices;
2962
+	
2963
+    switch view,
2964
+    case 'sag',
2965
+        currentpoint = get(nii_view.handles.sagittal_axes,'CurrentPoint');
2966
+        slices.cor = currentpoint(1,1);
2967
+        slices.axi = currentpoint(1,2);
2968
+    case 'cor',
2969
+        currentpoint = get(nii_view.handles.coronal_axes,'CurrentPoint');
2970
+        slices.sag = currentpoint(1,1);
2971
+        slices.axi = currentpoint(1,2);
2972
+    case 'axi',
2973
+        currentpoint = get(nii_view.handles.axial_axes,'CurrentPoint');
2974
+        slices.sag = currentpoint(1,1);
2975
+        slices.cor = currentpoint(1,2);
2976
+    end
2977
+
2978
+    %  update nii_view.slices with the updated slices
2979
+    %    
2980
+    nii_view.slices.axi = round(slices.axi);
2981
+    nii_view.slices.cor = round(slices.cor);
2982
+    nii_view.slices.sag = round(slices.sag);
2983
+
2984
+    return						% get_slice_position
2985
+
2986
+
2987
+%----------------------------------------------------------------
2988
+function nii_view = get_slider_position(nii_view),
2989
+
2990
+    [nii_view.slices.sag,nii_view.slices.cor,nii_view.slices.axi] = deal(0);
2991
+    
2992
+    if isfield(nii_view.handles,'sagittal_slider'),
2993
+        if ishandle(nii_view.handles.sagittal_slider),
2994
+            nii_view.slices.sag = ...
2995
+		round(get(nii_view.handles.sagittal_slider,'Value'));
2996
+        end
2997
+    end
2998
+    
2999
+    if isfield(nii_view.handles,'coronal_slider'),
3000
+        if ishandle(nii_view.handles.coronal_slider),
3001
+            nii_view.slices.cor = ...
3002
+		round(nii_view.dims(2) - ...
3003
+		get(nii_view.handles.coronal_slider,'Value') + 1);
3004
+        end
3005
+    end
3006
+    
3007
+    if isfield(nii_view.handles,'axial_slider'),
3008
+        if ishandle(nii_view.handles.axial_slider),
3009
+            nii_view.slices.axi = ...
3010
+		round(get(nii_view.handles.axial_slider,'Value'));
3011
+        end
3012
+    end
3013
+
3014
+    nii_view = check_slices(nii_view);
3015
+
3016
+    return						% get_slider_position
3017
+
3018
+
3019
+%----------------------------------------------------------------
3020
+function nii_view = update_imgXYZ(nii_view),
3021
+
3022
+   nii_view.imgXYZ.vox = ...
3023
+	[nii_view.slices.sag,nii_view.slices.cor,nii_view.slices.axi];
3024
+   nii_view.imgXYZ.mm = ...
3025
+	(nii_view.imgXYZ.vox - nii_view.origin) .* nii_view.voxel_size;
3026
+%   nii_view.imgXYZ.tal = mni2tal(nii_view.imgXYZ.mni);
3027
+
3028
+   return						% update_imgXYZ
3029
+
3030
+
3031
+%----------------------------------------------------------------
3032
+function nii_view = convert2voxel(nii_view,slices),
3033
+
3034
+    if get(nii_view.handles.coord,'value') == 1,
3035
+
3036
+        %  [slices.axi, slices.cor, slices.sag] are in vox
3037
+        %
3038
+        nii_view.slices.axi = round(slices.axi);
3039
+        nii_view.slices.cor = round(slices.cor);
3040
+        nii_view.slices.sag = round(slices.sag);
3041
+
3042
+    elseif get(nii_view.handles.coord,'value') == 2,
3043
+
3044
+        %  [slices.axi, slices.cor, slices.sag] are in mm
3045
+        %
3046
+        xpix = nii_view.voxel_size(1);
3047
+        ypix = nii_view.voxel_size(2);
3048
+        zpix = nii_view.voxel_size(3);
3049
+
3050
+        nii_view.slices.axi = round(slices.axi / zpix + nii_view.origin(3));
3051
+        nii_view.slices.cor = round(slices.cor / ypix + nii_view.origin(2));
3052
+        nii_view.slices.sag = round(slices.sag / xpix + nii_view.origin(1));
3053
+    elseif get(nii_view.handles.coord,'value') == 3,
3054
+
3055
+        %  [slices.axi, slices.cor, slices.sag] are in talairach
3056
+        %
3057
+        xpix = nii_view.voxel_size(1);
3058
+        ypix = nii_view.voxel_size(2);
3059
+        zpix = nii_view.voxel_size(3);
3060
+
3061
+        xyz_tal = [slices.sag, slices.cor, slices.axi];
3062
+        xyz_mni = tal2mni(xyz_tal);
3063
+
3064
+        nii_view.slices.axi = round(xyz_mni(3) / zpix + nii_view.origin(3));
3065
+        nii_view.slices.cor = round(xyz_mni(2) / ypix + nii_view.origin(2));
3066
+        nii_view.slices.sag = round(xyz_mni(1) / xpix + nii_view.origin(1));
3067
+
3068
+    end
3069
+
3070
+    return						% convert2voxel
3071
+
3072
+
3073
+%----------------------------------------------------------------
3074
+function nii_view = check_slices(nii_view),
3075
+
3076
+    img = nii_view.nii.img;
3077
+    
3078
+    [ SagSize, CorSize, AxiSize, TimeSize ] = size(img);
3079
+    if nii_view.slices.sag > SagSize, nii_view.slices.sag = SagSize; end;
3080
+    if nii_view.slices.sag < 1, nii_view.slices.sag = 1; end;
3081
+    if nii_view.slices.cor > CorSize, nii_view.slices.cor = CorSize; end;
3082
+    if nii_view.slices.cor < 1, nii_view.slices.cor = 1; end;
3083
+    if nii_view.slices.axi > AxiSize, nii_view.slices.axi = AxiSize; end;
3084
+    if nii_view.slices.axi < 1, nii_view.slices.axi = 1; end;
3085
+    if nii_view.scanid > TimeSize, nii_view.scanid = TimeSize; end;
3086
+    if nii_view.scanid < 1, nii_view.scanid = 1; end;
3087
+    
3088
+    return						% check_slices
3089
+
3090
+
3091
+%----------------------------------------------------------------
3092
+%
3093
+%  keep this function small, since it will be called for every click
3094
+%
3095
+function nii_view = update_nii_view(nii_view)
3096
+
3097
+   %  add imgXYZ into nii_view struct
3098
+   %
3099
+   nii_view = check_slices(nii_view);
3100
+   nii_view = update_imgXYZ(nii_view);
3101
+
3102
+   %  update xhair
3103
+   %
3104
+   p_axi = nii_view.imgXYZ.vox([1 2]);
3105
+   p_cor = nii_view.imgXYZ.vox([1 3]);
3106
+   p_sag = nii_view.imgXYZ.vox([2 3]);
3107
+
3108
+   nii_view.axi_xhair = ...
3109
+	rri_xhair(p_axi, nii_view.axi_xhair, nii_view.handles.axial_axes);
3110
+
3111
+   nii_view.cor_xhair = ...
3112
+	rri_xhair(p_cor, nii_view.cor_xhair, nii_view.handles.coronal_axes);
3113
+
3114
+   nii_view.sag_xhair = ...
3115
+	rri_xhair(p_sag, nii_view.sag_xhair, nii_view.handles.sagittal_axes);
3116
+
3117
+   setappdata(nii_view.fig, 'nii_view', nii_view);
3118
+   set_image_value(nii_view);
3119
+
3120
+   return;						% update_nii_view
3121
+
3122
+
3123
+%----------------------------------------------------------------
3124
+function hist_plot(fig)
3125
+
3126
+   nii_view = getappdata(fig,'nii_view');
3127
+
3128
+   if isfield(nii_view, 'disp')
3129
+      img = nii_view.disp;    
3130
+   else
3131
+      img = nii_view.nii.img;
3132
+   end
3133
+
3134
+   img = double(img(:));
3135
+
3136
+   if length(unique(round(img))) == length(unique(img))
3137
+      is_integer = 1;
3138
+      range = max(img) - min(img) + 1;
3139
+      figure; hist(img, range);
3140
+      set(gca, 'xlim', [-range/5, max(img)]);
3141
+   else
3142
+      is_integer = 0;
3143
+      figure; hist(img);
3144
+   end
3145
+
3146
+   xlabel('Voxel Intensity');
3147
+   ylabel('Voxel Numbers for Each Intensity');
3148
+   set(gcf, 'NumberTitle','off','Name','Histogram Plot');
3149
+
3150
+   return;						% hist_plot
3151
+
3152
+
3153
+%----------------------------------------------------------------
3154
+function hist_eq(fig)
3155
+
3156
+   nii_view = getappdata(fig,'nii_view');
3157
+
3158
+   old_pointer = get(fig,'Pointer');
3159
+   set(fig,'Pointer','watch');
3160
+
3161
+   if get(nii_view.handles.hist_eq,'value')
3162
+      max_img = double(max(nii_view.nii.img(:)));
3163
+      tmp = double(nii_view.nii.img) / max_img;		% normalize for histeq
3164
+      tmp = histeq(tmp(:));
3165
+      nii_view.disp = reshape(tmp, size(nii_view.nii.img));
3166
+      min_disp = min(nii_view.disp(:));
3167
+      nii_view.disp = (nii_view.disp - min_disp);		% range having eq hist
3168
+      nii_view.disp = nii_view.disp * max_img / max(nii_view.disp(:));
3169
+      nii_view.disp = single(nii_view.disp);
3170
+   else
3171
+      if isfield(nii_view, 'disp')
3172
+         nii_view.disp = nii_view.nii.img;
3173
+      else
3174
+         set(fig,'Pointer',old_pointer);
3175
+         return;
3176
+      end
3177
+   end
3178
+
3179
+   %  update axial view
3180
+   %
3181
+   img_slice = squeeze(double(nii_view.disp(:,:,nii_view.slices.axi)));
3182
+   h1 = nii_view.handles.axial_image;
3183
+   set(h1, 'cdata', img_slice');
3184
+
3185
+   %  update coronal view
3186
+   %
3187
+   img_slice = squeeze(double(nii_view.disp(:,nii_view.slices.cor,:)));
3188
+   h1 = nii_view.handles.coronal_image;
3189
+   set(h1, 'cdata', img_slice');
3190
+
3191
+   %  update sagittal view
3192
+   %
3193
+   img_slice = squeeze(double(nii_view.disp(nii_view.slices.sag,:,:)));
3194
+
3195
+   h1 = nii_view.handles.sagittal_image;
3196
+   set(h1, 'cdata', img_slice');
3197
+
3198
+   %  remove disp field if un-check 'histeq' button
3199
+   %
3200
+   if ~get(nii_view.handles.hist_eq,'value') & isfield(nii_view, 'disp')
3201
+      nii_view = rmfield(nii_view, 'disp');
3202
+   end
3203
+
3204
+   update_nii_view(nii_view);
3205
+
3206
+   set(fig,'Pointer',old_pointer);
3207
+
3208
+   return;						% hist_eq
3209
+
3210
+
3211
+%----------------------------------------------------------------
3212
+function [top1_label, top2_label, side1_label, side2_label] = ...
3213
+		dir_label(fig, top_ax, front_ax, side_ax)
3214
+
3215
+   nii_view = getappdata(fig,'nii_view');
3216
+
3217
+   top_pos = get(top_ax,'position');
3218
+   front_pos = get(front_ax,'position');
3219
+   side_pos = get(side_ax,'position');
3220
+
3221
+   top_gap_x = (side_pos(1)-top_pos(1)-top_pos(3)) / (2*top_pos(3));
3222
+   top_gap_y = (front_pos(2)-top_pos(2)-top_pos(4)) / (2*top_pos(4));
3223
+   side_gap_x = (side_pos(1)-top_pos(1)-top_pos(3)) / (2*side_pos(3));
3224
+   side_gap_y = (front_pos(2)-top_pos(2)-top_pos(4)) / (2*side_pos(4));
3225
+
3226
+   top1_label_pos = [0, 1];			% rot0
3227
+   top2_label_pos = [1, 0];			% rot90
3228
+   side1_label_pos = [1, - side_gap_y];		% rot0
3229
+   side2_label_pos = [0, 0];			% rot90
3230
+
3231
+   if isempty(nii_view)
3232
+      axes(top_ax);
3233
+      top1_label = text(top1_label_pos(1),top1_label_pos(2), ...
3234
+	'== X =>', ...
3235
+	'vertical', 'bottom', ...
3236
+	'unit', 'normal', 'fontsize', 8);
3237
+
3238
+      axes(top_ax);
3239
+      top2_label = text(top2_label_pos(1),top2_label_pos(2), ...
3240
+	'== Y =>', ...
3241
+	'rotation', 90, 'vertical', 'top', ...
3242
+	'unit', 'normal', 'fontsize', 8);
3243
+
3244
+      axes(side_ax);
3245
+      side1_label = text(side1_label_pos(1),side1_label_pos(2), ...
3246
+	'<= Y ==', ...
3247
+	'horizontal', 'right', 'vertical', 'top', ...
3248
+	'unit', 'normal', 'fontsize', 8);
3249
+
3250
+      axes(side_ax);
3251
+      side2_label = text(side2_label_pos(1),side2_label_pos(2), ...
3252
+	'== Z =>', ...
3253
+	'rotation', 90, 'vertical', 'bottom', ...
3254
+	'unit', 'normal', 'fontsize', 8);
3255
+   else
3256
+      top1_label = nii_view.handles.top1_label;
3257
+      top2_label = nii_view.handles.top2_label;
3258
+      side1_label = nii_view.handles.side1_label;
3259
+      side2_label = nii_view.handles.side2_label;
3260
+
3261
+      set(top1_label, 'position', [top1_label_pos 0]);
3262
+      set(top2_label, 'position', [top2_label_pos 0]);
3263
+      set(side1_label, 'position', [side1_label_pos 0]);
3264
+      set(side2_label, 'position', [side2_label_pos 0]);
3265
+   end
3266
+
3267
+   return;						% dir_label
3268
+
3269
+
3270
+%----------------------------------------------------------------
3271
+function update_enable(h, opt);
3272
+
3273
+   nii_view = getappdata(h,'nii_view');
3274
+   handles = nii_view.handles;
3275
+
3276
+   if isfield(opt,'enablecursormove')
3277
+      if opt.enablecursormove
3278
+         v = 'on';
3279
+      else
3280
+         v = 'off';
3281
+      end
3282
+
3283
+      set(handles.Timposcur, 'visible', v);
3284
+      set(handles.imposcur, 'visible', v);
3285
+      set(handles.Timvalcur, 'visible', v);
3286
+      set(handles.imvalcur, 'visible', v);
3287
+   end
3288
+
3289
+   if isfield(opt,'enableviewpoint')
3290
+      if opt.enableviewpoint
3291
+         v = 'on';
3292
+      else
3293
+         v = 'off';
3294
+      end
3295
+
3296
+      set(handles.Timpos, 'visible', v);
3297
+      set(handles.impos, 'visible', v);
3298
+      set(handles.Timval, 'visible', v);
3299
+      set(handles.imval, 'visible', v);
3300
+   end
3301
+
3302
+   if isfield(opt,'enableorigin')
3303
+      if opt.enableorigin
3304
+         v = 'on';
3305
+      else
3306
+         v = 'off';
3307
+      end
3308
+
3309
+      set(handles.Torigin, 'visible', v);
3310
+      set(handles.origin, 'visible', v);
3311
+   end
3312
+
3313
+   if isfield(opt,'enableunit')
3314
+      if opt.enableunit
3315
+         v = 'on';
3316
+      else
3317
+         v = 'off';
3318
+      end
3319
+
3320
+      set(handles.Tcoord, 'visible', v);
3321
+      set(handles.coord_frame, 'visible', v);
3322
+      set(handles.coord, 'visible', v);
3323
+   end
3324
+
3325
+   if isfield(opt,'enablecrosshair')
3326
+      if opt.enablecrosshair
3327
+         v = 'on';
3328
+      else
3329
+         v = 'off';
3330
+      end
3331
+
3332
+      set(handles.Txhair, 'visible', v);
3333
+      set(handles.xhair_color, 'visible', v);
3334
+      set(handles.xhair, 'visible', v);
3335
+   end
3336
+
3337
+   if isfield(opt,'enablehistogram')
3338
+      if opt.enablehistogram
3339
+         v = 'on';
3340
+         vv = 'off';
3341
+      else
3342
+         v = 'off';
3343
+         vv = 'on';
3344
+      end
3345
+
3346
+      set(handles.Tcoord, 'visible', vv);
3347
+      set(handles.coord_frame, 'visible', vv);
3348
+      set(handles.coord, 'visible', vv);
3349
+
3350
+      set(handles.Thist, 'visible', v);
3351
+      set(handles.hist_frame, 'visible', v);
3352
+      set(handles.hist_eq, 'visible', v);
3353
+      set(handles.hist_plot, 'visible', v);
3354
+   end
3355
+
3356
+   if isfield(opt,'enablecolormap')
3357
+      if opt.enablecolormap
3358
+         v = 'on';
3359
+      else
3360
+         v = 'off';
3361
+      end
3362
+
3363
+      set(handles.Tcolor, 'visible', v);
3364
+      set(handles.color_frame, 'visible', v);
3365
+      set(handles.neg_color, 'visible', v);
3366
+      set(handles.colorindex, 'visible', v);
3367
+   end
3368
+
3369
+   if isfield(opt,'enablecontrast')
3370
+      if opt.enablecontrast
3371
+         v = 'on';
3372
+      else
3373
+         v = 'off';
3374
+      end
3375
+
3376
+      set(handles.Tcontrast, 'visible', v);
3377
+      set(handles.contrast_frame, 'visible', v);
3378
+      set(handles.contrast_def, 'visible', v);
3379
+      set(handles.contrast, 'visible', v);
3380
+   end
3381
+
3382
+   if isfield(opt,'enablebrightness')
3383
+      if opt.enablebrightness
3384
+         v = 'on';
3385
+      else
3386
+         v = 'off';
3387
+      end
3388
+
3389
+      set(handles.Tbrightness, 'visible', v);
3390
+      set(handles.brightness_frame, 'visible', v);
3391
+      set(handles.brightness_def, 'visible', v);
3392
+      set(handles.brightness, 'visible', v);
3393
+   end
3394
+
3395
+   if isfield(opt,'enabledirlabel')
3396
+      if opt.enabledirlabel
3397
+         v = 'on';
3398
+      else
3399
+         v = 'off';
3400
+      end
3401
+
3402
+      set(handles.top1_label, 'visible', v);
3403
+      set(handles.top2_label, 'visible', v);
3404
+      set(handles.side1_label, 'visible', v);
3405
+      set(handles.side2_label, 'visible', v);
3406
+   end
3407
+
3408
+   if isfield(opt,'enableslider')
3409
+      if opt.enableslider
3410
+         v = 'on';
3411
+      else
3412
+         v = 'off';
3413
+      end
3414
+
3415
+      if isfield(handles,'sagittal_slider') & ishandle(handles.sagittal_slider)
3416
+         set(handles.sagittal_slider, 'visible', v);
3417
+      end
3418
+
3419
+      if isfield(handles,'coronal_slider') & ishandle(handles.coronal_slider)
3420
+         set(handles.coronal_slider, 'visible', v);
3421
+      end
3422
+
3423
+      if isfield(handles,'axial_slider') & ishandle(handles.axial_slider)
3424
+         set(handles.axial_slider, 'visible', v);
3425
+      end
3426
+   end
3427
+
3428
+   return;					% update_enable
3429
+
3430
+
3431
+%----------------------------------------------------------------
3432
+function update_usepanel(fig, usepanel)
3433
+
3434
+   if isempty(usepanel)
3435
+      return;
3436
+   end
3437
+
3438
+   if usepanel
3439
+      opt.enablecursormove = 1;
3440
+      opt.enableviewpoint = 1;
3441
+      opt.enableorigin = 1;
3442
+      opt.enableunit = 1;
3443
+      opt.enablecrosshair = 1;
3444
+%      opt.enablehistogram = 1;
3445
+      opt.enablecolormap = 1;
3446
+      opt.enablecontrast = 1;
3447
+      opt.enablebrightness = 1;
3448
+   else
3449
+      opt.enablecursormove = 0;
3450
+      opt.enableviewpoint = 0;
3451
+      opt.enableorigin = 0;
3452
+      opt.enableunit = 0;
3453
+      opt.enablecrosshair = 0;
3454
+%      opt.enablehistogram = 0;
3455
+      opt.enablecolormap = 0;
3456
+      opt.enablecontrast = 0;
3457
+      opt.enablebrightness = 0;
3458
+   end
3459
+
3460
+   update_enable(fig, opt);
3461
+
3462
+   nii_view = getappdata(fig,'nii_view');
3463
+   nii_view.usepanel = usepanel;
3464
+   setappdata(fig,'nii_view',nii_view);
3465
+
3466
+   return;					% update_usepanel
3467
+
3468
+
3469
+%----------------------------------------------------------------
3470
+function update_usecrosshair(fig, usecrosshair)
3471
+
3472
+   if isempty(usecrosshair)
3473
+      return;
3474
+   end
3475
+
3476
+   if usecrosshair
3477
+      v=1;
3478
+   else
3479
+      v=2;
3480
+   end
3481
+
3482
+   nii_view = getappdata(fig,'nii_view');
3483
+   set(nii_view.handles.xhair,'value',v);
3484
+
3485
+   opt.command = 'crosshair';
3486
+   view_nii(fig, opt);
3487
+
3488
+   return;					% update_usecrosshair
3489
+
3490
+
3491
+%----------------------------------------------------------------
3492
+function update_usestretch(fig, usestretch)
3493
+
3494
+   nii_view = getappdata(fig,'nii_view');
3495
+
3496
+   handles = nii_view.handles;
3497
+   fig = nii_view.fig;
3498
+   area = nii_view.area;
3499
+   vol_size = nii_view.voxel_size .* nii_view.dims;
3500
+
3501
+   %  Three Axes & label
3502
+   %
3503
+   [top_ax, front_ax, side_ax] = ...
3504
+	create_ax(fig, area, vol_size, usestretch);
3505
+
3506
+   dir_label(fig, top_ax, front_ax, side_ax);
3507
+
3508
+   top_pos = get(top_ax,'position');
3509
+   front_pos = get(front_ax,'position');
3510
+   side_pos = get(side_ax,'position');
3511
+
3512
+   %  Sagittal Slider
3513
+   %
3514
+   x = side_pos(1);
3515
+   y = top_pos(2) + top_pos(4);
3516
+   w = side_pos(3);
3517
+   h = (front_pos(2) - y) / 2;
3518
+   y = y + h;
3519
+   pos = [x y w h];
3520
+
3521
+   if isfield(handles,'sagittal_slider') & ishandle(handles.sagittal_slider)
3522
+      set(handles.sagittal_slider,'position',pos);
3523
+   end
3524
+
3525
+   %  Coronal Slider
3526
+   %
3527
+   x = top_pos(1);
3528
+   y = top_pos(2) + top_pos(4);
3529
+   w = top_pos(3);
3530
+   h = (front_pos(2) - y) / 2;
3531
+   y = y + h;
3532
+   pos = [x y w h];
3533
+
3534
+   if isfield(handles,'coronal_slider') & ishandle(handles.coronal_slider)
3535
+      set(handles.coronal_slider,'position',pos);
3536
+   end
3537
+
3538
+   %  Axial Slider
3539
+   %
3540
+   x = top_pos(1);
3541
+   y = area(2);
3542
+   w = top_pos(3);
3543
+   h = top_pos(2) - y;
3544
+   pos = [x y w h];
3545
+
3546
+   if isfield(handles,'axial_slider') & ishandle(handles.axial_slider)
3547
+      set(handles.axial_slider,'position',pos);
3548
+   end
3549
+
3550
+   %  plot info view
3551
+   %
3552
+%   info_pos = [side_pos([1,3]); top_pos([2,4])];
3553
+%   info_pos = info_pos(:);
3554
+   gap = side_pos(1)-(top_pos(1)+top_pos(3));
3555
+   info_pos(1) = side_pos(1) + gap;
3556
+   info_pos(2) = area(2);
3557
+   info_pos(3) = side_pos(3) - gap;
3558
+   info_pos(4) = top_pos(2) + top_pos(4) - area(2) - gap;
3559
+
3560
+   num_inputline = 10;
3561
+   inputline_space =info_pos(4) / num_inputline;
3562
+
3563
+
3564
+   %  Image Intensity Value at Cursor
3565
+   %
3566
+   x = info_pos(1);
3567
+   y = info_pos(2);
3568
+   w = info_pos(3)*0.5;
3569
+   h = inputline_space*0.6;
3570
+
3571
+   pos = [x y w h];
3572
+   set(handles.Timvalcur,'position',pos);
3573
+
3574
+   x = x + w;
3575
+   w = info_pos(3)*0.5;
3576
+
3577
+   pos = [x y w h];
3578
+   set(handles.imvalcur,'position',pos);
3579
+
3580
+   %  Position at Cursor
3581
+   %
3582
+   x = info_pos(1);
3583
+   y = y + inputline_space;
3584
+   w = info_pos(3)*0.5;
3585
+
3586
+   pos = [x y w h];
3587
+   set(handles.Timposcur,'position',pos);
3588
+
3589
+   x = x + w;
3590
+   w = info_pos(3)*0.5;
3591
+
3592
+   pos = [x y w h];
3593
+   set(handles.imposcur,'position',pos);
3594
+
3595
+   %  Image Intensity Value at Mouse Click
3596
+   %
3597
+   x = info_pos(1);
3598
+   y = y + inputline_space;
3599
+   w = info_pos(3)*0.5;
3600
+
3601
+   pos = [x y w h];
3602
+   set(handles.Timval,'position',pos);
3603
+
3604
+   x = x + w;
3605
+   w = info_pos(3)*0.5;
3606
+
3607
+   pos = [x y w h];
3608
+   set(handles.imval,'position',pos);
3609
+
3610
+   %  Viewpoint Position at Mouse Click
3611
+   %
3612
+   x = info_pos(1);
3613
+   y = y + inputline_space;
3614
+   w = info_pos(3)*0.5;
3615
+
3616
+   pos = [x y w h];
3617
+   set(handles.Timpos,'position',pos);
3618
+
3619
+   x = x + w + 0.005;
3620
+   y = y - 0.008;
3621
+   w = info_pos(3)*0.5;
3622
+   h = inputline_space*0.9;
3623
+
3624
+   pos = [x y w h];
3625
+   set(handles.impos,'position',pos);
3626
+
3627
+   %  Origin Position
3628
+   %
3629
+   x = info_pos(1);
3630
+   y = y + inputline_space*1.2;
3631
+   w = info_pos(3)*0.5;
3632
+   h = inputline_space*0.6;
3633
+
3634
+   pos = [x y w h];
3635
+   set(handles.Torigin,'position',pos);
3636
+
3637
+   x = x + w;
3638
+   w = info_pos(3)*0.5;
3639
+
3640
+   pos = [x y w h];
3641
+   set(handles.origin,'position',pos);
3642
+
3643
+if 0
3644
+   %  Axes Unit
3645
+   %
3646
+   x = info_pos(1);
3647
+   y = y + inputline_space;
3648
+   w = info_pos(3)*0.5;
3649
+
3650
+   pos = [x y w h];
3651
+   set(handles.Tcoord,'position',pos);
3652
+
3653
+   x = x + w + 0.005;
3654
+   w = info_pos(3)*0.5 - 0.005;
3655
+
3656
+   pos = [x y w h];
3657
+   set(handles.coord,'position',pos);
3658
+end
3659
+
3660
+   %  Crosshair
3661
+   %
3662
+   x = info_pos(1);
3663
+   y = y + inputline_space;
3664
+   w = info_pos(3)*0.4;
3665
+
3666
+   pos = [x y w h];
3667
+   set(handles.Txhair,'position',pos);
3668
+
3669
+   x = info_pos(1) + info_pos(3)*0.5;
3670
+   w = info_pos(3)*0.2;
3671
+   h = inputline_space*0.7;
3672
+
3673
+   pos = [x y w h];
3674
+   set(handles.xhair_color,'position',pos);
3675
+
3676
+   x = info_pos(1) + info_pos(3)*0.7;
3677
+   w = info_pos(3)*0.3;
3678
+
3679
+   pos = [x y w h];
3680
+   set(handles.xhair,'position',pos);
3681
+
3682
+   %  Histogram & Color
3683
+   %
3684
+   x = info_pos(1);
3685
+   w = info_pos(3)*0.45;
3686
+   h = inputline_space * 1.5;
3687
+   pos = [x,  y+inputline_space*0.9,  w,  h];
3688
+   set(handles.hist_frame,'position',pos);
3689
+   set(handles.coord_frame,'position',pos);
3690
+
3691
+   x = info_pos(1) + info_pos(3)*0.475;
3692
+   w = info_pos(3)*0.525;
3693
+   h = inputline_space * 1.5;
3694
+
3695
+   pos = [x,  y+inputline_space*0.9,  w,  h];
3696
+   set(handles.color_frame,'position',pos);
3697
+
3698
+   x = info_pos(1) + info_pos(3)*0.025;
3699
+   y = y + inputline_space*1.2;
3700
+   w = info_pos(3)*0.2;
3701
+   h = inputline_space*0.7;
3702
+
3703
+   pos = [x y w h];
3704
+   set(handles.hist_eq,'position',pos);
3705
+
3706
+   x = x + w;
3707
+   w = info_pos(3)*0.2;
3708
+
3709
+   pos = [x y w h];
3710
+   set(handles.hist_plot,'position',pos);
3711
+
3712
+   x = info_pos(1) + info_pos(3)*0.025;
3713
+   w = info_pos(3)*0.4;
3714
+
3715
+   pos = [x y w h];
3716
+   set(handles.coord,'position',pos);
3717
+
3718
+   x = info_pos(1) + info_pos(3)*0.5;
3719
+   w = info_pos(3)*0.2;
3720
+   pos = [x y w h];
3721
+   set(handles.neg_color,'position',pos);
3722
+
3723
+   x = info_pos(1) + info_pos(3)*0.7;
3724
+   w = info_pos(3)*0.275;
3725
+
3726
+   pos = [x y w h];
3727
+   set(handles.colorindex,'position',pos);
3728
+
3729
+   x = info_pos(1) + info_pos(3)*0.1;
3730
+   y = y + inputline_space;
3731
+   w = info_pos(3)*0.28;
3732
+   h = inputline_space*0.6;
3733
+
3734
+   pos = [x y w h];
3735
+   set(handles.Thist,'position',pos);
3736
+   set(handles.Tcoord,'position',pos);
3737
+
3738
+   x = info_pos(1) + info_pos(3)*0.60;
3739
+   w = info_pos(3)*0.28;
3740
+
3741
+   pos = [x y w h];
3742
+   set(handles.Tcolor,'position',pos);
3743
+
3744
+   %  Contrast Frame
3745
+   %
3746
+   x = info_pos(1);
3747
+   w = info_pos(3)*0.45;
3748
+   h = inputline_space * 2;
3749
+
3750
+   pos = [x,  y+inputline_space*0.8,  w,  h];
3751
+   set(handles.contrast_frame,'position',pos);
3752
+
3753
+   %  Brightness Frame
3754
+   %
3755
+   x = info_pos(1) + info_pos(3)*0.475;
3756
+   w = info_pos(3)*0.525;
3757
+
3758
+   pos = [x,  y+inputline_space*0.8,  w,  h];
3759
+   set(handles.brightness_frame,'position',pos);
3760
+
3761
+   %  Contrast
3762
+   %
3763
+   x = info_pos(1) + info_pos(3)*0.025;
3764
+   y = y + inputline_space;
3765
+   w = info_pos(3)*0.4;
3766
+   h = inputline_space*0.6;
3767
+
3768
+   pos = [x y w h];
3769
+   set(handles.contrast,'position',pos);
3770
+
3771
+   %  Brightness
3772
+   %
3773
+   x = info_pos(1) + info_pos(3)*0.5;
3774
+   w = info_pos(3)*0.475;
3775
+
3776
+   pos = [x y w h];
3777
+   set(handles.brightness,'position',pos);
3778
+
3779
+   %  Contrast text/def
3780
+   %
3781
+   x = info_pos(1) + info_pos(3)*0.025;
3782
+   y = y + inputline_space;
3783
+   w = info_pos(3)*0.22;
3784
+
3785
+   pos = [x y w h];
3786
+   set(handles.Tcontrast,'position',pos);
3787
+
3788
+   x = x + w;
3789
+   w = info_pos(3)*0.18;
3790
+
3791
+   pos = [x y w h];
3792
+   set(handles.contrast_def,'position',pos);
3793
+
3794
+   %  Brightness text/def
3795
+   %
3796
+   x = info_pos(1) + info_pos(3)*0.5;
3797
+   w = info_pos(3)*0.295;
3798
+
3799
+   pos = [x y w h];
3800
+   set(handles.Tbrightness,'position',pos);
3801
+
3802
+   x = x + w;
3803
+   w = info_pos(3)*0.18;
3804
+
3805
+   pos = [x y w h];
3806
+   set(handles.brightness_def,'position',pos);
3807
+
3808
+   return;					% update_usestretch
3809
+
3810
+
3811
+%----------------------------------------------------------------
3812
+function update_useinterp(fig, useinterp)
3813
+
3814
+   if isempty(useinterp)
3815
+      return;
3816
+   end
3817
+
3818
+   nii_menu = getappdata(fig, 'nii_menu');
3819
+
3820
+   if ~isempty(nii_menu)
3821
+      if get(nii_menu.Minterp,'user')
3822
+         set(nii_menu.Minterp,'Userdata',0,'Label','Interp off');
3823
+      else
3824
+         set(nii_menu.Minterp,'Userdata',1,'Label','Interp on');
3825
+      end
3826
+   end
3827
+
3828
+   nii_view = getappdata(fig, 'nii_view');
3829
+   nii_view.useinterp = useinterp;
3830
+
3831
+   if ~isempty(nii_view.handles.axial_image)
3832
+      if strcmpi(get(nii_view.handles.axial_image,'cdatamapping'), 'direct')
3833
+         useimagesc = 0;
3834
+      else
3835
+         useimagesc = 1;
3836
+      end
3837
+   elseif ~isempty(nii_view.handles.coronal_image)
3838
+      if strcmpi(get(nii_view.handles.coronal_image,'cdatamapping'), 'direct')
3839
+         useimagesc = 0;
3840
+      else
3841
+         useimagesc = 1;
3842
+      end
3843
+   else
3844
+      if strcmpi(get(nii_view.handles.sagittal_image,'cdatamapping'), 'direct')
3845
+         useimagesc = 0;
3846
+      else
3847
+         useimagesc = 1;
3848
+      end
3849
+   end
3850
+
3851
+   if ~isempty(nii_view.handles.axial_image)
3852
+      img_slice = get(nii_view.handles.axial_image, 'cdata');
3853
+      delete(nii_view.handles.axial_image);
3854
+      axes(nii_view.handles.axial_axes);
3855
+      clim = get(gca,'clim');
3856
+
3857
+      if useinterp
3858
+         if useimagesc
3859
+            nii_view.handles.axial_image = surface(zeros(size(img_slice)),double(img_slice),'edgecolor','none','facecolor','interp');
3860
+         else
3861
+            nii_view.handles.axial_image = surface(zeros(size(img_slice)),double(img_slice),'cdatamapping','direct','edgecolor','none','facecolor','interp');
3862
+         end
3863
+      else
3864
+         if useimagesc
3865
+            nii_view.handles.axial_image = imagesc('cdata',img_slice);
3866
+         else
3867
+            nii_view.handles.axial_image = image('cdata',img_slice);
3868
+         end
3869
+      end
3870
+
3871
+      set(gca,'clim',clim);
3872
+
3873
+      order = get(gca,'child');
3874
+      order(find(order == nii_view.handles.axial_image)) = [];
3875
+      order = [order; nii_view.handles.axial_image];
3876
+
3877
+      if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg)
3878
+         order(find(order == nii_view.handles.axial_bg)) = [];
3879
+         order = [order; nii_view.handles.axial_bg];
3880
+      end
3881
+
3882
+      set(gca, 'child', order);
3883
+
3884
+      if ~useinterp
3885
+         if isfield(nii_view.handles,'axial_bg') & ~isempty(nii_view.handles.axial_bg)
3886
+            delete(nii_view.handles.axial_bg);
3887
+            nii_view.handles.axial_bg = [];
3888
+         end
3889
+      end
3890
+
3891
+      set(nii_view.handles.axial_image,'buttondown','view_nii(''axial_image'');');
3892
+   end
3893
+
3894
+   if ~isempty(nii_view.handles.coronal_image)
3895
+      img_slice = get(nii_view.handles.coronal_image, 'cdata');
3896
+      delete(nii_view.handles.coronal_image);
3897
+      axes(nii_view.handles.coronal_axes);
3898
+      clim = get(gca,'clim');
3899
+
3900
+      if useinterp
3901
+         if useimagesc
3902
+            nii_view.handles.coronal_image = surface(zeros(size(img_slice)),double(img_slice),'edgecolor','none','facecolor','interp');
3903
+         else
3904
+            nii_view.handles.coronal_image = surface(zeros(size(img_slice)),double(img_slice),'cdatamapping','direct','edgecolor','none','facecolor','interp');
3905
+         end
3906
+      else
3907
+         if useimagesc
3908
+            nii_view.handles.coronal_image = imagesc('cdata',img_slice);
3909
+         else
3910
+            nii_view.handles.coronal_image = image('cdata',img_slice);
3911
+         end
3912
+      end
3913
+
3914
+      set(gca,'clim',clim);
3915
+
3916
+      order = get(gca,'child');
3917
+      order(find(order == nii_view.handles.coronal_image)) = [];
3918
+      order = [order; nii_view.handles.coronal_image];
3919
+
3920
+      if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg)
3921
+         order(find(order == nii_view.handles.coronal_bg)) = [];
3922
+         order = [order; nii_view.handles.coronal_bg];
3923
+      end
3924
+
3925
+      set(gca, 'child', order);
3926
+
3927
+      if ~useinterp
3928
+         if isfield(nii_view.handles,'coronal_bg') & ~isempty(nii_view.handles.coronal_bg)
3929
+            delete(nii_view.handles.coronal_bg);
3930
+            nii_view.handles.coronal_bg = [];
3931
+         end
3932
+      end
3933
+
3934
+      set(nii_view.handles.coronal_image,'buttondown','view_nii(''coronal_image'');');
3935
+   end
3936
+
3937
+   if ~isempty(nii_view.handles.sagittal_image)
3938
+      img_slice = get(nii_view.handles.sagittal_image, 'cdata');
3939
+      delete(nii_view.handles.sagittal_image);
3940
+      axes(nii_view.handles.sagittal_axes);
3941
+      clim = get(gca,'clim');
3942
+
3943
+      if useinterp
3944
+         if useimagesc
3945
+            nii_view.handles.sagittal_image = surface(zeros(size(img_slice)),double(img_slice),'edgecolor','none','facecolor','interp');
3946
+         else
3947
+            nii_view.handles.sagittal_image = surface(zeros(size(img_slice)),double(img_slice),'cdatamapping','direct','edgecolor','none','facecolor','interp');
3948
+         end
3949
+      else
3950
+         if useimagesc
3951
+            nii_view.handles.sagittal_image = imagesc('cdata',img_slice);
3952
+         else
3953
+            nii_view.handles.sagittal_image = image('cdata',img_slice);
3954
+         end
3955
+      end
3956
+
3957
+      set(gca,'clim',clim);
3958
+
3959
+      order = get(gca,'child');
3960
+      order(find(order == nii_view.handles.sagittal_image)) = [];
3961
+      order = [order; nii_view.handles.sagittal_image];
3962
+
3963
+      if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg)
3964
+         order(find(order == nii_view.handles.sagittal_bg)) = [];
3965
+         order = [order; nii_view.handles.sagittal_bg];
3966
+      end
3967
+
3968
+      set(gca, 'child', order);
3969
+
3970
+      if ~useinterp
3971
+         if isfield(nii_view.handles,'sagittal_bg') & ~isempty(nii_view.handles.sagittal_bg)
3972
+            delete(nii_view.handles.sagittal_bg);
3973
+            nii_view.handles.sagittal_bg = [];
3974
+         end
3975
+      end
3976
+
3977
+      set(nii_view.handles.sagittal_image,'buttondown','view_nii(''sagittal_image'');');
3978
+   end
3979
+
3980
+   if ~useinterp
3981
+      nii_view.bgimg = [];
3982
+   end
3983
+
3984
+   set_coordinates(nii_view,useinterp);
3985
+   setappdata(fig, 'nii_view', nii_view);
3986
+
3987
+   return;					% update_useinterp
3988
+
3989
+
3990
+%----------------------------------------------------------------
3991
+function update_useimagesc(fig, useimagesc)
3992
+
3993
+   if isempty(useimagesc)
3994
+      return;
3995
+   end
3996
+
3997
+   if useimagesc
3998
+      v='scaled';
3999
+   else
4000
+      v='direct';
4001
+   end
4002
+
4003
+   nii_view = getappdata(fig,'nii_view');
4004
+   handles = nii_view.handles;
4005
+
4006
+   if isfield(handles,'cbar_image') & ishandle(handles.cbar_image)
4007
+%      set(handles.cbar_image,'cdatamapping',v);
4008
+   end
4009
+
4010
+   set(handles.axial_image,'cdatamapping',v);
4011
+   set(handles.coronal_image,'cdatamapping',v);
4012
+   set(handles.sagittal_image,'cdatamapping',v);
4013
+
4014
+   return;					% update_useimagesc
4015
+
4016
+
4017
+%----------------------------------------------------------------
4018
+function update_shape(fig, area, usecolorbar, usestretch, useimagesc)
4019
+
4020
+   nii_view = getappdata(fig,'nii_view');
4021
+
4022
+   if isempty(usestretch)		% no change, get usestretch
4023
+      stretchchange = 0;
4024
+      usestretch = nii_view.usestretch;
4025
+   else					% change, set usestretch
4026
+      stretchchange = 1;
4027
+      nii_view.usestretch = usestretch;
4028
+   end
4029
+
4030
+   if isempty(area)			% no change, get area
4031
+
4032
+      areachange = 0;
4033
+      area = nii_view.area;
4034
+
4035
+   elseif ~isempty(nii_view.cbar_area)	% change, set area & cbar_area
4036
+
4037
+      areachange = 1;
4038
+      cbar_area = area;
4039
+      cbar_area(1) = area(1) + area(3)*0.93;
4040
+      cbar_area(3) = area(3)*0.04;
4041
+      area(3) = area(3)*0.9;		% 90% used for main axes
4042
+
4043
+      [cbar_axes cbarminmax_axes] = create_cbar_axes(fig, cbar_area);
4044
+
4045
+      nii_view.area = area;
4046
+      nii_view.cbar_area = cbar_area;
4047
+
4048
+   else					% change, set area only
4049
+      areachange = 1;
4050
+      nii_view.area = area;
4051
+   end
4052
+
4053
+   %  Add colorbar
4054
+   %
4055
+   if ~isempty(usecolorbar) & usecolorbar & isempty(nii_view.cbar_area)
4056
+
4057
+      colorbarchange = 1;
4058
+
4059
+      cbar_area = area;
4060
+      cbar_area(1) = area(1) + area(3)*0.93;
4061
+      cbar_area(3) = area(3)*0.04;
4062
+      area(3) = area(3)*0.9;		% 90% used for main axes
4063
+
4064
+      %  create axes for colorbar
4065
+      %
4066
+      [cbar_axes cbarminmax_axes] = create_cbar_axes(fig, cbar_area);
4067
+
4068
+      nii_view.area = area;
4069
+      nii_view.cbar_area = cbar_area;
4070
+
4071
+      %  useimagesc follows axial image
4072
+      %
4073
+      if isempty(useimagesc)
4074
+         if strcmpi(get(nii_view.handles.axial_image,'cdatamap'),'scaled')
4075
+            useimagesc = 1;
4076
+         else
4077
+            useimagesc = 0;
4078
+         end
4079
+      end
4080
+
4081
+      if isfield(nii_view, 'highcolor') & ~isempty(highcolor)
4082
+         num_highcolor = size(nii_view.highcolor,1);
4083
+      else
4084
+         num_highcolor = 0;
4085
+      end
4086
+
4087
+      if isfield(nii_view, 'colorlevel') & ~isempty(nii_view.colorlevel)
4088
+         colorlevel = nii_view.colorlevel;
4089
+      else
4090
+         colorlevel = 256 - num_highcolor;
4091
+      end
4092
+
4093
+      if isfield(nii_view, 'color_map')
4094
+         color_map = nii_view.color_map;
4095
+      else
4096
+         color_map = [];
4097
+      end
4098
+
4099
+      if isfield(nii_view, 'highcolor')
4100
+         highcolor = nii_view.highcolor;
4101
+      else
4102
+         highcolor = [];
4103
+      end
4104
+
4105
+      %  plot colorbar
4106
+      %
4107
+if 0
4108
+      if isempty(color_map)
4109
+         level = colorlevel + num_highcolor;
4110
+      else
4111
+         level = size([color_map; highcolor], 1);
4112
+      end
4113
+end
4114
+
4115
+      if isempty(color_map)
4116
+         level = colorlevel;
4117
+      else
4118
+         level = size([color_map], 1);
4119
+      end
4120
+
4121
+      cbar_image = [1:level]';
4122
+
4123
+      niiclass = class(nii_view.nii.img);
4124
+
4125
+      h1 = plot_cbar(fig, cbar_axes, cbarminmax_axes, nii_view.cbarminmax, ...
4126
+		level, nii_view.handles, useimagesc, nii_view.colorindex, ...
4127
+		color_map, colorlevel, highcolor, niiclass, nii_view.numscan);
4128
+      nii_view.handles.cbar_image = h1;
4129
+      nii_view.handles.cbar_axes = cbar_axes;
4130
+      nii_view.handles.cbarminmax_axes = cbar_axes;
4131
+
4132
+   %  remove colorbar
4133
+   %
4134
+   elseif ~isempty(usecolorbar) & ~usecolorbar & ~isempty(nii_view.cbar_area)
4135
+
4136
+      colorbarchange = 1;
4137
+
4138
+      area(3) = area(3) / 0.9;
4139
+
4140
+      nii_view.area = area;
4141
+      nii_view.cbar_area = [];
4142
+
4143
+      nii_view.handles = rmfield(nii_view.handles,'cbar_image');
4144
+      delete(nii_view.handles.cbarminmax_axes);
4145
+      nii_view.handles = rmfield(nii_view.handles,'cbarminmax_axes');
4146
+      delete(nii_view.handles.cbar_axes);
4147
+      nii_view.handles = rmfield(nii_view.handles,'cbar_axes');
4148
+
4149
+   else
4150
+      colorbarchange = 0;
4151
+   end
4152
+
4153
+   if colorbarchange | stretchchange | areachange
4154
+      setappdata(fig,'nii_view',nii_view);
4155
+      update_usestretch(fig, usestretch);
4156
+   end
4157
+
4158
+   return;					% update_shape
4159
+
4160
+
4161
+%----------------------------------------------------------------
4162
+function update_unit(fig, setunit)
4163
+
4164
+   if isempty(setunit)
4165
+      return;
4166
+   end
4167
+
4168
+   if strcmpi(setunit,'mm') | strcmpi(setunit,'millimeter') | strcmpi(setunit,'mni')
4169
+      v = 2;
4170
+%   elseif strcmpi(setunit,'tal') | strcmpi(setunit,'talairach')
4171
+ %     v = 3;
4172
+   elseif strcmpi(setunit,'vox') | strcmpi(setunit,'voxel')
4173
+      v = 1;
4174
+   else
4175
+      v = 1;
4176
+   end
4177
+
4178
+   nii_view = getappdata(fig,'nii_view');
4179
+   set(nii_view.handles.coord, 'value', v);
4180
+   set_image_value(nii_view);
4181
+
4182
+   return;					% update_unit
4183
+
4184
+
4185
+%----------------------------------------------------------------
4186
+function update_viewpoint(fig, setviewpoint)
4187
+
4188
+   if isempty(setviewpoint)
4189
+      return;
4190
+   end
4191
+
4192
+   nii_view = getappdata(fig,'nii_view');
4193
+
4194
+   if length(setviewpoint) ~= 3
4195
+      error('Viewpoint position should contain [x y z]');
4196
+   end
4197
+
4198
+   set(nii_view.handles.impos,'string',num2str(setviewpoint));
4199
+
4200
+   opt.command = 'impos_edit';
4201
+   view_nii(fig, opt);
4202
+
4203
+   set(nii_view.handles.axial_axes,'selected','on');
4204
+   set(nii_view.handles.axial_axes,'selected','off');
4205
+   set(nii_view.handles.coronal_axes,'selected','on');
4206
+   set(nii_view.handles.coronal_axes,'selected','off');
4207
+   set(nii_view.handles.sagittal_axes,'selected','on');
4208
+   set(nii_view.handles.sagittal_axes,'selected','off');
4209
+
4210
+   return;					% update_viewpoint
4211
+
4212
+
4213
+%----------------------------------------------------------------
4214
+function update_scanid(fig, setscanid)
4215
+
4216
+   if isempty(setscanid)
4217
+      return;
4218
+   end
4219
+
4220
+   nii_view = getappdata(fig,'nii_view');
4221
+
4222
+   if setscanid < 1
4223
+      setscanid = 1;
4224
+   end
4225
+
4226
+   if setscanid > nii_view.numscan
4227
+      setscanid = nii_view.numscan;
4228
+   end
4229
+
4230
+   set(nii_view.handles.contrast_def,'string',num2str(setscanid));
4231
+   set(nii_view.handles.contrast,'value',setscanid);
4232
+
4233
+   opt.command = 'updateimg';
4234
+   opt.setscanid = setscanid;
4235
+
4236
+   view_nii(fig, nii_view.nii.img, opt);
4237
+
4238
+   return;					% update_scanid
4239
+
4240
+
4241
+%----------------------------------------------------------------
4242
+function update_crosshaircolor(fig, new_color)
4243
+
4244
+   if isempty(new_color)
4245
+      return;
4246
+   end
4247
+
4248
+   nii_view = getappdata(fig,'nii_view');
4249
+   xhair_color = nii_view.handles.xhair_color;
4250
+
4251
+   set(xhair_color,'user',new_color);
4252
+   set(nii_view.axi_xhair.lx,'color',new_color);
4253
+   set(nii_view.axi_xhair.ly,'color',new_color);
4254
+   set(nii_view.cor_xhair.lx,'color',new_color);
4255
+   set(nii_view.cor_xhair.ly,'color',new_color);
4256
+   set(nii_view.sag_xhair.lx,'color',new_color);
4257
+   set(nii_view.sag_xhair.ly,'color',new_color);
4258
+
4259
+   return;					% update_crosshaircolor
4260
+
4261
+
4262
+%----------------------------------------------------------------
4263
+function update_colorindex(fig, colorindex)
4264
+
4265
+   if isempty(colorindex)
4266
+      return;
4267
+   end
4268
+
4269
+   nii_view = getappdata(fig,'nii_view');
4270
+   nii_view.colorindex = colorindex;
4271
+   setappdata(fig, 'nii_view', nii_view);
4272
+   set(nii_view.handles.colorindex,'value',colorindex);
4273
+
4274
+   opt.command = 'color';
4275
+   view_nii(fig, opt);
4276
+
4277
+   return;					% update_colorindex
4278
+
4279
+
4280
+%----------------------------------------------------------------
4281
+function redraw_cbar(fig, colorlevel, color_map, highcolor)
4282
+
4283
+   nii_view = getappdata(fig,'nii_view');
4284
+
4285
+   if isempty(nii_view.cbar_area)
4286
+      return;
4287
+   end
4288
+
4289
+   colorindex = nii_view.colorindex;
4290
+
4291
+   if isempty(highcolor)
4292
+      num_highcolor = 0;
4293
+   else
4294
+      num_highcolor = size(highcolor,1);
4295
+   end
4296
+
4297
+   if isempty(colorlevel)
4298
+      colorlevel=256;
4299
+   end
4300
+
4301
+   if colorindex == 1
4302
+      colorlevel = size(color_map, 1);
4303
+   end
4304
+
4305
+%   level = colorlevel + num_highcolor;
4306
+   level = colorlevel;
4307
+
4308
+   cbar_image = [1:level]';
4309
+
4310
+   cbar_area = nii_view.cbar_area;
4311
+
4312
+   %  useimagesc follows axial image
4313
+   %
4314
+   if strcmpi(get(nii_view.handles.axial_image,'cdatamap'),'scaled')
4315
+      useimagesc = 1;
4316
+   else
4317
+      useimagesc = 0;
4318
+   end
4319
+
4320
+   niiclass = class(nii_view.nii.img);
4321
+
4322
+   delete(nii_view.handles.cbar_image);
4323
+   delete(nii_view.handles.cbar_axes);
4324
+   delete(nii_view.handles.cbarminmax_axes);
4325
+
4326
+   [nii_view.handles.cbar_axes nii_view.handles.cbarminmax_axes] = ...
4327
+	create_cbar_axes(fig, cbar_area, []);
4328
+
4329
+   nii_view.handles.cbar_image = plot_cbar(fig, ...
4330
+	nii_view.handles.cbar_axes, nii_view.handles.cbarminmax_axes, ...
4331
+	nii_view.cbarminmax, level, nii_view.handles, useimagesc, ...
4332
+	colorindex, color_map, colorlevel, highcolor, niiclass, ...
4333
+	nii_view.numscan, []);
4334
+
4335
+   setappdata(fig, 'nii_view', nii_view);
4336
+
4337
+   return;					% redraw_cbar
4338
+
4339
+
4340
+%----------------------------------------------------------------
4341
+function update_buttondown(fig, setbuttondown)
4342
+
4343
+   if isempty(setbuttondown)
4344
+      return;
4345
+   end
4346
+
4347
+   nii_view = getappdata(fig,'nii_view');
4348
+   nii_view.buttondown = setbuttondown;
4349
+   setappdata(fig, 'nii_view', nii_view);
4350
+
4351
+   return;					% update_buttondown
4352
+
4353
+
4354
+%----------------------------------------------------------------
4355
+function update_cbarminmax(fig, cbarminmax)
4356
+
4357
+   if isempty(cbarminmax)
4358
+      return;
4359
+   end
4360
+
4361
+   nii_view = getappdata(fig, 'nii_view');
4362
+
4363
+   if ~isfield(nii_view.handles, 'cbarminmax_axes')
4364
+      return;
4365
+   end
4366
+
4367
+   nii_view.cbarminmax = cbarminmax;
4368
+   setappdata(fig, 'nii_view', nii_view);
4369
+
4370
+   axes(nii_view.handles.cbarminmax_axes);
4371
+
4372
+   plot([0 0], cbarminmax, 'w');
4373
+   axis tight;
4374
+
4375
+   set(nii_view.handles.cbarminmax_axes,'YDir','normal', ...
4376
+      'XLimMode','manual','YLimMode','manual','YColor',[0 0 0], ...
4377
+      'XColor',[0 0 0],'xtick',[],'YAxisLocation','right');
4378
+
4379
+   ylim = get(nii_view.handles.cbar_axes,'ylim');
4380
+   ylimb = get(nii_view.handles.cbarminmax_axes,'ylim');
4381
+   ytickb = get(nii_view.handles.cbarminmax_axes,'ytick');
4382
+   ytick=(ylim(2)-ylim(1))*(ytickb-ylimb(1))/(ylimb(2)-ylimb(1))+ylim(1);
4383
+
4384
+   axes(nii_view.handles.cbar_axes);
4385
+
4386
+   set(nii_view.handles.cbar_axes,'YDir','normal','XLimMode','manual', ...
4387
+	'YLimMode','manual','YColor',[0 0 0],'XColor',[0 0 0],'xtick',[], ...
4388
+	'YAxisLocation','right','ylim',ylim,'ytick',ytick,'yticklabel','');
4389
+
4390
+   return;					% update_cbarminmax
4391
+
4392
+
4393
+%----------------------------------------------------------------
4394
+function update_highcolor(fig, highcolor, colorlevel)
4395
+
4396
+   nii_view = getappdata(fig,'nii_view');
4397
+
4398
+   if ischar(highcolor) & (isempty(colorlevel) | nii_view.colorindex == 1)
4399
+      return;
4400
+   end
4401
+
4402
+   if ~ischar(highcolor)
4403
+      nii_view.highcolor = highcolor;
4404
+
4405
+      if isempty(highcolor)
4406
+         nii_view = rmfield(nii_view, 'highcolor');
4407
+      end
4408
+   else
4409
+      highcolor = [];
4410
+   end
4411
+
4412
+   if isempty(colorlevel) | nii_view.colorindex == 1
4413
+      nii_view.colorlevel = nii_view.colorlevel - size(highcolor,1);
4414
+   else
4415
+      nii_view.colorlevel = colorlevel;
4416
+   end
4417
+
4418
+   setappdata(fig, 'nii_view', nii_view);
4419
+
4420
+   if isfield(nii_view,'color_map')
4421
+      color_map = nii_view.color_map;
4422
+   else
4423
+      color_map = [];
4424
+   end
4425
+
4426
+   redraw_cbar(fig, nii_view.colorlevel, color_map, highcolor);
4427
+   change_colormap(fig);
4428
+
4429
+   return;					% update_highcolor
4430
+
4431
+
4432
+%----------------------------------------------------------------
4433
+function update_colormap(fig, color_map)
4434
+
4435
+   if ischar(color_map)
4436
+      return;
4437
+   end
4438
+
4439
+   nii_view = getappdata(fig,'nii_view');
4440
+   nii = nii_view.nii;
4441
+   minvalue = nii_view.minvalue;
4442
+
4443
+   if isempty(color_map)
4444
+      if minvalue < 0
4445
+         colorindex = 2;
4446
+      else
4447
+         colorindex = 3;
4448
+      end
4449
+
4450
+      nii_view = rmfield(nii_view, 'color_map');
4451
+      setappdata(fig,'nii_view',nii_view);
4452
+      update_colorindex(fig, colorindex);
4453
+      return;
4454
+   else
4455
+      colorindex = 1;
4456
+      nii_view.color_map = color_map;
4457
+      nii_view.colorindex = colorindex;
4458
+      setappdata(fig,'nii_view',nii_view);
4459
+      set(nii_view.handles.colorindex,'value',colorindex);
4460
+   end
4461
+
4462
+   colorlevel = nii_view.colorlevel;
4463
+
4464
+   if isfield(nii_view, 'highcolor')
4465
+      highcolor = nii_view.highcolor;
4466
+   else
4467
+      highcolor = [];
4468
+   end
4469
+
4470
+   redraw_cbar(fig, colorlevel, color_map, highcolor);
4471
+   change_colormap(fig);
4472
+
4473
+   opt.enablecontrast = 0;
4474
+   update_enable(fig, opt);
4475
+
4476
+   return;					% update_colormap
4477
+
4478
+
4479
+%----------------------------------------------------------------
4480
+function status = get_status(h);
4481
+
4482
+   nii_view = getappdata(h,'nii_view');
4483
+
4484
+   status.fig = h;
4485
+   status.area = nii_view.area;
4486
+
4487
+   if isempty(nii_view.cbar_area)
4488
+      status.usecolorbar = 0;
4489
+   else
4490
+      status.usecolorbar = 1;
4491
+      width = status.area(3) / 0.9;
4492
+      status.area(3) = width;
4493
+   end
4494
+
4495
+   if strcmpi(get(nii_view.handles.imval,'visible'), 'on')
4496
+      status.usepanel = 1;
4497
+   else
4498
+      status.usepanel = 0;
4499
+   end
4500
+
4501
+   if get(nii_view.handles.xhair,'value') == 1
4502
+      status.usecrosshair = 1;
4503
+   else
4504
+      status.usecrosshair = 0;
4505
+   end
4506
+
4507
+   status.usestretch = nii_view.usestretch;
4508
+
4509
+   if strcmpi(get(nii_view.handles.axial_image,'cdatamapping'), 'direct')
4510
+      status.useimagesc = 0;
4511
+   else
4512
+      status.useimagesc = 1;
4513
+   end
4514
+
4515
+   status.useinterp = nii_view.useinterp;
4516
+
4517
+   if get(nii_view.handles.coord,'value') == 1
4518
+      status.unit = 'vox';
4519
+   elseif get(nii_view.handles.coord,'value') == 2
4520
+      status.unit = 'mm';
4521
+   elseif get(nii_view.handles.coord,'value') == 3
4522
+      status.unit = 'tal';
4523
+   end
4524
+
4525
+   status.viewpoint = get(nii_view.handles.impos,'value');
4526
+   status.scanid = nii_view.scanid;
4527
+   status.intensity = get(nii_view.handles.imval,'value');
4528
+   status.colorindex = get(nii_view.handles.colorindex,'value');
4529
+
4530
+   if isfield(nii_view,'color_map')
4531
+      status.colormap = nii_view.color_map;
4532
+   else
4533
+      status.colormap = [];
4534
+   end
4535
+
4536
+   status.colorlevel = nii_view.colorlevel;
4537
+
4538
+   if isfield(nii_view,'highcolor')
4539
+      status.highcolor = nii_view.highcolor;
4540
+   else
4541
+      status.highcolor = [];
4542
+   end
4543
+
4544
+   status.cbarminmax = nii_view.cbarminmax;
4545
+   status.buttondown = nii_view.buttondown;
4546
+
4547
+   return;					% get_status
4548
+
4549
+
4550
+%----------------------------------------------------------------
4551
+function [custom_color_map, colorindex] ...
4552
+		 = change_colormap(fig, nii, colorindex, cbarminmax)
4553
+
4554
+   custom_color_map = [];
4555
+
4556
+   if ~exist('nii', 'var')
4557
+      nii_view = getappdata(fig,'nii_view');
4558
+   else
4559
+      nii_view = nii;
4560
+   end
4561
+
4562
+   if ~exist('colorindex', 'var')
4563
+      colorindex = get(nii_view.handles.colorindex,'value');
4564
+   end
4565
+
4566
+   if ~exist('cbarminmax', 'var')
4567
+      cbarminmax = nii_view.cbarminmax;
4568
+   end
4569
+
4570
+   if isfield(nii_view, 'highcolor') & ~isempty(nii_view.highcolor)
4571
+      highcolor = nii_view.highcolor;
4572
+      num_highcolor = size(highcolor,1);
4573
+   else
4574
+      highcolor = [];
4575
+      num_highcolor = 0;
4576
+   end
4577
+
4578
+%   if isfield(nii_view, 'colorlevel') & ~isempty(nii_view.colorlevel)
4579
+   if nii_view.colorlevel < 256
4580
+      num_color = nii_view.colorlevel;
4581
+   else
4582
+      num_color = 256 - num_highcolor;
4583
+   end
4584
+
4585
+   contrast = [];
4586
+
4587
+   if colorindex == 3					% for gray
4588
+      if nii_view.numscan > 1
4589
+         contrast = 1;
4590
+      else
4591
+         contrast = (num_color-1)*(get(nii_view.handles.contrast,'value')-1)/255+1;
4592
+         contrast = floor(contrast);
4593
+      end
4594
+   elseif colorindex == 2				% for bipolar
4595
+      if nii_view.numscan > 1
4596
+         contrast = 128;
4597
+      else
4598
+         contrast = get(nii_view.handles.contrast,'value');
4599
+      end
4600
+   end
4601
+
4602
+   if isfield(nii_view,'color_map') & ~isempty(nii_view.color_map)
4603
+      color_map = nii_view.color_map;
4604
+      custom_color_map = color_map;
4605
+   elseif colorindex == 1
4606
+      [f p] = uigetfile('*.txt', 'Input colormap text file');
4607
+
4608
+      if p==0
4609
+         colorindex = nii_view.colorindex;
4610
+         set(nii_view.handles.colorindex,'value',colorindex);
4611
+         return; 
4612
+      end;
4613
+
4614
+      try
4615
+         custom_color_map = load(fullfile(p,f));
4616
+         loadfail = 0;
4617
+      catch
4618
+         loadfail = 1;
4619
+      end
4620
+
4621
+      if loadfail | isempty(custom_color_map) | size(custom_color_map,2)~=3 ...
4622
+	| min(custom_color_map(:)) < 0 | max(custom_color_map(:)) > 1 
4623
+
4624
+         msg = 'Colormap should be a Mx3 matrix with value between 0 and 1';
4625
+         msgbox(msg,'Error in colormap file');
4626
+         colorindex = nii_view.colorindex;
4627
+         set(nii_view.handles.colorindex,'value',colorindex);
4628
+         return;         
4629
+      end
4630
+
4631
+      color_map = custom_color_map;
4632
+      nii_view.color_map = color_map;
4633
+   end
4634
+
4635
+   switch colorindex
4636
+   case {2}
4637
+      color_map = bipolar(num_color, cbarminmax(1), cbarminmax(2), contrast);
4638
+   case {3}
4639
+      color_map = gray(num_color - contrast + 1);
4640
+   case {4}
4641
+      color_map = jet(num_color);
4642
+   case {5}
4643
+      color_map = cool(num_color);
4644
+   case {6}
4645
+      color_map = bone(num_color);
4646
+   case {7}
4647
+      color_map = hot(num_color);
4648
+   case {8}
4649
+      color_map = copper(num_color);
4650
+   case {9}
4651
+      color_map = pink(num_color);
4652
+   end
4653
+
4654
+   nii_view.colorindex = colorindex;
4655
+
4656
+   if ~exist('nii', 'var')
4657
+      setappdata(fig,'nii_view',nii_view);
4658
+   end
4659
+
4660
+   if colorindex == 3
4661
+      color_map = [zeros(contrast,3); color_map(2:end,:)];
4662
+   end
4663
+
4664
+   if get(nii_view.handles.neg_color,'value') & isempty(highcolor)
4665
+      color_map = flipud(color_map);
4666
+   elseif get(nii_view.handles.neg_color,'value') & ~isempty(highcolor)
4667
+      highcolor = flipud(highcolor);
4668
+   end
4669
+
4670
+   brightness = get(nii_view.handles.brightness,'value');
4671
+   color_map = brighten(color_map, brightness);
4672
+
4673
+   color_map = [color_map; highcolor];
4674
+
4675
+   set(fig, 'colormap', color_map);
4676
+
4677
+   return;					% change_colormap
4678
+
4679
+
4680
+%----------------------------------------------------------------
4681
+function move_cursor(fig)
4682
+
4683
+   nii_view = getappdata(fig, 'nii_view');
4684
+
4685
+   if isempty(nii_view)
4686
+      return;
4687
+   end
4688
+
4689
+   axi = get(nii_view.handles.axial_axes, 'pos');
4690
+   cor = get(nii_view.handles.coronal_axes, 'pos');
4691
+   sag = get(nii_view.handles.sagittal_axes, 'pos');
4692
+   curr = get(fig, 'currentpoint');
4693
+
4694
+   if		curr(1) >= axi(1) & curr(1) <= axi(1)+axi(3) & ...
4695
+		curr(2) >= axi(2) & curr(2) <= axi(2)+axi(4)
4696
+
4697
+      curr = get(nii_view.handles.axial_axes, 'current');
4698
+      sag = curr(1,1);
4699
+      cor = curr(1,2);
4700
+      axi = nii_view.slices.axi;
4701
+
4702
+   elseif	curr(1) >= cor(1) & curr(1) <= cor(1)+cor(3) & ...
4703
+		curr(2) >= cor(2) & curr(2) <= cor(2)+cor(4)
4704
+
4705
+      curr = get(nii_view.handles.coronal_axes, 'current');
4706
+      sag = curr(1,1);
4707
+      cor = nii_view.slices.cor;
4708
+      axi = curr(1,2);
4709
+
4710
+   elseif	curr(1) >= sag(1) & curr(1) <= sag(1)+sag(3) & ...
4711
+		curr(2) >= sag(2) & curr(2) <= sag(2)+sag(4)
4712
+
4713
+      curr = get(nii_view.handles.sagittal_axes, 'current');
4714
+
4715
+      sag = nii_view.slices.sag;
4716
+      cor = curr(1,1);
4717
+      axi = curr(1,2);
4718
+
4719
+   else
4720
+
4721
+      set(nii_view.handles.imvalcur,'String',' ');
4722
+      set(nii_view.handles.imposcur,'String',' ');
4723
+      return;
4724
+
4725
+   end
4726
+
4727
+    sag = round(sag);
4728
+    cor = round(cor);
4729
+    axi = round(axi);
4730
+
4731
+    if sag < 1
4732
+       sag = 1;
4733
+    elseif sag > nii_view.dims(1)
4734
+       sag = nii_view.dims(1);
4735
+    end
4736
+
4737
+    if cor < 1
4738
+       cor = 1;
4739
+    elseif cor > nii_view.dims(2)
4740
+       cor = nii_view.dims(2);
4741
+    end
4742
+
4743
+    if axi < 1
4744
+       axi = 1;
4745
+    elseif axi > nii_view.dims(3)
4746
+       axi = nii_view.dims(3);
4747
+    end
4748
+
4749
+    if 0 % isfield(nii_view, 'disp')
4750
+       img = nii_view.disp;    
4751
+    else
4752
+       img = nii_view.nii.img;
4753
+    end
4754
+
4755
+    if nii_view.nii.hdr.dime.datatype == 128
4756
+       imgvalue = [double(img(sag,cor,axi,1,nii_view.scanid)) double(img(sag,cor,axi,2,nii_view.scanid)) double(img(sag,cor,axi,3,nii_view.scanid))];
4757
+       set(nii_view.handles.imvalcur,'String',sprintf('%7.4g %7.4g %7.4g',imgvalue));
4758
+    elseif nii_view.nii.hdr.dime.datatype == 511
4759
+       R = double(img(sag,cor,axi,1,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
4760
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
4761
+       G = double(img(sag,cor,axi,2,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
4762
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
4763
+       B = double(img(sag,cor,axi,3,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
4764
+		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
4765
+       imgvalue = [R G B];
4766
+       set(nii_view.handles.imvalcur,'String',sprintf('%7.4g %7.4g %7.4g',imgvalue));
4767
+    else
4768
+       imgvalue = double(img(sag,cor,axi,nii_view.scanid));
4769
+
4770
+       if isnan(imgvalue) | imgvalue > nii_view.cbarminmax(2)
4771
+          imgvalue = 0;
4772
+       end
4773
+
4774
+       set(nii_view.handles.imvalcur,'String',sprintf('%.6g',imgvalue));
4775
+    end
4776
+
4777
+    nii_view.slices.sag = sag;
4778
+    nii_view.slices.cor = cor;
4779
+    nii_view.slices.axi = axi;
4780
+
4781
+    nii_view = update_imgXYZ(nii_view);
4782
+
4783
+    if get(nii_view.handles.coord,'value') == 1,
4784
+       sag = nii_view.imgXYZ.vox(1);
4785
+       cor = nii_view.imgXYZ.vox(2);
4786
+       axi = nii_view.imgXYZ.vox(3);
4787
+    elseif get(nii_view.handles.coord,'value') == 2,
4788
+       sag = nii_view.imgXYZ.mm(1);
4789
+       cor = nii_view.imgXYZ.mm(2);
4790
+       axi = nii_view.imgXYZ.mm(3);
4791
+    elseif get(nii_view.handles.coord,'value') == 3,
4792
+       sag = nii_view.imgXYZ.tal(1);
4793
+       cor = nii_view.imgXYZ.tal(2);
4794
+       axi = nii_view.imgXYZ.tal(3);
4795
+    end
4796
+
4797
+    if get(nii_view.handles.coord,'value') == 1,
4798
+        string = sprintf('%7.0f %7.0f %7.0f',sag,cor,axi);
4799
+    else
4800
+        string = sprintf('%7.1f %7.1f %7.1f',sag,cor,axi);
4801
+    end;
4802
+    
4803
+    set(nii_view.handles.imposcur,'String',string);
4804
+
4805
+    return;					% move_cursor
4806
+
4807
+
4808
+%----------------------------------------------------------------
4809
+function change_scan(hdl_str)
4810
+
4811
+   fig = gcbf;
4812
+   nii_view = getappdata(fig,'nii_view');
4813
+
4814
+   if strcmpi(hdl_str, 'edit_change_scan')		% edit
4815
+      hdl = nii_view.handles.contrast_def;
4816
+      setscanid = round(str2num(get(hdl, 'string')));
4817
+   else							% slider
4818
+      hdl = nii_view.handles.contrast;
4819
+      setscanid = round(get(hdl, 'value'));
4820
+   end
4821
+
4822
+   update_scanid(fig, setscanid);
4823
+
4824
+   return;					% change_scan
4825
+
4826
+
4827
+%----------------------------------------------------------------
4828
+function val = scale_in(val, minval, maxval, range)
4829
+
4830
+   %  scale value into range
4831
+   %
4832
+   val = range*(double(val)-double(minval))/(double(maxval)-double(minval))+1;
4833
+
4834
+   return;					% scale_in
4835
+
4836
+
4837
+%----------------------------------------------------------------
4838
+function val = scale_out(val, minval, maxval, range)
4839
+
4840
+   %  according to [minval maxval] and range of color levels (e.g. 199)
4841
+   %  scale val back from any thing between 1~256 to a small number that
4842
+   %  is corresonding to [minval maxval].
4843
+   %
4844
+   val = (double(val)-1)*(double(maxval)-double(minval))/range+double(minval);
4845
+
4846
+   return;					% scale_out
4847
+
... ...
@@ -0,0 +1,317 @@
1
+%  Imbed Zoom, Interp, and Info menu to view_nii window.
2
+%
3
+%  Usage: view_nii_menu(fig);
4
+%
5
+
6
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
7
+%
8
+%--------------------------------------------------------------------
9
+function menu_hdl = view_nii_menu(fig, varargin)
10
+
11
+   if isnumeric(fig)
12
+      menu_hdl = init(fig);
13
+      return;
14
+   end
15
+
16
+   menu_hdl = [];
17
+
18
+   switch fig
19
+   case 'interp'
20
+      if nargin > 1
21
+         fig = varargin{1};
22
+      else
23
+         fig = gcbf;
24
+      end
25
+
26
+      nii_menu = getappdata(fig, 'nii_menu');
27
+      interp_on_state = get(nii_menu.Minterp,'Userdata');
28
+
29
+      if (interp_on_state == 1)
30
+         opt.useinterp = 1;
31
+         view_nii(fig,opt);
32
+         set(nii_menu.Minterp,'Userdata',0,'Label','Interp off');
33
+         reset_zoom(fig);
34
+      else
35
+         opt.useinterp = 0;
36
+         view_nii(fig,opt);
37
+         set(nii_menu.Minterp,'Userdata',1,'Label','Interp on');
38
+         reset_zoom(fig);
39
+      end
40
+   case 'reset_zoom'
41
+      if nargin > 1
42
+         fig = varargin{1};
43
+      else
44
+         fig = gcbf;
45
+      end
46
+
47
+      reset_zoom(fig);
48
+   case 'orient'
49
+      orient;
50
+   case 'img_info'
51
+      img_info;
52
+   case 'save_disp'
53
+      save_disp;
54
+   end
55
+
56
+   return					% view_nii_menu
57
+
58
+
59
+%--------------------------------------------------------------------
60
+function menu_hdl = init(fig)
61
+
62
+   %  search for edit, view menu
63
+   %
64
+   nii_menu.Mfile = [];
65
+   nii_menu.Medit = [];
66
+   nii_menu.Mview = [];
67
+   menuitems = findobj(fig, 'type', 'uimenu');
68
+
69
+   for i=1:length(menuitems)
70
+      filelabel = get(menuitems(i),'label');
71
+
72
+      if strcmpi(strrep(filelabel, '&', ''), 'file')
73
+         nii_menu.Mfile = menuitems(i);
74
+      end
75
+
76
+      editlabel = get(menuitems(i),'label');
77
+
78
+      if strcmpi(strrep(editlabel, '&', ''), 'edit')
79
+         nii_menu.Medit = menuitems(i);
80
+      end
81
+
82
+      viewlabel = get(menuitems(i),'label');
83
+
84
+      if strcmpi(strrep(viewlabel, '&', ''), 'view')
85
+         nii_menu.Mview = menuitems(i);
86
+      end
87
+   end
88
+
89
+   set(fig, 'menubar', 'none');
90
+
91
+   if isempty(nii_menu.Mfile)
92
+      nii_menu.Mfile = uimenu('Parent',fig, ...
93
+   	   'Label','File');
94
+
95
+      nii_menu.Mfile_save = uimenu('Parent',nii_menu.Mfile, ...
96
+   	   'Label','Save displayed image as ...', ...
97
+           'Callback','view_nii_menu(''save_disp'');');
98
+   else
99
+      nii_menu.Mfile_save = uimenu('Parent',nii_menu.Mfile, ...
100
+   	   'Label','Save displayed image as ...', ...
101
+           'separator','on', ...
102
+           'Callback','view_nii_menu(''save_disp'');');
103
+   end
104
+
105
+   if isempty(nii_menu.Medit)
106
+      nii_menu.Medit = uimenu('Parent',fig, ...
107
+   	   'Label','Edit');
108
+
109
+      nii_menu.Medit_orient = uimenu('Parent',nii_menu.Medit, ...
110
+   	   'Label','Convert to RAS orientation', ...
111
+           'Callback','view_nii_menu(''orient'');');
112
+   else
113
+      nii_menu.Medit_orient = uimenu('Parent',nii_menu.Medit, ...
114
+   	   'Label','Convert to RAS orientation', ...
115
+           'separator','on', ...
116
+           'Callback','view_nii_menu(''orient'');');
117
+   end
118
+
119
+   if isempty(nii_menu.Mview)
120
+      nii_menu.Mview = uimenu('Parent',fig, ...
121
+   	   'Label','View');
122
+
123
+      nii_menu.Mview_info = uimenu('Parent',nii_menu.Mview, ...
124
+   	   'Label','Image Information', ...
125
+           'Callback','view_nii_menu(''img_info'');');
126
+   else
127
+      nii_menu.Mview_info = uimenu('Parent',nii_menu.Mview, ...
128
+   	   'Label','Image Information', ...
129
+           'separator','on', ...
130
+           'Callback','view_nii_menu(''img_info'');');
131
+   end
132
+
133
+   nii_menu.Mzoom = rri_zoom_menu(fig);
134
+
135
+   nii_menu.Minterp = uimenu('Parent',fig, ...
136
+   	   'Label','Interp on', ...
137
+	   'Userdata', 1, ...
138
+           'Callback','view_nii_menu(''interp'');');
139
+
140
+   setappdata(fig,'nii_menu',nii_menu);
141
+   menu_hdl = nii_menu.Minterp;
142
+
143
+   return					% init
144
+
145
+
146
+%----------------------------------------------------------------
147
+function reset_zoom(fig)
148
+
149
+   old_handle_vis = get(fig, 'HandleVisibility');
150
+   set(fig, 'HandleVisibility', 'on');
151
+
152
+   nii_view = getappdata(fig, 'nii_view');
153
+   nii_menu = getappdata(fig, 'nii_menu');
154
+
155
+   set(nii_menu.Mzoom,'Userdata',1,'Label','Zoom on');
156
+   set(fig,'pointer','arrow');
157
+   zoom off;
158
+
159
+   axes(nii_view.handles.axial_axes);
160
+   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
161
+			[get(gca, 'xlim') get(gca, 'ylim')])
162
+%   zoom reset;
163
+ %  zoom getlimits;
164
+   zoom out;
165
+
166
+   axes(nii_view.handles.coronal_axes);
167
+   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
168
+			[get(gca, 'xlim') get(gca, 'ylim')])
169
+%   zoom reset;
170
+ %  zoom getlimits;
171
+   zoom out;
172
+
173
+   axes(nii_view.handles.sagittal_axes);
174
+   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
175
+			[get(gca, 'xlim') get(gca, 'ylim')])
176
+%   zoom reset;
177
+ %  zoom getlimits;
178
+   zoom out;
179
+
180
+   set(fig, 'HandleVisibility', old_handle_vis);
181
+
182
+   return;					% reset_zoom
183
+
184
+
185
+%----------------------------------------------------------------
186
+function img_info
187
+
188
+   nii_view = getappdata(gcbf, 'nii_view');
189
+   hdr = nii_view.nii.hdr;
190
+
191
+   max_value = num2str(double(max(nii_view.nii.img(:))));
192
+   min_value = num2str(double(min(nii_view.nii.img(:))));
193
+
194
+   dim = sprintf('%d  %d  %d', double(hdr.dime.dim(2:4)));
195
+   vox = sprintf('%.3f  %.3f  %.3f', double(hdr.dime.pixdim(2:4)));
196
+
197
+   if double(hdr.dime.datatype) == 1
198
+      type = '1-bit binary';
199
+   elseif double(hdr.dime.datatype) == 2
200
+      type = '8-bit unsigned integer';
201
+   elseif double(hdr.dime.datatype) == 4
202
+      type = '16-bit signed integer';
203
+   elseif double(hdr.dime.datatype) == 8
204
+      type = '32-bit signed integer';
205
+   elseif double(hdr.dime.datatype) == 16
206
+      type = '32-bit single float';
207
+   elseif double(hdr.dime.datatype) == 64
208
+      type = '64-bit double precision';
209
+   elseif double(hdr.dime.datatype) == 128
210
+      type = '24-bit RGB true color';
211
+   elseif double(hdr.dime.datatype) == 256
212
+      type = '8-bit signed integer';
213
+   elseif double(hdr.dime.datatype) == 511
214
+      type = '96-bit RGB true color';
215
+   elseif double(hdr.dime.datatype) == 512
216
+      type = '16-bit unsigned integer';
217
+   elseif double(hdr.dime.datatype) == 768
218
+      type = '32-bit unsigned integer';
219
+   elseif double(hdr.dime.datatype) == 1024
220
+      type = '64-bit signed integer';
221
+   elseif double(hdr.dime.datatype) == 1280
222
+      type = '64-bit unsigned integer';
223
+   end
224
+
225
+   msg = {};
226
+   msg = [msg {''}];
227
+   msg = [msg {['Dimension:  [', dim, ']']}];
228
+   msg = [msg {''}];
229
+   msg = [msg {['Voxel Size:  [', vox, ']']}];
230
+   msg = [msg {''}];
231
+   msg = [msg {['Data Type:  [', type, ']']}];
232
+   msg = [msg {''}];
233
+   msg = [msg {['Max Value:  [', max_value, ']']}];
234
+   msg = [msg {''}];
235
+   msg = [msg {['Min Value:  [', min_value, ']']}];
236
+   msg = [msg {''}];
237
+
238
+   if isfield(nii_view.nii, 'fileprefix')
239
+      if isfield(nii_view.nii, 'filetype') & nii_view.nii.filetype == 2
240
+         msg = [msg {['File Name:  [', nii_view.nii.fileprefix, '.nii]']}];
241
+         msg = [msg {''}];
242
+      elseif isfield(nii_view.nii, 'filetype')
243
+         msg = [msg {['File Name:  [', nii_view.nii.fileprefix, '.img]']}];
244
+         msg = [msg {''}];
245
+      else
246
+         msg = [msg {['File Prefix:  [', nii_view.nii.fileprefix, ']']}];
247
+         msg = [msg {''}];
248
+      end
249
+   end
250
+
251
+   h = msgbox(msg, 'Image Information', 'modal');
252
+   set(h,'color',[1 1 1]);
253
+
254
+   return;					% img_info
255
+
256
+
257
+%----------------------------------------------------------------
258
+function orient
259
+
260
+   fig = gcbf;
261
+   nii_view = getappdata(fig, 'nii_view');
262
+   nii = nii_view.nii;
263
+
264
+   old_pointer = get(fig,'Pointer');
265
+   set(fig,'Pointer','watch');
266
+
267
+   [nii orient] = rri_orient(nii);
268
+
269
+   if isequal(orient, [1 2 3])		% do nothing
270
+      set(fig,'Pointer',old_pointer);
271
+      return;
272
+   end
273
+
274
+   oldopt = view_nii(fig);
275
+   opt.setarea = oldopt.area;
276
+   opt.usecolorbar = oldopt.usecolorbar;
277
+   opt.usecrosshair = oldopt.usecrosshair;
278
+   opt.usestretch = oldopt.usestretch;
279
+   opt.useimagesc = oldopt.useimagesc;
280
+   opt.useinterp = oldopt.useinterp;
281
+   opt.command = 'updatenii';
282
+
283
+   view_nii(fig, nii, opt);
284
+   set(fig,'Pointer',old_pointer);
285
+   reset_zoom(fig);
286
+
287
+   return;					% orient
288
+
289
+
290
+%----------------------------------------------------------------
291
+function save_disp
292
+
293
+   [filename pathname] = uiputfile('*.*', 'Save displayed image as (*.nii or *.img)');
294
+
295
+   if isequal(filename,0) | isequal(pathname,0)
296
+      return;
297
+   else
298
+      out_imgfile = fullfile(pathname, filename);	% original image file
299
+   end
300
+
301
+   old_pointer = get(gcbf,'Pointer');
302
+   set(gcbf,'Pointer','watch');
303
+
304
+   nii_view = getappdata(gcbf, 'nii_view');
305
+   nii = nii_view.nii;
306
+
307
+   try
308
+      save_nii(nii, out_imgfile);
309
+   catch
310
+      msg = 'File can not be saved.';
311
+      msgbox(msg, 'File write error', 'modal');
312
+   end
313
+
314
+   set(gcbf,'Pointer',old_pointer);
315
+
316
+   return;					% save_disp
317
+
... ...
@@ -0,0 +1,488 @@
1
+%  internal function
2
+
3
+%  'xform_nii.m' is an internal function called by "load_nii.m", so
4
+%  you do not need run this program by yourself. It does simplified
5
+%  NIfTI sform/qform affine transform, and supports some of the 
6
+%  affine transforms, including translation, reflection, and 
7
+%  orthogonal rotation (N*90 degree).
8
+%
9
+%  For other affine transforms, e.g. any degree rotation, shearing
10
+%  etc. you will have to use the included 'reslice_nii.m' program
11
+%  to reslice the image volume. 'reslice_nii.m' is not called by
12
+%  any other program, and you have to run 'reslice_nii.m' explicitly
13
+%  for those NIfTI files that you want to reslice them.
14
+%
15
+%  Since 'xform_nii.m' does not involve any interpolation or any
16
+%  slice change, the original image volume is supposed to be
17
+%  untouched, although it is translated, reflected, or even 
18
+%  orthogonally rotated, based on the affine matrix in the
19
+%  NIfTI header.
20
+%
21
+%  However, the affine matrix in the header of a lot NIfTI files
22
+%  contain slightly non-orthogonal rotation. Therefore, optional
23
+%  input parameter 'tolerance' is used to allow some distortion
24
+%  in the loaded image for any non-orthogonal rotation or shearing
25
+%  of NIfTI affine matrix. If you set 'tolerance' to 0, it means
26
+%  that you do not allow any distortion. If you set 'tolerance' to
27
+%  1, it means that you do not care any distortion. The image will
28
+%  fail to be loaded if it can not be tolerated. The tolerance will
29
+%  be set to 0.1 (10%), if it is default or empty.
30
+%
31
+%  Because 'reslice_nii.m' has to perform 3D interpolation, it can
32
+%  be slow depending on image size and affine matrix in the header.
33
+%  
34
+%  After you perform the affine transform, the 'nii' structure
35
+%  generated from 'xform_nii.m' or new NIfTI file created from
36
+%  'reslice_nii.m' will be in RAS orientation, i.e. X axis from
37
+%  Left to Right, Y axis from Posterior to Anterior, and Z axis
38
+%  from Inferior to Superior.
39
+%
40
+%  NOTE: This function should be called immediately after load_nii.
41
+%  
42
+%  Usage: [ nii ] = xform_nii(nii, [tolerance], [preferredForm])
43
+%  
44
+%  nii	- NIFTI structure (returned from load_nii)
45
+%
46
+%  tolerance (optional) - distortion allowed for non-orthogonal rotation
47
+%	or shearing in NIfTI affine matrix. It will be set to 0.1 (10%),
48
+%	if it is default or empty.
49
+%
50
+%  preferredForm (optional)  -  selects which transformation from voxels
51
+%	to RAS coordinates; values are s,q,S,Q.  Lower case s,q indicate
52
+%	"prefer sform or qform, but use others if preferred not present". 
53
+%	Upper case indicate the program is forced to use the specificied
54
+%	tranform or fail loading.  'preferredForm' will be 's', if it is
55
+%	default or empty.	- Jeff Gunter
56
+%  
57
+%  NIFTI data format can be found on: http://nifti.nimh.nih.gov
58
+%
59
+%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
60
+%
61
+function nii = xform_nii(nii, tolerance, preferredForm)
62
+
63
+   %  save a copy of the header as it was loaded.  This is the
64
+   %  header before any sform, qform manipulation is done.
65
+   %
66
+   nii.original.hdr = nii.hdr;
67
+
68
+   if ~exist('tolerance','var') | isempty(tolerance)
69
+      tolerance = 0.1;
70
+   elseif(tolerance<=0)
71
+      tolerance = eps;
72
+   end
73
+
74
+   if ~exist('preferredForm','var') | isempty(preferredForm)
75
+      preferredForm= 's';				% Jeff
76
+   end
77
+
78
+   %  if scl_slope field is nonzero, then each voxel value in the
79
+   %  dataset should be scaled as: y = scl_slope * x + scl_inter
80
+   %  I bring it here because hdr will be modified by change_hdr.
81
+   %
82
+   if nii.hdr.dime.scl_slope ~= 0 & ...
83
+	ismember(nii.hdr.dime.datatype, [2,4,8,16,64,256,512,768]) & ...
84
+	(nii.hdr.dime.scl_slope ~= 1 | nii.hdr.dime.scl_inter ~= 0)
85
+
86
+      nii.img = ...
87
+	nii.hdr.dime.scl_slope * double(nii.img) + nii.hdr.dime.scl_inter;
88
+
89
+      if nii.hdr.dime.datatype == 64
90
+
91
+         nii.hdr.dime.datatype = 64;
92
+         nii.hdr.dime.bitpix = 64;
93
+      else
94
+         nii.img = single(nii.img);
95
+
96
+         nii.hdr.dime.datatype = 16;
97
+         nii.hdr.dime.bitpix = 32;
98
+      end
99
+
100
+      nii.hdr.dime.glmax = max(double(nii.img(:)));
101
+      nii.hdr.dime.glmin = min(double(nii.img(:)));
102
+
103
+      %  set scale to non-use, because it is applied in xform_nii
104
+      %
105
+      nii.hdr.dime.scl_slope = 0;
106
+
107
+   end
108
+
109
+   %  However, the scaling is to be ignored if datatype is DT_RGB24.
110
+
111
+   %  If datatype is a complex type, then the scaling is to be applied
112
+   %  to both the real and imaginary parts.
113
+   %
114
+   if nii.hdr.dime.scl_slope ~= 0 & ...
115
+	ismember(nii.hdr.dime.datatype, [32,1792])
116
+
117
+      nii.img = ...
118
+	nii.hdr.dime.scl_slope * double(nii.img) + nii.hdr.dime.scl_inter;
119
+
120
+      if nii.hdr.dime.datatype == 32
121
+         nii.img = single(nii.img);
122
+      end
123
+
124
+      nii.hdr.dime.glmax = max(double(nii.img(:)));
125
+      nii.hdr.dime.glmin = min(double(nii.img(:)));
126
+
127
+      %  set scale to non-use, because it is applied in xform_nii
128
+      %
129
+      nii.hdr.dime.scl_slope = 0;
130
+
131
+   end
132
+
133
+   %  There is no need for this program to transform Analyze data
134
+   %
135
+   if nii.filetype == 0 & exist([nii.fileprefix '.mat'],'file')
136
+      load([nii.fileprefix '.mat']);	% old SPM affine matrix
137
+      R=M(1:3,1:3);
138
+      T=M(1:3,4);
139
+      T=R*ones(3,1)+T;
140
+      M(1:3,4)=T;
141
+      nii.hdr.hist.qform_code=0;
142
+      nii.hdr.hist.sform_code=1;
143
+      nii.hdr.hist.srow_x=M(1,:);
144
+      nii.hdr.hist.srow_y=M(2,:);
145
+      nii.hdr.hist.srow_z=M(3,:);
146
+   elseif nii.filetype == 0
147
+      nii.hdr.hist.rot_orient = [];
148
+      nii.hdr.hist.flip_orient = [];
149
+      return;				% no sform/qform for Analyze format
150
+   end
151
+
152
+   hdr = nii.hdr;
153
+
154
+   [hdr,orient]=change_hdr(hdr,tolerance,preferredForm);
155
+
156
+   %  flip and/or rotate image data
157
+   %
158
+   if ~isequal(orient, [1 2 3])
159
+
160
+      old_dim = hdr.dime.dim([2:4]);
161
+
162
+      %  More than 1 time frame
163
+      %
164
+      if ndims(nii.img) > 3
165
+         pattern = 1:prod(old_dim);
166
+      else
167
+         pattern = [];
168
+      end
169
+
170
+      if ~isempty(pattern)
171
+         pattern = reshape(pattern, old_dim);
172
+      end
173
+
174
+      %  calculate for rotation after flip
175
+      %
176
+      rot_orient = mod(orient + 2, 3) + 1;
177
+
178
+      %  do flip:
179
+      %
180
+      flip_orient = orient - rot_orient;
181
+
182
+      for i = 1:3
183
+         if flip_orient(i)
184
+            if ~isempty(pattern)
185
+               pattern = flipdim(pattern, i);
186
+            else
187
+               nii.img = flipdim(nii.img, i);
188
+            end
189
+         end
190
+      end
191
+
192
+      %  get index of orient (rotate inversely)
193
+      %
194
+      [tmp rot_orient] = sort(rot_orient);
195
+
196
+      new_dim = old_dim;
197
+      new_dim = new_dim(rot_orient);
198
+      hdr.dime.dim([2:4]) = new_dim;
199
+
200
+      new_pixdim = hdr.dime.pixdim([2:4]);
201
+      new_pixdim = new_pixdim(rot_orient);
202
+      hdr.dime.pixdim([2:4]) = new_pixdim;
203
+
204
+      %  re-calculate originator
205
+      %
206
+      tmp = hdr.hist.originator([1:3]);
207
+      tmp = tmp(rot_orient);
208
+      flip_orient = flip_orient(rot_orient);
209
+
210
+      for i = 1:3
211
+         if flip_orient(i) & ~isequal(tmp(i), 0)
212
+            tmp(i) = new_dim(i) - tmp(i) + 1;
213
+         end
214
+      end
215
+
216
+      hdr.hist.originator([1:3]) = tmp;
217
+      hdr.hist.rot_orient = rot_orient;
218
+      hdr.hist.flip_orient = flip_orient;
219
+
220
+      %  do rotation:
221
+      %
222
+      if ~isempty(pattern)
223
+         pattern = permute(pattern, rot_orient);
224
+         pattern = pattern(:);
225
+
226
+         nii.img = reshape(nii.img, [prod(new_dim) hdr.dime.dim(5:8)]);
227
+         nii.img = nii.img(pattern, :);
228
+         nii.img = reshape(nii.img, [new_dim       hdr.dime.dim(5:8)]);
229
+      else
230
+         nii.img = permute(nii.img, rot_orient);
231
+      end
232
+   else
233
+      hdr.hist.rot_orient = [];
234
+      hdr.hist.flip_orient = [];
235
+   end
236
+
237
+   nii.hdr = hdr;
238
+
239
+   return;					% xform_nii
240
+
241
+
242
+%-----------------------------------------------------------------------
243
+function [hdr, orient] = change_hdr(hdr, tolerance, preferredForm)
244
+
245
+   orient = [1 2 3];
246
+   affine_transform = 1;
247
+
248
+   %  NIFTI can have both sform and qform transform. This program
249
+   %  will check sform_code prior to qform_code by default.
250
+   %
251
+   %  If user specifys "preferredForm", user can then choose the
252
+   %  priority.					- Jeff
253
+   %
254
+   useForm=[];					% Jeff
255
+
256
+   if isequal(preferredForm,'S')
257
+       if isequal(hdr.hist.sform_code,0)
258
+           error('User requires sform, sform not set in header');
259
+       else
260
+           useForm='s';
261
+       end
262
+   end						% Jeff
263
+
264
+   if isequal(preferredForm,'Q')
265
+       if isequal(hdr.hist.qform_code,0)
266
+           error('User requires qform, qform not set in header');
267
+       else
268
+           useForm='q';
269
+       end
270
+   end						% Jeff
271
+
272
+   if isequal(preferredForm,'s')
273
+       if hdr.hist.sform_code > 0
274
+           useForm='s';
275
+       elseif hdr.hist.qform_code > 0
276
+           useForm='q';
277
+       end
278
+   end						% Jeff
279
+   
280
+   if isequal(preferredForm,'q')
281
+       if hdr.hist.qform_code > 0
282
+           useForm='q';
283
+       elseif hdr.hist.sform_code > 0
284
+           useForm='s';
285
+       end
286
+   end						% Jeff
287
+
288
+   if isequal(useForm,'s')
289
+      R = [hdr.hist.srow_x(1:3)
290
+           hdr.hist.srow_y(1:3)
291
+           hdr.hist.srow_z(1:3)];
292
+
293
+      T = [hdr.hist.srow_x(4)
294
+           hdr.hist.srow_y(4)
295
+           hdr.hist.srow_z(4)];
296
+
297
+      if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
298
+         hdr.hist.old_affine = [ [R;[0 0 0]] [T;1] ];
299
+         R_sort = sort(abs(R(:)));
300
+         R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0;
301
+         hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ];
302
+
303
+         if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
304
+            msg = [char(10) char(10) '   Non-orthogonal rotation or shearing '];
305
+            msg = [msg 'found inside the affine matrix' char(10)];
306
+            msg = [msg '   in this NIfTI file. You have 3 options:' char(10) char(10)];
307
+            msg = [msg '   1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)];
308
+            msg = [msg '      file. I strongly recommand this, because it will not cause' char(10)];
309
+            msg = [msg '      negative effect, as long as you remember not to do slice' char(10)];
310
+            msg = [msg '      time correction after using ''reslice_nii.m''.' char(10) char(10)];
311
+            msg = [msg '   2. Using included ''load_untouch_nii.m'' program to load image' char(10)];
312
+            msg = [msg '      without applying any affine geometric transformation or' char(10)];
313
+            msg = [msg '      voxel intensity scaling. This is only for people who want' char(10)];
314
+            msg = [msg '      to do some image processing regardless of image orientation' char(10)];
315
+            msg = [msg '      and to save data back with the same NIfTI header.' char(10) char(10)];
316
+            msg = [msg '   3. Increasing the tolerance to allow more distortion in loaded' char(10)];
317
+            msg = [msg '      image, but I don''t suggest this.' char(10) char(10)];
318
+            msg = [msg '   To get help, please type:' char(10) char(10) '   help reslice_nii.m' char(10)];
319
+            msg = [msg '   help load_untouch_nii.m' char(10) '   help load_nii.m'];
320
+            error(msg);
321
+         end
322
+      end
323
+
324
+   elseif isequal(useForm,'q')
325
+      b = hdr.hist.quatern_b;
326
+      c = hdr.hist.quatern_c;
327
+      d = hdr.hist.quatern_d;
328
+
329
+      if 1.0-(b*b+c*c+d*d) < 0
330
+         if abs(1.0-(b*b+c*c+d*d)) < 1e-5
331
+            a = 0;
332
+         else
333
+            error('Incorrect quaternion values in this NIFTI data.');
334
+         end
335
+      else
336
+         a = sqrt(1.0-(b*b+c*c+d*d));
337
+      end
338
+
339
+      qfac = hdr.dime.pixdim(1);
340
+      i = hdr.dime.pixdim(2);
341
+      j = hdr.dime.pixdim(3);
342
+      k = qfac * hdr.dime.pixdim(4);
343
+
344
+      R = [a*a+b*b-c*c-d*d     2*b*c-2*a*d        2*b*d+2*a*c
345
+           2*b*c+2*a*d         a*a+c*c-b*b-d*d    2*c*d-2*a*b
346
+           2*b*d-2*a*c         2*c*d+2*a*b        a*a+d*d-c*c-b*b];
347
+
348
+      T = [hdr.hist.qoffset_x
349
+           hdr.hist.qoffset_y
350
+           hdr.hist.qoffset_z];
351
+
352
+      %  qforms are expected to generate rotation matrices R which are
353
+      %  det(R) = 1; we'll make sure that happens.
354
+      %  
355
+      %  now we make the same checks as were done above for sform data
356
+      %  BUT we do it on a transform that is in terms of voxels not mm;
357
+      %  after we figure out the angles and squash them to closest 
358
+      %  rectilinear direction. After that, the voxel sizes are then
359
+      %  added.
360
+      %
361
+      %  This part is modified by Jeff Gunter.
362
+      %
363
+      if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
364
+
365
+         %  det(R) == 0 is not a common trigger for this ---
366
+         %  R(find(R)) is a list of non-zero elements in R; if that
367
+         %  is straight (not oblique) then it should be the same as 
368
+         %  columnwise summation. Could just as well have checked the
369
+         %  lengths of R(find(R)) and sum(R)' (which should be 3)
370
+         %
371
+         hdr.hist.old_affine = [ [R * diag([i j k]);[0 0 0]] [T;1] ];
372
+         R_sort = sort(abs(R(:)));
373
+         R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0;
374
+         R = R * diag([i j k]);
375
+         hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ];
376
+
377
+         if det(R) == 0 | ~isequal(R(find(R)), sum(R)')
378
+            msg = [char(10) char(10) '   Non-orthogonal rotation or shearing '];
379
+            msg = [msg 'found inside the affine matrix' char(10)];
380
+            msg = [msg '   in this NIfTI file. You have 3 options:' char(10) char(10)];
381
+            msg = [msg '   1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)];
382
+            msg = [msg '      file. I strongly recommand this, because it will not cause' char(10)];
383
+            msg = [msg '      negative effect, as long as you remember not to do slice' char(10)];
384
+            msg = [msg '      time correction after using ''reslice_nii.m''.' char(10) char(10)];
385
+            msg = [msg '   2. Using included ''load_untouch_nii.m'' program to load image' char(10)];
386
+            msg = [msg '      without applying any affine geometric transformation or' char(10)];
387
+            msg = [msg '      voxel intensity scaling. This is only for people who want' char(10)];
388
+            msg = [msg '      to do some image processing regardless of image orientation' char(10)];
389
+            msg = [msg '      and to save data back with the same NIfTI header.' char(10) char(10)];
390
+            msg = [msg '   3. Increasing the tolerance to allow more distortion in loaded' char(10)];
391
+            msg = [msg '      image, but I don''t suggest this.' char(10) char(10)];
392
+            msg = [msg '   To get help, please type:' char(10) char(10) '   help reslice_nii.m' char(10)];
393
+            msg = [msg '   help load_untouch_nii.m' char(10) '   help load_nii.m'];
394
+            error(msg);
395
+         end
396
+
397
+      else
398
+         R = R * diag([i j k]);
399
+      end					% 1st det(R)
400
+
401
+   else
402
+      affine_transform = 0;	% no sform or qform transform
403
+   end
404
+
405
+   if affine_transform == 1
406
+      voxel_size = abs(sum(R,1));
407
+      inv_R = inv(R);
408
+      originator = inv_R*(-T)+1;
409
+      orient = get_orient(inv_R);
410
+
411
+      %  modify pixdim and originator
412
+      %
413
+      hdr.dime.pixdim(2:4) = voxel_size;
414
+      hdr.hist.originator(1:3) = originator;
415
+
416
+      %  set sform or qform to non-use, because they have been
417
+      %  applied in xform_nii
418
+      %
419
+      hdr.hist.qform_code = 0;
420
+      hdr.hist.sform_code = 0;
421
+   end
422
+
423
+   %  apply space_unit to pixdim if not 1 (mm)
424
+   %
425
+   space_unit = get_units(hdr);
426
+
427
+   if space_unit ~= 1
428
+      hdr.dime.pixdim(2:4) = hdr.dime.pixdim(2:4) * space_unit;
429
+
430
+      %  set space_unit of xyzt_units to millimeter, because
431
+      %  voxel_size has been re-scaled
432
+      %
433
+      hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,1,0));
434
+      hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,2,1));
435
+      hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,3,0));
436
+   end
437
+
438
+   return;					% change_hdr
439
+
440
+
441
+%-----------------------------------------------------------------------
442
+function orient = get_orient(R)
443
+
444
+   orient = [];
445
+
446
+   for i = 1:3
447
+      switch find(R(i,:)) * sign(sum(R(i,:)))
448
+      case 1
449
+         orient = [orient 1];		% Left to Right
450
+      case 2
451
+         orient = [orient 2];		% Posterior to Anterior
452
+      case 3
453
+         orient = [orient 3];		% Inferior to Superior
454
+      case -1
455
+         orient = [orient 4];		% Right to Left
456
+      case -2
457
+         orient = [orient 5];		% Anterior to Posterior
458
+      case -3
459
+         orient = [orient 6];		% Superior to Inferior
460
+      end
461
+   end
462
+
463
+   return;					% get_orient
464
+
465
+
466
+%-----------------------------------------------------------------------
467
+function [space_unit, time_unit] = get_units(hdr)
468
+
469
+   switch bitand(hdr.dime.xyzt_units, 7)	% mask with 0x07
470
+   case 1
471
+      space_unit = 1e+3;		% meter, m
472
+   case 3
473
+      space_unit = 1e-3;		% micrometer, um
474
+   otherwise
475
+      space_unit = 1;			% millimeter, mm
476
+   end
477
+
478
+   switch bitand(hdr.dime.xyzt_units, 56)	% mask with 0x38
479
+   case 16
480
+      time_unit = 1e-3;			% millisecond, ms
481
+   case 24
482
+      time_unit = 1e-6;			% microsecond, us
483
+   otherwise
484
+      time_unit = 1;			% second, s
485
+   end
486
+
487
+   return;					% get_units
488
+
... ...
@@ -0,0 +1,28 @@
1
+function sphere = fbs_buildSphere(mapping,center,radius,vdim)
2
+iVoxel = 1;
3
+% returns the IDs within Sphere
4
+coord = mapping.indexToCoordMap.get(center);
5
+
6
+vxrad = ceil((radius*ones(1,3))./(ones(1,1)*vdim))';
7
+
8
+[x y z] = ndgrid(-vxrad(1,iVoxel):sign(vdim(1)):vxrad(1,iVoxel), ...
9
+    -vxrad(2,iVoxel):sign(vdim(2)):vxrad(2,iVoxel), ...
10
+    -vxrad(3,iVoxel):sign(vdim(3)):vxrad(3,iVoxel));
11
+sel = (x./vxrad(1,iVoxel)).^2 + (y./vxrad(2,iVoxel)).^2 + ...
12
+    (z./vxrad(3,iVoxel)).^2 <= 1;
13
+
14
+x = coord(1,1)+x(sel(:));
15
+y = coord(2,1)+y(sel(:));
16
+z = coord(3,1)+z(sel(:));
17
+
18
+sphere = [];
19
+for iCoord = 1:size(x,1);
20
+       key = java.util.Vector(3,0);
21
+        key.add(0,x(iCoord));
22
+        key.add(1,y(iCoord));
23
+        key.add(2,z(iCoord));
24
+    id = mapping.coordToIndexMap.get(key);
25
+    sphere = [sphere id];
26
+end
27
+
28
+end
0 29
\ No newline at end of file
... ...
@@ -0,0 +1,7 @@
1
+function id = fbs_coordtable_getIndex(table,coord)
2
+if table.containsKey(coord)
3
+    id = table.get(coord);
4
+else
5
+     error('FBS:getLabel:noSuchValue','this Mapping does not contain a Value %d',condition);
6
+end
7
+end
0 8
\ No newline at end of file
... ...
@@ -141,6 +141,8 @@ switch task
141 141
         disp('not implemented')
142 142
     case 'FBS'
143 143
         disp('this method is under high development.')
144
+        fbsargs.svmopts = getSvmArgs(model,1);
145
+        header.svmrnd   = getSvmRnd(model);
144 146
         fbsargs.radius  = getSearchlightRadius(model);
145 147
             runFBSImageMaskMode(header,data,fbsargs);
146 148
         
... ...
@@ -1,4 +1,6 @@
1 1
 function output =  runFBSImageMaskMode(header,subjectdata,fbsargs)
2
+addpath('NIFTI_20090325');
3
+
2 4
 args = header.args;
3 5
 
4 6
 subjects = subjectdata;
... ...
@@ -21,36 +23,47 @@ timePointArgs.eventList     = header.classDef.eventMatrix;
21 23
 timeLineStart  = timeline.frameShiftStart;
22 24
 timeLineEnd    = timeline.frameShiftEnd;
23 25
 
26
+RANDOMIZE_DATAPOINTS = header.svmrnd;
27
+svmopts = fbsargs.svmopts;
28
+
24 29
 disp(sprintf('batch processing  %g subjects.',nSubjects));
25 30
 
26 31
 for s = 1:nSubjects
27
-    
32
+    elapsed = struct; %measure the timing
28 33
     disp(sprintf('processing subject %s.',subjects{s}.name));
29 34
     % load image data
30 35
    
31 36
     disp('fetching volume definitions, please wait');
37
+    tic;
32 38
     volumes = spm_vol(getImageFileList(subjects{s}.dir,sessionlist,args.mask));
33
-
39
+    elapsed.loadList = toc;
34 40
     disp('computing volume values, please wait');
35
-    
41
+    tic 
36 42
     [extr x y z] = calculateRoiImageData(volumes,subjects{s}.roiFile);
43
+    elapsed.calcExtr = toc;
37 44
     
38 45
 clear volumes; %save memory ??
39 46
 disp('cleared volumes');
40
-
47
+tic
41 48
     
42 49
     nVoxel = size(extr(1).dat,1);
43 50
 
44 51
     indexToCoordMap = java.util.HashMap;
45 52
     coordToIndexMap = java.util.HashMap;
46 53
     for iVoxel = 1:nVoxel
47
-        coord = [x(iVoxel),y(iVoxel),z(iVoxel)];
54
+        coord = [x(iVoxel) y(iVoxel) z(iVoxel)];
55
+        a = java.util.Vector(3,0);
56
+        a.add(0,coord(1));
57
+        a.add(1,coord(2));
58
+        a.add(2,coord(3));
48 59
         indexToCoordMap.put(iVoxel,coord);
49
-        coordToIndexMap.put(coord,iVoxel);
60
+        coordToIndexMap.put(a,iVoxel);
50 61
     end
51 62
     
52
-    subjects{s}.indexToCoordMap = indexToCoordMap;
53
-    subjects{s}.coordToIndexMap = coordToIndexMap;
63
+    mapping.indexToCoordMap = indexToCoordMap;
64
+    mapping.coordToIndexMap = coordToIndexMap;
65
+
66
+    elapsed.mapping = toc;
54 67
     
55 68
     % calculate psth
56 69
     
... ...
@@ -58,6 +71,7 @@ disp('cleared volumes');
58 71
     pstopts.des = subjects{s}.des;
59 72
 
60 73
     disp(sprintf('computing psth for %g voxel.',nVoxel));
74
+tic 
61 75
 
62 76
     for iVoxel = 1:nVoxel
63 77
         rawdata = [];
... ...
@@ -73,49 +87,74 @@ disp('cleared volumes');
73 87
              sprintf(' %g%%\t complete',p);
74 88
          end
75 89
     end
90
+elapsed.psth = toc;
76 91
     disp('psth done');
77 92
     warning(warn);
93
+    clear extr;
78 94
     %run searchlight
79
-    
80
-
95
+tic
81 96
     
82 97
     display(sprintf('rastering %g coordinates with approx. %g mm radius',nVoxel,radius));
83 98
     % for each timeslice
84
-
85
-    for index = 1:timeLineEnd-timeLineStart+1
86
-        timeShift = index;
99
+    globalStart = timeline.psthStart;
100
+    globalEnd = timeline.psthEnd;
101
+    decodeDuration = timeline.decodeDuration;
102
+    labelMap = timePointArgs.labelMap;
103
+    eventList = pstopts.eventList;
104
+    
105
+    img3D = [];
106
+    % tmp = spm_imatrix(V(kImage).mat); %
107
+    % vdim = tmp(7:9); % Voxel-Size
108
+    vdim = [3,3,3.5];
109
+    
110
+    for timeShift = 1:timeLineEnd-timeLineStart+1
87 111
     % center timepoint && relative shift
88 112
     frameStart  = floor(-globalStart+1+timeShift - 0.5*decodeDuration);
89 113
     frameEnd    = min(ceil(frameStart+decodeDuration + 0.5*decodeDuration),-globalStart+globalEnd);
90 114
 
91
-        
92
-
93 115
         for iVoxel = 1:nVoxel % linear structure avoids 3D-Loop.
94
-            % get coordinate for iVoxel
95
-%             coord = 
96
-            
97
-            % get surrounding coordinates within radius
98
-%             sphere = 
99
-
100
-            % calculate decode performance on these coordinates
101
-            svmdata      = timePointMatrix{index}(:,2:size(timePointMatrix{index},2));
102
-            svmlabel     = timePointMatrix{index}(:,1);
116
+            % get surrounding coordinate-IDs within radius
117
+            sphere = fbs_buildSphere(mapping,iVoxel,radius,vdim);
118
+
119
+            %build svm inputmatrix
120
+            svmdata = [];
121
+            svmlabel = [];
122
+            anyvoxel = 1;
123
+            for pstConditionGroup = 1:size(pst{1,anyvoxel},2)
124
+                for dp = 1:size(pst{1,anyvoxel}{1,pstConditionGroup},1) % data point
125
+                    svmlabel = [svmlabel; lm_getSVMLabel(labelMap,eventList(pstConditionGroup,1))];
126
+                    row = [];
127
+                    for voxel = 1:size(sphere,2)
128
+                        row = [row, pst{1,voxel}{1,pstConditionGroup}(dp,frameStart:frameEnd)]; % label,[value,value,...],[value,value,...]...
129
+                    end
130
+                    svmdata  = [svmdata; row];
131
+                end
132
+            end
103 133
 
104 134
             if RANDOMIZE_DATAPOINTS
105 135
                 rndindex  = randperm(length(svmlabel));
106 136
                 svmdata   = svmdata(rndindex,:);
107 137
                 svmlabel  = svmlabel(rndindex);
108 138
             end
139
+            
109 140
             decode = svm_single_crossval(svmlabel,svmdata,svmopts);
110 141
             % save the decode value to the corresponding coordinate
111
-        end
112 142
 
113
-    display('rastering done');
114
-    % save data for timeslice
143
+            coord= mapping.indexToCoordMap.get(iVoxel);
144
+            img3D(coord',timeShift) = decode;
145
+
146
+        end  %for each voxel
147
+
148
+        nii = make_nii(img3D,vdim,[],16,'decode'); %default origin
149
+        save_nii(nii,sprintf('TESTFILE%g',timeShift));
115 150
     
116 151
     end %for each timeslice
152
+    display('rastering done');
153
+elapsed.decode = toc;
154
+
117 155
 
118 156
     clear pst; %save memory!
157
+assignin('base','timing',elapsed);
119 158
 end
120 159
 
121 160
 end
122 161