|
93 | 93 | if(fseek(fid, hdr.vox_offset, 'bof') ~= 0)
|
94 | 94 | error(['failed to seek to start of data in file ' filename]);
|
95 | 95 | end
|
96 |
| - %always output as float32, maybe add a feature later |
| 96 | + %always convert to float32, maybe add a feature later |
97 | 97 | %use 'cdata' to be compatible with old ciftiopen
|
98 | 98 | max_elems = 128 * 1024 * 1024 / 4; %when reading as float32, use only 128MiB extra memory when reading (or the size of a row, if that manages to be larger)
|
99 |
| - if prod(hdr.dim(6:(hdr.dim(1) + 1))) <= max_elems |
| 99 | + if prod(dims_c) <= max_elems |
100 | 100 | %file is small, use the simple code to read it all in one call
|
101 | 101 | %permute to match ciftiopen: cifti "rows" matching matlab rows
|
102 | 102 | %hack: 3:2 produces empty array, 3:3 produces [3]
|
103 | 103 | outstruct.cdata = permute(do_nifti_scaling(fread_excepting(fid, hdr.dim(6:(hdr.dim(1) + 1)), [intype '=>float32'], filename), hdr), [2 1 3:(hdr.dim(1) - 4)]);
|
104 | 104 | else
|
105 |
| - outstruct.cdata = myzeros(dims_m); %avoid inconsistent 1-dimension handling, allow column vector, default to float32 |
106 |
| - max_rows = max(1, min(hdr.dim(7), floor(max_elems / hdr.dim(6)))); |
107 |
| - switch hdr.dim(1) %dim[0] |
108 |
| - case 6 |
109 |
| - %even out the passes to use about the same memory |
110 |
| - num_passes = ceil(hdr.dim(7) / max_rows); |
111 |
| - chunk_rows = ceil(hdr.dim(7) / num_passes); |
112 |
| - for i = 1:chunk_rows:hdr.dim(7) |
113 |
| - outstruct.cdata(i:min(hdr.dim(7), i + chunk_rows - 1), :) = do_nifti_scaling(fread_excepting(fid, [hdr.dim(6), min(chunk_rows, hdr.dim(7) - i + 1)], [intype '=>float32']), hdr)'; |
| 105 | + %matlab indexing modes can't handle swapping first two dims while doing "some full planes plus a partial plane" per fread() |
| 106 | + %reshape at the end would hit double the memory usage, and we want to avoid that |
| 107 | + %so to avoid slow row-at-a-time loops, two cases: less than a plane, and multiple full planes |
| 108 | + %with implicit third index and implicit flattening on final specified dimension, we can do these generically in a way that should work even for 4D+ (if it is ever supported) |
| 109 | + outstruct.cdata = myzeros(dims_m); |
| 110 | + max_rows = max(1, floor(max_elems / dims_c(1))); |
| 111 | + if max_rows < dims_c(2) %less than a plane at a time, don't read cross-plane |
| 112 | + num_passes = ceil(dims_c(2) / max_rows); %even out the passes |
| 113 | + chunk_rows = ceil(prod(dims_c(2:end)) / num_passes); |
| 114 | + total_planes = prod(dims_c(3:end)); |
| 115 | + for plane = 1:total_planes |
| 116 | + for chunkstart = 1:chunk_rows:dims_c(2) |
| 117 | + outstruct.cdata(chunkstart:min(dims_c(2), chunkstart + chunk_rows - 1), :, plane) = do_nifti_scaling(fread_excepting(fid, [dims_c(1), min(chunk_rows, dims_c(2) - chunkstart + 1)], [intype '=>float32']), hdr)'; |
114 | 118 | end
|
115 |
| - case 7 |
116 |
| - %3D - this is all untested |
117 |
| - if max_rows < hdr.dim(7) |
118 |
| - %keep it simple, chunk each plane independently |
119 |
| - num_passes = ceil(hdr.dim(7) / max_rows); |
120 |
| - chunk_rows = ceil(hdr.dim(7) / num_passes); |
121 |
| - for j = 1:hdr.dim(8) |
122 |
| - for i = 1:chunk_rows:hdr.dim(7) |
123 |
| - outstruct.cdata(i:min(hdr.dim(7), i + chunk_rows - 1), :, j) = do_nifti_scaling(fread_excepting(fid, [hdr.dim(6), min(chunk_rows, hdr.dim(7) - i + 1)], [intype '=>float32']), hdr)'; |
124 |
| - end |
125 |
| - end |
126 |
| - else |
127 |
| - %read multiple full planes per call |
128 |
| - plane_elems = hdr.dim(7) * hdr.dim(6); |
129 |
| - max_planes = max(1, min(hdr.dim(8), floor(max_elems / plane_elems))); |
130 |
| - num_passes = ceil(hdr.dim(8) / max_planes); |
131 |
| - chunk_planes = ceil(hdr.dim(8) / num_passes); |
132 |
| - for j = 1:chunk_planes:hdr.dim(8) |
133 |
| - outstruct.cdata(:, :, j:min(hdr.dim(8), j + chunk_planes - 1)) = permute(do_nifti_scaling(fread_excepting(fid, [hdr.dim(6:7), min(chunk_planes, hdr.dim(8) - j + 1)], [intype '=>float32']), hdr), [2 1 3]); |
134 |
| - end |
135 |
| - end |
136 |
| - otherwise |
137 |
| - %4D and beyond is not in the cifti-2 standard and is treated as an error in sanity_check_cdata |
138 |
| - %but, if it ever is supported, warn and read it the memory-intensive way anyway |
139 |
| - warning('cifti reading for 4 or more dimensions currently peaks at double the memory'); |
140 |
| - outstruct.cdata = permute(do_nifti_scaling(fread_excepting(fid, hdr.dim(6:(hdr.dim(1) + 1)), [intype '=>float32'], filename), hdr), [2 1 3:(hdr.dim(1) - 4)]); |
| 119 | + end |
| 120 | + else |
| 121 | + max_planes = max(1, floor(max_rows / dims_c(2))); %just in case the division does something dumb |
| 122 | + total_planes = prod(dims_c(3:end)); |
| 123 | + num_passes = ceil(total_planes / max_planes); |
| 124 | + chunk_planes = ceil(total_planes / num_passes); |
| 125 | + for chunkstart = 1:chunk_planes:total_planes |
| 126 | + outstruct.cdata(:, :, chunkstart:min(total_planes, chunkstart + chunk_planes - 1)) = permute(do_nifti_scaling(fread_excepting(fid, [dims_c(1:2), min(chunk_planes, total_planes - chunkstart + 1)], [intype '=>float32']), hdr), [2 1 3]); |
| 127 | + end |
141 | 128 | end
|
142 | 129 | end
|
143 | 130 | end
|
|
158 | 145 | outzeros = zeros(dimarray(:)', 'single');
|
159 | 146 | end
|
160 | 147 | end
|
| 148 | + |
0 commit comments